初版gui
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
# App Quickstart
|
||||
|
||||
## Launch
|
||||
|
||||
From MATLAB, open the app with:
|
||||
|
||||
```matlab
|
||||
launch_edfm_simulator_app
|
||||
```
|
||||
|
||||
File:
|
||||
|
||||
- `gui_support/app/launch_edfm_simulator_app.m`
|
||||
|
||||
## Current Scope
|
||||
|
||||
The app currently provides:
|
||||
|
||||
- tab layout by Part
|
||||
- template loading
|
||||
- config import/export as MAT
|
||||
- result import/export as MAT
|
||||
- unified run entry through `run_case(config)`
|
||||
- run log capture
|
||||
- basic result summary and plotting
|
||||
|
||||
## Current Editing Style
|
||||
|
||||
For large arrays and cell data, the app currently uses MATLAB literal text areas.
|
||||
|
||||
Examples:
|
||||
|
||||
- numeric arrays: `[1 2 3]`
|
||||
- matrices: `[1 2; 3 4]`
|
||||
- cell arrays: `{'w1', 1, [1 1 1], 0.089, 0, 1}`
|
||||
|
||||
This keeps the first App Designer style version flexible while the parameter schema is still being stabilized.
|
||||
|
||||
## Notes
|
||||
|
||||
- The flow models are mutually exclusive.
|
||||
- The GUI only uses the active `flow_model` branch at runtime.
|
||||
- The current result page is a first-pass implementation.
|
||||
- The current app class is written in App Designer style (`matlab.apps.AppBase`) as a text `.m` class instead of a binary `.mlapp`.
|
||||
@@ -0,0 +1,90 @@
|
||||
# Case Template Summary
|
||||
|
||||
This file captures the first-pass differences among the 7 existing example cases.
|
||||
The goal is to turn these into GUI presets later instead of keeping 7 separate hard-coded entry scripts.
|
||||
|
||||
## Shared Structure
|
||||
|
||||
All current example `main1.m` scripts follow the same 8-part flow:
|
||||
|
||||
1. model selection
|
||||
2. matrix grid definition
|
||||
3. fracture input
|
||||
4. discretization
|
||||
5. flow model and initial state
|
||||
6. well and schedule
|
||||
7. solver setup
|
||||
8. execution
|
||||
|
||||
## Template Summary
|
||||
|
||||
| Case | Folder | Grid | Grid Model | Flow Model | Fracture Wells | Schedule Phases | Notes |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| 1 | `算例1-组分流-不规则非均质计算域` | `20 x 10 x 1` | SP | Multi-component | 1 | 3 | Component transport, surfactant/salt injection |
|
||||
| 2 | `算例2-组分流-无效网格` | `20 x 20 x 3` | SP | Multi-component | 1 | 3 | Similar to case 1, but multi-layer and invalid-grid theme |
|
||||
| 3 | `算例3-单重双重离散裂缝混合模型` | `20 x 10 x 1` | DP | Multi-component | 1 | 3 | Dual-medium setup |
|
||||
| 4 | `算例4-气水两相流-压力导数曲线` | `20 x 10 x 1` | SP | Gas-water | 1 | 5 | Pressure derivative style schedule with very small early timesteps |
|
||||
| 5 | `算例5-油水两相流-注焖采` | `20 x 10 x 1` | SP | Oil-water | 1 | 3 | Injection-soak-production schedule |
|
||||
| 6 | `算例6-油水两相流-直井注压裂水平井采` | `20 x 10 x 2` | SP | Oil-water | 1 | 1 | Contains both conventional wells and fracture well |
|
||||
| 7 | `算例7-油水两相流-不同裂缝制度不同` | `20 x 10 x 1` | SP | Oil-water | 6 | 4 | Multiple fracture-well controls with different stages |
|
||||
|
||||
## Key Template Differences
|
||||
|
||||
### Grid
|
||||
|
||||
- Most cases use `dx = 50 * ones(1, 20)`.
|
||||
- Most cases use `dy = 50 * ones(1, 10)`.
|
||||
- `dz` differs by case:
|
||||
- case 1: 1 layer
|
||||
- case 2: 3 layers
|
||||
- case 3: 1 layer
|
||||
- case 4: 1 layer
|
||||
- case 5: 1 layer
|
||||
- case 6: 2 layers
|
||||
- case 7: 1 layer
|
||||
|
||||
### Discretization
|
||||
|
||||
- Cases 1, 2, 4, 5, 6, 7 use single-medium mode.
|
||||
- Case 3 uses dual-medium mode.
|
||||
|
||||
### Flow Physics
|
||||
|
||||
- Cases 1, 2, 3 use multi-component flow.
|
||||
- Case 4 uses gas-water flow.
|
||||
- Cases 5, 6, 7 use oil-water flow.
|
||||
|
||||
### Wells
|
||||
|
||||
- Cases 1 to 5 mainly define fracture well completions through `welloc`.
|
||||
- Case 6 includes conventional wells in `well1` plus one fracture well in `well2`.
|
||||
- Case 7 splits six fracture locations into six separately controlled fracture wells.
|
||||
|
||||
### Schedule
|
||||
|
||||
- Cases 1, 2, 3: 3-stage schedule
|
||||
- Case 4: 5-stage schedule with aggressive timestep ramping
|
||||
- Case 5: 3-stage schedule
|
||||
- Case 6: 1-stage schedule
|
||||
- Case 7: 4-stage schedule
|
||||
|
||||
## Preset Design Recommendation
|
||||
|
||||
Later, each GUI preset should contain:
|
||||
|
||||
- display name
|
||||
- source folder
|
||||
- default `config`
|
||||
- supported flow model
|
||||
- supported grid model
|
||||
- notes for the result page
|
||||
|
||||
Suggested preset IDs:
|
||||
|
||||
- `case01_multicomponent_irregular`
|
||||
- `case02_multicomponent_invalid_grid`
|
||||
- `case03_multicomponent_dp`
|
||||
- `case04_gas_water_pressure_derivative`
|
||||
- `case05_oil_water_huff_n_puff`
|
||||
- `case06_oil_water_vertical_inj_fractured_horizontal_prod`
|
||||
- `case07_oil_water_multi_fracture_regimes`
|
||||
@@ -0,0 +1,386 @@
|
||||
# GUI Parameter And Run Architecture
|
||||
|
||||
## Decision
|
||||
|
||||
Use MATLAB `struct` as the primary runtime and persistence format.
|
||||
|
||||
Reasons:
|
||||
|
||||
- App Designer works naturally with nested `struct` data.
|
||||
- Existing solver code already expects MATLAB variables and structs, not object models.
|
||||
- `struct` avoids unnecessary conversion while the GUI is being built.
|
||||
- JSON can still be added later as an optional export/import layer.
|
||||
|
||||
Recommended flow:
|
||||
|
||||
1. Load a case template into `config` as a MATLAB struct.
|
||||
2. Let the GUI edit `config`.
|
||||
3. Save or load `config` directly as MATLAB data first.
|
||||
4. Convert `config` into solver inputs through a single entry point later: `run_case(config)`.
|
||||
|
||||
## Unified Config Layout
|
||||
|
||||
The GUI should be built around the following top-level fields:
|
||||
|
||||
```matlab
|
||||
config.meta
|
||||
config.model
|
||||
config.grid
|
||||
config.fracture
|
||||
config.discretization
|
||||
config.flow
|
||||
config.initial
|
||||
config.wells
|
||||
config.schedule
|
||||
config.solver
|
||||
config.output
|
||||
```
|
||||
|
||||
## Part Mapping
|
||||
|
||||
The existing `main1.m` scripts are structurally consistent and map well to the GUI:
|
||||
|
||||
1. `model`: model selection
|
||||
2. `grid`: matrix grid definition
|
||||
3. `fracture`: fracture input and geometry
|
||||
4. `discretization`: SP/DP discretization and medium setup
|
||||
5. `flow` + `initial`: flow model, PVT, relative permeability, initial state
|
||||
6. `wells` + `schedule`: wells, perforations, stage schedule
|
||||
7. `solver`: nonlinear and timestep controls
|
||||
8. `output`: run execution and result presentation
|
||||
|
||||
## Parameter Layers
|
||||
|
||||
The previous inventory mixed together direct inputs and fields created during preprocessing.
|
||||
The GUI should distinguish them explicitly.
|
||||
|
||||
### Layer A: Editable Input Parameters
|
||||
|
||||
These are the parameters the GUI should expose directly or through advanced panels.
|
||||
|
||||
### Layer B: Derived Or Runtime Fields
|
||||
|
||||
These are generated by preprocessing, discretization, solver assembly, or postprocessing.
|
||||
They should usually be displayed or logged, but not edited directly.
|
||||
|
||||
## Core Parameter Inventory
|
||||
|
||||
This is the revised first-pass grouping of parameters already identified in the repository.
|
||||
|
||||
### `meta`
|
||||
|
||||
- `case_name`
|
||||
- `case_id`
|
||||
- `description`
|
||||
- `source_case_folder`
|
||||
- `created_from_template`
|
||||
- `version`
|
||||
|
||||
### `model`
|
||||
|
||||
- `modelflag`
|
||||
- `grid_model`
|
||||
- `flow_model`
|
||||
|
||||
Known values:
|
||||
|
||||
- `modelflag`: currently fixed to classical EDFM in all 7 examples
|
||||
- `grid_model`: `1` single-medium, `2` dual-medium
|
||||
- `flow_model`: `1` gas-water, `2` oil-water, `3` multi-component
|
||||
|
||||
### `grid`
|
||||
|
||||
Editable inputs:
|
||||
|
||||
- `dx`
|
||||
- `dy`
|
||||
- `dz`
|
||||
- `nx`
|
||||
- `ny`
|
||||
- `nz`
|
||||
- `NTG`
|
||||
|
||||
Derived by `GridProp_pre` and later preprocessing:
|
||||
|
||||
- `coordinates`
|
||||
- `nodes`
|
||||
- `nP`
|
||||
- `nmc`
|
||||
- `dxv`
|
||||
- `dyv`
|
||||
- `dzv`
|
||||
- `vm`
|
||||
- `zm`
|
||||
- `xrao`
|
||||
- `yrao`
|
||||
- `zrao`
|
||||
- `cell_mid_coords`
|
||||
|
||||
Important correction:
|
||||
|
||||
- `boundary` is not defined in `GridProp_pre.m`.
|
||||
- In case 1 it is defined in `grid_discretization_SP_model.m`.
|
||||
- This means geometric grid size and reservoir validity boundary are separate parameter groups and should not be merged.
|
||||
|
||||
### `fracture`
|
||||
|
||||
- `input_style`
|
||||
- `input_content`
|
||||
- `f`
|
||||
- `fellip`
|
||||
- `fractureLines`
|
||||
- `fractureHeights`
|
||||
- `flowBarrierFlags`
|
||||
- `frac_information`
|
||||
- `nf`
|
||||
|
||||
Observed input modes:
|
||||
|
||||
- Engineering input table
|
||||
- Vector input
|
||||
- 2D line input
|
||||
- Reserved `.fab` import mode
|
||||
|
||||
### `discretization`
|
||||
|
||||
Editable inputs:
|
||||
|
||||
- `grid_model`
|
||||
- `boundary`
|
||||
- `invalid_layer`
|
||||
- `valid_grids` generation rule
|
||||
- matrix permeability definition rule
|
||||
- matrix porosity definition rule
|
||||
- matrix reference pressure `prpor`
|
||||
- matrix compressibility `cpor`
|
||||
- rock density `rock_density`
|
||||
- fracture permeability `Kf`
|
||||
- fracture aperture `Wf`
|
||||
- fracture porosity `Porf`
|
||||
- fracture reference pressure `prporf`
|
||||
- fracture compressibility `cporf`
|
||||
- `stress_factor_fracture`
|
||||
- `stress_factor_matrix`
|
||||
- `stress_factor_ref_pressure`
|
||||
- dual-medium only:
|
||||
- `kx_matrixLayer`
|
||||
- `ky_matrixLayer`
|
||||
- `kz_matrixLayer`
|
||||
- `pori_matrixLayer`
|
||||
- `sigma`
|
||||
|
||||
Observed editable rock-property expressions in current cases:
|
||||
|
||||
- case 1 SP:
|
||||
- polygon `boundary`
|
||||
- `kx/ky/kz` as spatial functions of `cell_mid_coords`
|
||||
- `pori` as spatial function of `cell_mid_coords`
|
||||
- cases 2/4/6:
|
||||
- constant matrix properties
|
||||
- `invalid_layer` controls inactive layers
|
||||
- cases 5/7:
|
||||
- constant matrix properties, different values from cases 2/4/6
|
||||
- case 3 DP:
|
||||
- fracture-layer permeability set
|
||||
- matrix-layer permeability set
|
||||
- matrix-layer porosity
|
||||
- shape factor `sigma`
|
||||
|
||||
Derived fields:
|
||||
|
||||
- fracture-matrix discretization result
|
||||
- fracture-fracture discretization result
|
||||
- EDFM connection data
|
||||
- operator generation inputs for `OperatorRS`
|
||||
- runtime fields added onto `r`, including `rock_density`, `valid_grids`, stress-factor fields, and dual-medium derived fields
|
||||
|
||||
### `flow`
|
||||
|
||||
Shared categories:
|
||||
|
||||
- phase density
|
||||
- reference pressure
|
||||
- formation volume factor
|
||||
- compressibility
|
||||
- viscosity
|
||||
- viscosity-pressure coefficient
|
||||
- capillary pressure switch
|
||||
- non-Darcy coefficient
|
||||
- threshold pressure gradient
|
||||
- matrix relative permeability table
|
||||
- fracture relative permeability table
|
||||
|
||||
Additional note:
|
||||
|
||||
- Many of these are hidden inside helper files such as `gas_water_flow.m`, `oil_water_flow.m`, and `multi_component_flow.m`, so they must be treated as editable physics parameters even though they are not visible in `main1.m`.
|
||||
|
||||
Gas-water specific:
|
||||
|
||||
- `gas_prop.VL`
|
||||
- `gas_prop.PL`
|
||||
- `gas_prop.Kn`
|
||||
- `gas_prop.Kn_modified_factor`
|
||||
- `gas_prop.beta_non_Darcy_flow`
|
||||
- `density_g_sc`
|
||||
- `gas_model`
|
||||
- gas PVT table or generated PVT parameters
|
||||
|
||||
Oil-water specific:
|
||||
|
||||
- `density_o_sc`
|
||||
- `oil_model`
|
||||
- oil PVT table or generated PVT parameters
|
||||
|
||||
Multi-component specific:
|
||||
|
||||
- `Ds`
|
||||
- `Db`
|
||||
- adsorption table `c_ca_table`
|
||||
- chemistry parameters `R`, `Vm`, `Temperature`, `chemistry_cof`
|
||||
- dynamic relative permeability tables `cs_Nc`, `kr_nosurf`, `kr_surf`, `PC`
|
||||
- fracture counterparts of the same tables
|
||||
- `number_state_variables`
|
||||
|
||||
### `initial`
|
||||
|
||||
Gas-water and oil-water:
|
||||
|
||||
- `P`
|
||||
- `Sw`
|
||||
|
||||
Multi-component:
|
||||
|
||||
- `P`
|
||||
- `Sw`
|
||||
- `Cs`
|
||||
- `Cb`
|
||||
|
||||
### `wells`
|
||||
|
||||
Conventional well definition:
|
||||
|
||||
- `well1`
|
||||
- well name
|
||||
- perforation count
|
||||
- perforation grid indices
|
||||
- wellbore radius
|
||||
- skin
|
||||
- well type
|
||||
|
||||
Fracture-well definition:
|
||||
|
||||
- `num_fracture_wells`
|
||||
- `welloc`
|
||||
- `perfnum`
|
||||
- `well2`
|
||||
|
||||
Combined runtime well structure:
|
||||
|
||||
- `Wellc`
|
||||
|
||||
### `schedule`
|
||||
|
||||
- `number_phases`
|
||||
- `well_schedules`
|
||||
- `time`
|
||||
- `dtmax`
|
||||
- `dtmin`
|
||||
|
||||
Per-row schedule fields observed:
|
||||
|
||||
- well name
|
||||
- well state
|
||||
- well role
|
||||
- control mode
|
||||
- target value 1
|
||||
- target value 2
|
||||
- optional `Cs_inj`
|
||||
- optional `Cb_inj`
|
||||
|
||||
### `solver`
|
||||
|
||||
- `yitap`
|
||||
- `yitas`
|
||||
- `omega`
|
||||
- `Nmax`
|
||||
- `epsave`
|
||||
- `epsmax`
|
||||
|
||||
### `output`
|
||||
|
||||
Runtime outputs observed:
|
||||
|
||||
- `Times`
|
||||
- `OutputRs`
|
||||
- `Wellpara`
|
||||
- `trun`
|
||||
|
||||
Useful progress fields for the future GUI:
|
||||
|
||||
- current stage index
|
||||
- current simulation time
|
||||
- current `dt`
|
||||
- Newton iteration count
|
||||
- cumulative linear solve time
|
||||
- cumulative Jacobian assembly time
|
||||
|
||||
## Preset Strategy
|
||||
|
||||
The seven example folders should be treated as presets, not as independent long-term entry points.
|
||||
|
||||
Recommended future structure:
|
||||
|
||||
- `load_case_template(1)` ... `load_case_template(7)`
|
||||
- each template returns a complete `config`
|
||||
- GUI edits the `config`
|
||||
- `run_case(config)` executes the solver
|
||||
|
||||
This avoids binding the GUI to seven different hard-coded scripts.
|
||||
|
||||
## Run Page Scope
|
||||
|
||||
Pause and abort are explicitly deferred for now.
|
||||
|
||||
Current target for the run page:
|
||||
|
||||
- show active case name
|
||||
- show active stage
|
||||
- show current simulation time
|
||||
- show current timestep
|
||||
- show Newton count
|
||||
- show text log
|
||||
- optionally plot selected well response during run
|
||||
|
||||
The existing solver already prints progress with `fprintf`, but the proper GUI solution will be to add a progress callback later.
|
||||
|
||||
## File-Level Sources Confirmed So Far
|
||||
|
||||
Primary input sources already confirmed:
|
||||
|
||||
- `main1.m`
|
||||
- `GridProp_pre.m`
|
||||
- `grid_discretization_SP_model.m`
|
||||
- `grid_discretization_DP_model.m`
|
||||
- `preprocess_heterogeneous.m`
|
||||
- `gas_water_flow.m`
|
||||
- `oil_water_flow.m`
|
||||
- `multi_component_flow.m`
|
||||
|
||||
This matters because not all user-facing parameters live in `main1.m`.
|
||||
The parameter registry must therefore be built from the full call chain, not from entry scripts only.
|
||||
|
||||
## Next Implementation Steps
|
||||
|
||||
1. Build a complete field-level parameter registry file from the 7 case folders.
|
||||
2. Keep `create_empty_config` as the primary configuration skeleton.
|
||||
3. Use `run_case(config)` as the single runtime entry point for all three flow models.
|
||||
4. Build App Designer pages around model-specific parameter panels.
|
||||
|
||||
## Runtime Status
|
||||
|
||||
Current runtime direction:
|
||||
|
||||
- `run_case(config)` is now the unified execution entry.
|
||||
- `flow_model` is treated as mutually exclusive.
|
||||
- GUI should only show the active model's parameter set.
|
||||
- Non-active model parameters should remain hidden and unused.
|
||||
@@ -0,0 +1,351 @@
|
||||
# Parameter Registry
|
||||
|
||||
This registry maps the current hard-coded parameters to a unified `config` structure.
|
||||
It is intentionally field-oriented so the future GUI can be built against a stable schema.
|
||||
|
||||
## Conventions
|
||||
|
||||
- `Config Path`: target field in the unified config
|
||||
- `Source Variable`: current variable name in code
|
||||
- `Source File`: current MATLAB file where the parameter is defined
|
||||
- `Cases`: which example folders currently use the field
|
||||
- `Editable`: whether the GUI should expose the field
|
||||
- `Notes`: behavior, enum meaning, or shape
|
||||
|
||||
## Meta
|
||||
|
||||
| Config Path | Source Variable | Source File | Cases | Editable | Notes |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `meta.case_name` | none | template-level | all | yes | Display name |
|
||||
| `meta.case_id` | none | template-level | all | yes | Stable preset ID |
|
||||
| `meta.description` | none | template-level | all | yes | Free text |
|
||||
| `meta.source_case_folder` | folder name | template-level | all | no | Traceability |
|
||||
| `meta.created_from_template` | none | template-level | all | no | Preset source |
|
||||
| `meta.version` | none | config system | all | no | Schema version |
|
||||
|
||||
## Model
|
||||
|
||||
| Config Path | Source Variable | Source File | Cases | Editable | Notes |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `model.modelflag` | `modelflag` | `main1.m` | 1-7 | yes | Current examples use `1` |
|
||||
| `model.grid_model` | `grid_model` | `main1.m` | 1-7 | yes | `1` SP, `2` DP |
|
||||
| `model.flow_model` | `flow_model` | `main1.m` | 1-7 | yes | `1` gas-water, `2` oil-water, `3` multi-component |
|
||||
|
||||
## Grid Geometry
|
||||
|
||||
| Config Path | Source Variable | Source File | Cases | Editable | Notes |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `grid.dx` | `dx` | `main1.m` | 1-7 | yes | Vector |
|
||||
| `grid.dy` | `dy` | `main1.m` | 1-7 | yes | Vector |
|
||||
| `grid.dz` | `dz` | `main1.m` | 1-7 | yes | Vector |
|
||||
| `grid.nx` | `nx` | `main1.m` | 1-7 | no | Derived from `dx` |
|
||||
| `grid.ny` | `ny` | `main1.m` | 1-7 | no | Derived from `dy` |
|
||||
| `grid.nz` | `nz` | `main1.m` | 1-7 | no | Derived from `dz` |
|
||||
| `grid.NTG` | `NTG` | `main1.m` | 1-7 | no | Array sized `nx*ny*nz` |
|
||||
|
||||
Derived fields produced by `GridProp_pre.m`:
|
||||
|
||||
- `grid.coordinates`
|
||||
- `grid.nodes`
|
||||
- `grid.nP`
|
||||
- `grid.nmc`
|
||||
- `grid.dxv`
|
||||
- `grid.dyv`
|
||||
- `grid.dzv`
|
||||
- `grid.zm`
|
||||
- `grid.vm`
|
||||
- `grid.xrao`
|
||||
- `grid.yrao`
|
||||
- `grid.zrao`
|
||||
- `grid.cell_mid_coords`
|
||||
|
||||
## Fracture Input
|
||||
|
||||
| Config Path | Source Variable | Source File | Cases | Editable | Notes |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `fracture.input_style` | `input_style` | `main1.m` | 1-7 | yes | 1 engineering, 2 vector, 3 2D lines, 4 fab reserved |
|
||||
| `fracture.input_content` | `input_content` | `main1.m` | 1-7 | yes | Engineering fracture table |
|
||||
| `fracture.f` | `f` | `main1.m` / helper outputs | 1-7 | advanced | Vector fracture representation |
|
||||
| `fracture.fellip` | `fellip` | `main1.m` / helper outputs | 1-7 | advanced | Elliptic fractures |
|
||||
| `fracture.fractureLines` | `fractureLines` | `main1.m` | 1-7 | yes | Used in mode 3 |
|
||||
| `fracture.fractureHeights` | `fractureHeights` | `main1.m` | 1-7 | yes | Used in mode 3 |
|
||||
| `fracture.flowBarrierFlags` | `flowBarrierFlags` | `main1.m` | 1-7 | yes | Optional |
|
||||
| `fracture.frac_information` | `frac_information` | helper outputs | 1-7 | no | Generated by helper functions |
|
||||
| `fracture.nf` | `nf` | `main1.m` | 1-7 | no | Derived fracture count |
|
||||
|
||||
## Discretization Selection
|
||||
|
||||
| Config Path | Source Variable | Source File | Cases | Editable | Notes |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `discretization.mode` | `grid_model` | `main1.m` | 1-7 | yes | Mirrors `model.grid_model` |
|
||||
| `discretization.use_operator` | implicit | `main1.m` | 1-7 | no | `OperatorRS` is always called currently |
|
||||
|
||||
## SP Rock And Boundary Parameters
|
||||
|
||||
These are critical editable parameters and were previously undercounted.
|
||||
|
||||
| Config Path | Source Variable | Source File | Cases | Editable | Notes |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `discretization.sp.boundary_polygon` | `boundary` | `grid_discretization_SP_model.m` | 1 | yes | Irregular domain polygon |
|
||||
| `discretization.sp.invalid_layer` | `invalid_layer` | `grid_discretization_SP_model.m` | 1,2,4,5,6,7 | yes | Layer indices disabled from simulation |
|
||||
| `discretization.sp.valid_grids` | `valid_grids` | `grid_discretization_SP_model.m` | 1,2,4,5,6,7 | no | Derived from boundary/layers |
|
||||
| `discretization.sp.matrix.kx` | `kx` | `grid_discretization_SP_model.m` | 1,2,4,5,6,7 | yes | Array or generated field |
|
||||
| `discretization.sp.matrix.ky` | `ky` | `grid_discretization_SP_model.m` | 1,2,4,5,6,7 | yes | Array or generated field |
|
||||
| `discretization.sp.matrix.kz` | `kz` | `grid_discretization_SP_model.m` | 1,2,4,5,6,7 | yes | Array or generated field |
|
||||
| `discretization.sp.matrix.pori` | `pori` | `grid_discretization_SP_model.m` | 1,2,4,5,6,7 | yes | Array or generated field |
|
||||
| `discretization.sp.matrix.prpor` | `prpor` | `grid_discretization_SP_model.m` | 1,2,4,5,6,7 | yes | Matrix reference pressure |
|
||||
| `discretization.sp.matrix.cpor` | `cpor` | `grid_discretization_SP_model.m` | 1,2,4,5,6,7 | yes | Matrix compressibility |
|
||||
| `discretization.sp.matrix.rock_density` | `rock_density` / `density_rock` | `grid_discretization_SP_model.m` | 1,2,4,5,6,7 | yes | Naming is inconsistent across cases |
|
||||
| `discretization.sp.fracture.Kf` | `Kf` | `grid_discretization_SP_model.m` | 1,2,4,5,6,7 | yes | Fracture permeability |
|
||||
| `discretization.sp.fracture.Wf` | `Wf` | `grid_discretization_SP_model.m` | 1,2,4,5,6,7 | yes | Fracture aperture |
|
||||
| `discretization.sp.fracture.Porf` | `Porf` | `grid_discretization_SP_model.m` | 1,2,4,5,6,7 | yes | Fracture porosity |
|
||||
| `discretization.sp.fracture.prporf` | `prporf` | `grid_discretization_SP_model.m` | 1,2,4,5,6,7 | yes | Fracture reference pressure |
|
||||
| `discretization.sp.fracture.cporf` | `cporf` | `grid_discretization_SP_model.m` | 1,2,4,5,6,7 | yes | Fracture compressibility |
|
||||
| `discretization.sp.stress.fracture_factor` | `stress_factor_fracture` | `grid_discretization_SP_model.m` | 1,2,4,5,6,7 | yes | Stress sensitivity |
|
||||
| `discretization.sp.stress.matrix_factor` | `stress_factor_matrix` | `grid_discretization_SP_model.m` | 1,2,4,5,6,7 | yes | Stress sensitivity |
|
||||
| `discretization.sp.stress.ref_pressure` | `stress_factor_ref_pressure` | `grid_discretization_SP_model.m` | 1,2,4,5,6,7 | yes | Reference pressure |
|
||||
| `discretization.sp.stress.Rpt` | `Rpt` | `grid_discretization_SP_model.m` | 1,2,4,5,6,7 | yes | Unknown |
|
||||
| `discretization.sp.stress.cf` | `cf` | `grid_discretization_SP_model.m` | 1,2,4,5,6,7 | yes | Unknown |
|
||||
| `discretization.sp.stress.ca` | `ca` | `grid_discretization_SP_model.m` | 1,2,4,5,6,7 | yes | Unknown |
|
||||
|
||||
Case-specific notes:
|
||||
|
||||
- Case 1 uses spatial functions and an irregular polygon boundary.
|
||||
- Cases 2 and 4 use `invalid_layer` to deactivate the second layer when applicable.
|
||||
- Cases 5 and 7 use different constant matrix properties than cases 2, 4, and 6.
|
||||
|
||||
## DP Rock Parameters
|
||||
|
||||
| Config Path | Source Variable | Source File | Cases | Editable | Notes |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `discretization.dp.fracture_layer.kx` | `kx` | `grid_discretization_DP_model.m` | 3 | yes | Dual-medium fracture layer |
|
||||
| `discretization.dp.fracture_layer.ky` | `ky` | `grid_discretization_DP_model.m` | 3 | yes | Dual-medium fracture layer |
|
||||
| `discretization.dp.fracture_layer.kz` | `kz` | `grid_discretization_DP_model.m` | 3 | yes | Dual-medium fracture layer |
|
||||
| `discretization.dp.fracture_layer.pori` | `pori` | `grid_discretization_DP_model.m` | 3 | no | Dual-medium fracture layer porosity |
|
||||
| `discretization.dp.matrix_layer.kx` | `kx_matrixLayer` | `grid_discretization_DP_model.m` | 3 | yes | Matrix layer permeability |
|
||||
| `discretization.dp.matrix_layer.ky` | `ky_matrixLayer` | `grid_discretization_DP_model.m` | 3 | yes | Matrix layer permeability |
|
||||
| `discretization.dp.matrix_layer.kz` | `kz_matrixLayer` | `grid_discretization_DP_model.m` | 3 | yes | Matrix layer permeability |
|
||||
| `discretization.dp.matrix_layer.pori` | `pori_matrixLayer` | `grid_discretization_DP_model.m` | 3 | yes | Matrix layer porosity |
|
||||
| `discretization.dp.shape_factor` | `sigma` | `grid_discretization_DP_model.m` | 3 | yes | Interporosity shape factor |
|
||||
| `discretization.dp.valid_grids` | `valid_grids` | `grid_discretization_DP_model.m` | 3 | no | All ones in current example |
|
||||
| `discretization.dp.NTG` | `NTG` | `grid_discretization_DP_model.m` | 3 | yes | Reassigned in file |
|
||||
| `discretization.dp.prpor` | `prpor` | `grid_discretization_DP_model.m` | 3 | yes | Reference pressure |
|
||||
| `discretization.dp.cpor` | `cpor` | `grid_discretization_DP_model.m` | 3 | yes | Compressibility |
|
||||
| `discretization.dp.fracture.Kf` | `Kf` | `grid_discretization_DP_model.m` | 3 | yes | Fracture permeability |
|
||||
| `discretization.dp.fracture.Wf` | `Wf` | `grid_discretization_DP_model.m` | 3 | yes | Fracture aperture |
|
||||
| `discretization.dp.fracture.Porf` | `Porf` | `grid_discretization_DP_model.m` | 3 | yes | Fracture porosity |
|
||||
| `discretization.dp.fracture.prporf` | `prporf` | `grid_discretization_DP_model.m` | 3 | yes | Fracture reference pressure |
|
||||
| `discretization.dp.fracture.cporf` | `cporf` | `grid_discretization_DP_model.m` | 3 | yes | Fracture compressibility |
|
||||
| `discretization.dp.stress.fracture_factor` | `stress_factor_fracture` | `grid_discretization_DP_model.m` | 3 | yes | Stress sensitivity |
|
||||
| `discretization.dp.stress.matrix_factor` | `stress_factor_matrix` | `grid_discretization_DP_model.m` | 3 | yes | Stress sensitivity |
|
||||
| `discretization.dp.stress.ref_pressure` | `stress_factor_ref_pressure` | `grid_discretization_DP_model.m` | 3 | yes | Reference pressure |
|
||||
| `discretization.dp.rock_density` | `rock_density` | `grid_discretization_DP_model.m` | 3 | yes | Rock density |
|
||||
| `discretization.dp.Rpt` | `Rpt` | `grid_discretization_DP_model.m` | 3 | yes | Unknown |
|
||||
| `discretization.dp.cf` | `cf` | `grid_discretization_DP_model.m` | 3 | yes | Unknown |
|
||||
| `discretization.dp.ca` | `ca` | `grid_discretization_DP_model.m` | 3 | yes | Unknown |
|
||||
|
||||
## Flow: Gas-Water
|
||||
|
||||
| Config Path | Source Variable | Source File | Cases | Editable | Notes |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `flow.gas_water.gas_prop.VL` | `gas_prop.VL` | `gas_water_flow.m` | 4 | yes | Langmuir volume |
|
||||
| `flow.gas_water.gas_prop.PL` | `gas_prop.PL` | `gas_water_flow.m` | 4 | yes | Langmuir pressure |
|
||||
| `flow.gas_water.gas_prop.Kn` | `gas_prop.Kn` | `gas_water_flow.m` | 4 | yes | Knudsen number |
|
||||
| `flow.gas_water.gas_prop.Kn_modified_factor` | `gas_prop.Kn_modified_factor` | `gas_water_flow.m` | 4 | no | Derived |
|
||||
| `flow.gas_water.gas_prop.beta_non_darcy_flow` | `gas_prop.beta_non_Darcy_flow` | `gas_water_flow.m` | 4 | yes | High-velocity term |
|
||||
| `flow.gas_water.p_grad_threshold` | `p_grad_threshold` | `gas_water_flow.m` | 4 | yes | Threshold pressure gradient |
|
||||
| `flow.gas_water.density_g_sc` | `density_g_sc` | `gas_water_flow.m` | 4 | yes | Gas density at standard conditions |
|
||||
| `flow.gas_water.density_w_sc` | `density_w_sc` | `gas_water_flow.m` | 4 | yes | Water density at standard conditions |
|
||||
| `flow.gas_water.gas_model` | `gas_model` | `gas_water_flow.m` | 4 | yes | 1 generated PVT, 2 tabulated PVT |
|
||||
| `flow.gas_water.prg` | `prg` | `gas_water_flow.m` | 4 | yes | Only in model 1 |
|
||||
| `flow.gas_water.Bgi` | `Bgi` | `gas_water_flow.m` | 4 | yes | Only in model 1 |
|
||||
| `flow.gas_water.cg` | `cg` | `gas_water_flow.m` | 4 | yes | Only in model 1 |
|
||||
| `flow.gas_water.vgi` | `vgi` | `gas_water_flow.m` | 4 | yes | Only in model 1 |
|
||||
| `flow.gas_water.cvg` | `cvg` | `gas_water_flow.m` | 4 | yes | Only in model 1 |
|
||||
| `flow.gas_water.Ppr` | `Ppr` | `gas_water_flow.m` | 4 | yes | Table or generated |
|
||||
| `flow.gas_water.BG` | `BG` | `gas_water_flow.m` | 4 | yes | Table or generated |
|
||||
| `flow.gas_water.MUG` | `MUG` | `gas_water_flow.m` | 4 | yes | Table or generated |
|
||||
| `flow.gas_water.prw` | `prw` | `gas_water_flow.m` | 4 | yes | Water reference pressure |
|
||||
| `flow.gas_water.Bwi` | `Bwi` | `gas_water_flow.m` | 4 | yes | Water volume factor |
|
||||
| `flow.gas_water.cw` | `cw` | `gas_water_flow.m` | 4 | yes | Water compressibility |
|
||||
| `flow.gas_water.vwi` | `vwi` | `gas_water_flow.m` | 4 | yes | Water viscosity |
|
||||
| `flow.gas_water.cvw` | `cvw` | `gas_water_flow.m` | 4 | yes | Water viscosity-pressure coefficient |
|
||||
| `flow.gas_water.ifpcgl` | `ifpcgl` | `gas_water_flow.m` | 4 | yes | Capillary pressure switch |
|
||||
| `flow.gas_water.matrix_relperm_table` | `RPGW` | `gas_water_flow.m` | 4 | yes | Matrix table |
|
||||
| `flow.gas_water.fracture_relperm_table` | `PRF` | `gas_water_flow.m` | 4 | yes | Fracture table |
|
||||
|
||||
## Flow: Oil-Water
|
||||
|
||||
| Config Path | Source Variable | Source File | Cases | Editable | Notes |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `flow.oil_water.density_o_sc` | `density_o_sc` | `oil_water_flow.m` | 5,6,7 | yes | Oil density |
|
||||
| `flow.oil_water.density_w_sc` | `density_w_sc` | `oil_water_flow.m` | 5,6,7 | yes | Water density |
|
||||
| `flow.oil_water.oil_model` | `oil_model` | `oil_water_flow.m` | 5,6,7 | yes | 1 generated PVT, 2 tabulated |
|
||||
| `flow.oil_water.pro` | `pro` | `oil_water_flow.m` | 5,6,7 | yes | Oil ref pressure |
|
||||
| `flow.oil_water.Boi` | `Boi` | `oil_water_flow.m` | 5,6,7 | yes | Oil volume factor |
|
||||
| `flow.oil_water.co` | `co` | `oil_water_flow.m` | 5,6,7 | yes | Oil compressibility |
|
||||
| `flow.oil_water.voi` | `voi` | `oil_water_flow.m` | 5,6,7 | yes | Oil viscosity |
|
||||
| `flow.oil_water.cvo` | `cvo` | `oil_water_flow.m` | 5,6,7 | yes | Oil viscosity-pressure coefficient |
|
||||
| `flow.oil_water.Ppr` | `Ppr` | `oil_water_flow.m` | 5,6,7 | yes | Table or generated |
|
||||
| `flow.oil_water.BO` | `BO` | `oil_water_flow.m` | 5,6,7 | yes | Table or generated |
|
||||
| `flow.oil_water.MUO` | `MUO` | `oil_water_flow.m` | 5,6,7 | yes | Table or generated |
|
||||
| `flow.oil_water.prw` | `prw` | `oil_water_flow.m` | 5,6,7 | yes | Water ref pressure |
|
||||
| `flow.oil_water.Bwi` | `Bwi` | `oil_water_flow.m` | 5,6,7 | yes | Water volume factor |
|
||||
| `flow.oil_water.cw` | `cw` | `oil_water_flow.m` | 5,6,7 | yes | Water compressibility |
|
||||
| `flow.oil_water.vwi` | `vwi` | `oil_water_flow.m` | 5,6,7 | yes | Water viscosity |
|
||||
| `flow.oil_water.cvw` | `cvw` | `oil_water_flow.m` | 5,6,7 | yes | Water viscosity-pressure coefficient |
|
||||
| `flow.oil_water.ifpcow` | `ifpcow` | `oil_water_flow.m` | 5,6,7 | yes | Capillary pressure switch |
|
||||
| `flow.oil_water.matrix_relperm_table` | `PRM` | `oil_water_flow.m` | 5,6,7 | yes | Matrix table |
|
||||
| `flow.oil_water.fracture_relperm_table` | `PRF` | `oil_water_flow.m` | 5,6,7 | yes | Fracture table |
|
||||
| `flow.oil_water.beta_non_darcy_flow` | `beta_non_Darcy_flow` | `oil_water_flow.m` | 5,6,7 | yes | Non-Darcy coefficient |
|
||||
| `flow.oil_water.p_grad_threshold` | `p_grad_threshold` | `oil_water_flow.m` | 5,6,7 | yes | Threshold gradient |
|
||||
|
||||
## Flow: Multi-Component
|
||||
|
||||
| Config Path | Source Variable | Source File | Cases | Editable | Notes |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `flow.multi_component.Ds` | `Ds` | `multi_component_flow.m` | 1,2,3 | yes | Surfactant diffusion |
|
||||
| `flow.multi_component.Db` | `Db` | `multi_component_flow.m` | 1,2,3 | yes | Salt diffusion |
|
||||
| `flow.multi_component.c_ca_table` | `c_ca_table` | `multi_component_flow.m` | 1,2,3 | yes | Adsorption table |
|
||||
| `flow.multi_component.cs_data` | `cs_data` | `multi_component_flow.m` | 1,2,3 | no | Derived from table |
|
||||
| `flow.multi_component.cb_data` | `cb_data` | `multi_component_flow.m` | 1,2,3 | no | Derived from table |
|
||||
| `flow.multi_component.csa_data` | `csa_data` | `multi_component_flow.m` | 1,2,3 | no | Derived from table |
|
||||
| `flow.multi_component.cba_data` | `cba_data` | `multi_component_flow.m` | 1,2,3 | no | Derived from table |
|
||||
| `flow.multi_component.R` | `R` | `multi_component_flow.m` | 1,2,3 | yes | Chemistry constant |
|
||||
| `flow.multi_component.Vm` | `Vm` | `multi_component_flow.m` | 1,2,3 | yes | Molar volume |
|
||||
| `flow.multi_component.Temperature` | `Temperature` | `multi_component_flow.m` | 1,2,3 | yes | Temperature |
|
||||
| `flow.multi_component.chemistry_cof` | `chemistry_cof` | `multi_component_flow.m` | 1,2,3 | no | Derived |
|
||||
| `flow.multi_component.x_matrix!!!!` | `xm` | `multi_component_flow.m` | 1,2,3 | yes | Chemistry activity factor for matrix cells |
|
||||
| `flow.multi_component.x_fracture!!!` | `xf` | `multi_component_flow.m` | 1,2,3 | yes | Chemistry activity factor for fracture cells |
|
||||
| `flow.multi_component.cs_Nc` | `cs_Nc` | `multi_component_flow.m` | 1,2,3 | yes | Dynamic relative permeability mapping |
|
||||
| `flow.multi_component.Nc_nosurf` | `Nc_nosurf` | `multi_component_flow.m` | 1,2,3 | no | Derived |
|
||||
| `flow.multi_component.Nc_surf` | `Nc_surf` | `multi_component_flow.m` | 1,2,3 | no | Derived |
|
||||
| `flow.multi_component.kr_nosurf` | `kr_nosurf` | `multi_component_flow.m` | 1,2,3 | yes | Relative permeability table |
|
||||
| `flow.multi_component.kr_surf` | `kr_surf` | `multi_component_flow.m` | 1,2,3 | yes | Relative permeability table |
|
||||
| `flow.multi_component.PC` | `PC` | `multi_component_flow.m` | 1,2,3 | yes | Capillary pressure table |
|
||||
| `flow.multi_component.cs_Nc_fracture` | `cs_Nc_fracture` | `multi_component_flow.m` | 1,2,3 | yes | Fracture table |
|
||||
| `flow.multi_component.kr_nosurf_fracture` | `kr_nosurf_fracture` | `multi_component_flow.m` | 1,2,3 | yes | Fracture table |
|
||||
| `flow.multi_component.kr_surf_fracture` | `kr_surf_fracture` | `multi_component_flow.m` | 1,2,3 | yes | Fracture table |
|
||||
| `flow.multi_component.PC_fracture` | `PC_fracture` | `multi_component_flow.m` | 1,2,3 | yes | Fracture capillary table |
|
||||
| `flow.multi_component.ifpcgl` | `ifpcgl` | `multi_component_flow.m` | 1,2,3 | yes | Capillary pressure switch |
|
||||
| `flow.multi_component.p_grad_threshold` | `p_grad_threshold` | `multi_component_flow.m` | 1,2,3 | yes | Threshold gradient |
|
||||
| `flow.multi_component.gas_prop.VL` | `gas_prop.VL` | `multi_component_flow.m` | 1,2,3 | yes | Often zero for oil-like use |
|
||||
| `flow.multi_component.gas_prop.PL` | `gas_prop.PL` | `multi_component_flow.m` | 1,2,3 | yes | Langmuir pressure |
|
||||
| `flow.multi_component.gas_prop.Kn` | `gas_prop.Kn` | `multi_component_flow.m` | 1,2,3 | yes | Knudsen number |
|
||||
| `flow.multi_component.gas_prop.Kn_modified_factor` | `gas_prop.Kn_modified_factor` | `multi_component_flow.m` | 1,2,3 | no | Derived |
|
||||
| `flow.multi_component.gas_prop.stress_factor_fracture` | `gas_prop.stress_factor_fracture` | `multi_component_flow.m` | 1,2,3 | yes | Present in case-specific flow files |
|
||||
| `flow.multi_component.gas_prop.stress_factor_matrix` | `gas_prop.stress_factor_matrix` | `multi_component_flow.m` | 1,2,3 | yes | Present in case-specific flow files |
|
||||
| `flow.multi_component.gas_prop.stress_factor_ref_pressure` | `gas_prop.stress_factor_ref_pressure` | `multi_component_flow.m` | 1,2,3 | yes | Present in case-specific flow files |
|
||||
| `flow.multi_component.gas_prop.beta_non_darcy_flow` | `gas_prop.beta_non_Darcy_flow` | `multi_component_flow.m` | 1,2,3 | yes | Non-Darcy coefficient |
|
||||
| `flow.multi_component.density_g_sc` | `density_g_sc` | `multi_component_flow.m` | 1,2,3 | yes | Standard density |
|
||||
| `flow.multi_component.gas_model` | `gas_model` | `multi_component_flow.m` | 1,2,3 | yes | 1 generated, 2 tabulated |
|
||||
| `flow.multi_component.prg` | `prg` | `multi_component_flow.m` | 1,2,3 | yes | Ref pressure |
|
||||
| `flow.multi_component.Bgi` | `Bgi` | `multi_component_flow.m` | 1,2,3 | yes | Volume factor |
|
||||
| `flow.multi_component.cg` | `cg` | `multi_component_flow.m` | 1,2,3 | yes | Compressibility |
|
||||
| `flow.multi_component.vgi` | `vgi` | `multi_component_flow.m` | 1,2,3 | yes | Viscosity |
|
||||
| `flow.multi_component.cvg` | `cvg` | `multi_component_flow.m` | 1,2,3 | yes | Viscosity-pressure coefficient |
|
||||
| `flow.multi_component.Ppr` | `Ppr` | `multi_component_flow.m` | 1,2,3 | yes | Table or generated |
|
||||
| `flow.multi_component.BG` | `BG` | `multi_component_flow.m` | 1,2,3 | yes | Table or generated |
|
||||
| `flow.multi_component.MUG` | `MUG` | `multi_component_flow.m` | 1,2,3 | yes | Table or generated |
|
||||
| `flow.multi_component.density_w_sc` | `density_w_sc` | `multi_component_flow.m` | 1,2,3 | yes | Water density |
|
||||
| `flow.multi_component.prw` | `prw` | `multi_component_flow.m` | 1,2,3 | yes | Water ref pressure |
|
||||
| `flow.multi_component.Bwi` | `Bwi` | `multi_component_flow.m` | 1,2,3 | yes | Water volume factor |
|
||||
| `flow.multi_component.cw` | `cw` | `multi_component_flow.m` | 1,2,3 | yes | Water compressibility |
|
||||
| `flow.multi_component.vwi` | `vwi` | `multi_component_flow.m` | 1,2,3 | yes | Water viscosity |
|
||||
| `flow.multi_component.cvw` | `cvw` | `multi_component_flow.m` | 1,2,3 | yes | Water viscosity-pressure coefficient |
|
||||
| `flow.multi_component.number_state_variables` | `number_state_variables` | `multi_component_flow.m` | 1,2,3 | no | Fixed as 4 in current code |
|
||||
|
||||
## Initial Conditions
|
||||
|
||||
| Config Path | Source Variable | Source File | Cases | Editable | Notes |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `initial.pressure` | `P` | flow files | 1-7 | yes | Initial pressure array |
|
||||
| `initial.sw` | `Sw` | flow files | 1-7 | yes | Initial water saturation array |
|
||||
| `initial.cs` | `Cs` | `multi_component_flow.m` | 1,2,3 | yes | Initial surfactant concentration |
|
||||
| `initial.cb` | `Cb` | `multi_component_flow.m` | 1,2,3 | yes | Initial salt concentration |
|
||||
|
||||
## Wells
|
||||
|
||||
| Config Path | Source Variable | Source File | Cases | Editable | Notes |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `wells.well1` | `well1` | `main1.m` | 1-7 | yes | Conventional wells table |
|
||||
| `wells.num_fracture_wells` | `num_fracture_wells` | `main1.m` | 1-7 | yes | Count |
|
||||
| `wells.welloc` | `welloc` | `main1.m` | 1-7 | yes | Fracture well coordinates |
|
||||
| `wells.perfnum` | `perfnum` | helper output | 1-7 | no | Derived from `findWelloc` |
|
||||
| `wells.well2` | `well2` | `main1.m` | 1-7 | yes | Fracture-well table |
|
||||
| `wells.Wellc` | `Wellc` | helper output | 1-7 | no | Combined runtime structure |
|
||||
|
||||
Conventional well row shape:
|
||||
|
||||
- well name
|
||||
- perforation count
|
||||
- perforation grid index matrix
|
||||
- well radius
|
||||
- skin
|
||||
- well type
|
||||
|
||||
Fracture-well row shape:
|
||||
|
||||
- well name
|
||||
- perforation count
|
||||
- perforation indices
|
||||
- well radius
|
||||
- skin
|
||||
- well type
|
||||
|
||||
## Schedule
|
||||
|
||||
| Config Path | Source Variable | Source File | Cases | Editable | Notes |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `schedule.number_phases` | `number_phases` | `main1.m` | 1-7 | yes | Stage count |
|
||||
| `schedule.well_schedules` | `well_schedules` | `main1.m` | 1-7 | yes | Per-stage control rows |
|
||||
| `schedule.time` | `time` | `main1.m` | 1-7 | yes | Stage duration vector |
|
||||
| `schedule.dtmax` | `dtmax` | `main1.m` | 1-7 | yes | Max timestep per stage |
|
||||
| `schedule.dtmin` | `dtmin` | `main1.m` | 1-7 | yes | Min timestep per stage |
|
||||
|
||||
Schedule row fields observed:
|
||||
|
||||
- well name
|
||||
- well state
|
||||
- well role
|
||||
- control mode
|
||||
- target value 1
|
||||
- target value 2
|
||||
- optional `Cs_inj`
|
||||
- optional `Cb_inj`
|
||||
|
||||
## Solver
|
||||
|
||||
| Config Path | Source Variable | Source File | Cases | Editable | Notes |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `solver.yitap` | `yitap` | `main1.m` | 1-7 | yes | Adaptive timestep control |
|
||||
| `solver.yitas` | `yitas` | `main1.m` | 1-7 | yes | Adaptive timestep control |
|
||||
| `solver.omega` | `omega` | `main1.m` | 1-7 | yes | Adaptive timestep control |
|
||||
| `solver.Nmax` | `Nmax` | `main1.m` | 1-7 | yes | Max Newton iterations |
|
||||
| `solver.epsave` | `epsave` | `main1.m` | 1-7 | yes | Average residual tolerance |
|
||||
| `solver.epsmax` | `epsmax` | `main1.m` | 1-7 | yes | Max residual tolerance |
|
||||
|
||||
## Runtime / Output
|
||||
|
||||
| Config Path | Source Variable | Source File | Cases | Editable | Notes |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `output.result_name` | none | future GUI | all | yes | Result label |
|
||||
| `output.save_input_path` | none | future GUI | all | yes | Save location |
|
||||
| `output.save_result_path` | none | future GUI | all | yes | Save location |
|
||||
| `output.plot_requests` | none | future GUI | all | yes | Requested result plots |
|
||||
|
||||
Runtime-only outputs:
|
||||
|
||||
- `Times`
|
||||
- `OutputRs`
|
||||
- `Wellpara`
|
||||
- `trun`
|
||||
|
||||
## Known Inconsistencies To Normalize
|
||||
|
||||
- `rock_density` and `density_rock` are both used in SP discretization files.
|
||||
- Some fields are editable expressions in one case and constant arrays in another, especially `kx`, `ky`, `kz`, and `pori`.
|
||||
- `boundary` exists in case 1 but not in the other SP examples.
|
||||
- DP mode introduces extra fields absent from SP mode.
|
||||
|
||||
These inconsistencies are exactly why the GUI must be built on a normalized `config` instead of the raw scripts.
|
||||
@@ -0,0 +1,369 @@
|
||||
# EDFM GUI Project Status Overview
|
||||
|
||||
## Project Goal
|
||||
|
||||
Build a MATLAB GUI for the existing EDFM simulator so that users can:
|
||||
|
||||
- edit simulation parameters through a graphical interface
|
||||
- load and save input configurations
|
||||
- run the solver from the GUI
|
||||
- view run status and basic results
|
||||
- import and export results
|
||||
- eventually call existing plotting functions from the result page
|
||||
|
||||
The current solver code already exists.
|
||||
The main work is:
|
||||
|
||||
1. extracting and organizing parameters from the existing case scripts and helper files
|
||||
2. building a GUI around a unified configuration format and runtime entry point
|
||||
|
||||
## Functional Scope Agreed So Far
|
||||
|
||||
### GUI Structure
|
||||
|
||||
The GUI should be organized by the `Part1` to `Part8` logic already present in the case `main1.m` files.
|
||||
|
||||
Recommended page split:
|
||||
|
||||
- `Part1 模型`
|
||||
- `Part2 网格`
|
||||
- `Part3 裂缝`
|
||||
- `Part4 离散化/岩性`
|
||||
- `Part5 流动模型`
|
||||
- `Part6 井与制度`
|
||||
- `Part7 求解器`
|
||||
- `结果`
|
||||
|
||||
There is also a top toolbar for:
|
||||
|
||||
- template loading
|
||||
- config import/export
|
||||
- run
|
||||
- result import/export
|
||||
|
||||
### Data Management
|
||||
|
||||
The main editable runtime format is now defined as MATLAB `struct`.
|
||||
|
||||
Current persistence direction:
|
||||
|
||||
- config import/export: `.mat`
|
||||
- result import/export: `.mat`
|
||||
|
||||
JSON is not the current priority.
|
||||
It can be added later if needed.
|
||||
|
||||
### Runtime Model Handling
|
||||
|
||||
The three flow models are mutually exclusive:
|
||||
|
||||
- `1`: gas-water
|
||||
- `2`: oil-water
|
||||
- `3`: multi-component
|
||||
|
||||
The GUI should only show the active flow model's parameters.
|
||||
Inactive model parameters should not be shown or used during runtime.
|
||||
|
||||
## What Has Been Completed
|
||||
|
||||
## 1. Parameter extraction and organization
|
||||
|
||||
The repository has been reviewed across:
|
||||
|
||||
- all 7 example case folders
|
||||
- `main1.m`
|
||||
- `GridProp_pre.m`
|
||||
- `grid_discretization_SP_model.m`
|
||||
- `grid_discretization_DP_model.m`
|
||||
- `gas_water_flow.m`
|
||||
- `oil_water_flow.m`
|
||||
- `multi_component_flow.m`
|
||||
- solver entry and main runtime functions
|
||||
|
||||
Completed documents:
|
||||
|
||||
- [`gui_parameter_plan.md`](C:\Users\Administrator\Videos\3D_EDFM_simulator_20260305\docs\gui_parameter_plan.md)
|
||||
- [`case_template_summary.md`](C:\Users\Administrator\Videos\3D_EDFM_simulator_20260305\docs\case_template_summary.md)
|
||||
- [`parameter_registry.md`](C:\Users\Administrator\Videos\3D_EDFM_simulator_20260305\docs\parameter_registry.md)
|
||||
|
||||
These already cover:
|
||||
|
||||
- overall GUI architecture
|
||||
- 7-case summary
|
||||
- field-level parameter registry
|
||||
- separation of editable parameters and derived runtime fields
|
||||
|
||||
## 2. Unified config skeleton
|
||||
|
||||
Created:
|
||||
|
||||
- [`create_empty_config.m`](C:\Users\Administrator\Videos\3D_EDFM_simulator_20260305\gui_support\config\create_empty_config.m)
|
||||
|
||||
Current config structure includes:
|
||||
|
||||
- `meta`
|
||||
- `model`
|
||||
- `grid`
|
||||
- `fracture`
|
||||
- `discretization`
|
||||
- `flow`
|
||||
- `initial`
|
||||
- `wells`
|
||||
- `schedule`
|
||||
- `solver`
|
||||
- `output`
|
||||
|
||||
It now includes all major editable parameter groups identified so far.
|
||||
|
||||
## 3. Config and result MAT import/export helpers
|
||||
|
||||
Created:
|
||||
|
||||
- [`load_config_mat.m`](C:\Users\Administrator\Videos\3D_EDFM_simulator_20260305\gui_support\config\load_config_mat.m)
|
||||
- [`save_config_mat.m`](C:\Users\Administrator\Videos\3D_EDFM_simulator_20260305\gui_support\config\save_config_mat.m)
|
||||
- [`load_results_mat.m`](C:\Users\Administrator\Videos\3D_EDFM_simulator_20260305\gui_support\results\load_results_mat.m)
|
||||
- [`save_results_mat.m`](C:\Users\Administrator\Videos\3D_EDFM_simulator_20260305\gui_support\results\save_results_mat.m)
|
||||
|
||||
## 4. Unified runtime entry point
|
||||
|
||||
Created:
|
||||
|
||||
- [`run_case.m`](C:\Users\Administrator\Videos\3D_EDFM_simulator_20260305\gui_support\runtime\run_case.m)
|
||||
|
||||
This is now the intended runtime entry point instead of calling each case's `main1.m` directly.
|
||||
|
||||
Current status:
|
||||
|
||||
- grid preprocessing is routed through unified config
|
||||
- fracture inputs are routed through unified config
|
||||
- well and schedule setup are routed through unified config
|
||||
- solver invocation is routed through unified config
|
||||
- all three `flow_model` branches are now supported through the unified runtime path
|
||||
|
||||
## 5. First template support
|
||||
|
||||
Created:
|
||||
|
||||
- [`load_case_template.m`](C:\Users\Administrator\Videos\3D_EDFM_simulator_20260305\gui_support\templates\load_case_template.m)
|
||||
- [`load_case_template_case01.m`](C:\Users\Administrator\Videos\3D_EDFM_simulator_20260305\gui_support\templates\load_case_template_case01.m)
|
||||
|
||||
Current template coverage:
|
||||
|
||||
- `case01`
|
||||
|
||||
This is enough to validate the unified config and runtime direction, but not yet enough for final GUI delivery.
|
||||
|
||||
## 6. App Designer direction clarified
|
||||
|
||||
Important conclusion:
|
||||
|
||||
- a pure `.m` app class is not the right final form for this project if the user wants to edit the GUI in MATLAB App Designer
|
||||
- the final GUI should be built as a real `.mlapp`
|
||||
- the current recommended workflow is:
|
||||
- manually draw the layout in App Designer
|
||||
- keep stable component names
|
||||
- then bind code to those components
|
||||
|
||||
## What Still Needs To Be Done
|
||||
|
||||
## 1. Draw the real `.mlapp` interface
|
||||
|
||||
This is the next main task.
|
||||
|
||||
Need to complete:
|
||||
|
||||
- top toolbar
|
||||
- all main tabs
|
||||
- model-specific sub-tabs or dynamic sections
|
||||
- all editable controls
|
||||
- result page layout
|
||||
|
||||
The drawing guide has been prepared conceptually, but the actual `.mlapp` still needs to be built manually in App Designer.
|
||||
|
||||
## 2. Bind `.mlapp` code to existing backend
|
||||
|
||||
After the UI is drawn, code still needs to be connected for:
|
||||
|
||||
- startup default config loading
|
||||
- template switching
|
||||
- config import/export
|
||||
- result import/export
|
||||
- reading values from controls into `config`
|
||||
- writing `config` back into controls
|
||||
- calling `run_case(config)`
|
||||
- refreshing result plots
|
||||
|
||||
## 3. Expand template coverage
|
||||
|
||||
Currently only `case01` has a template loader.
|
||||
|
||||
Still needed:
|
||||
|
||||
- `case02`
|
||||
- `case03`
|
||||
- `case04`
|
||||
- `case05`
|
||||
- `case06`
|
||||
- `case07`
|
||||
|
||||
These should eventually all become presets in the GUI.
|
||||
|
||||
## 4. Strengthen flow-model config coverage
|
||||
|
||||
The unified runtime path now supports all three model branches, but more practical work is still needed:
|
||||
|
||||
- make sure default template values are complete for each model
|
||||
- validate that GUI fields map cleanly to backend config fields
|
||||
- ensure inactive model fields do not interfere with execution
|
||||
|
||||
## 5. Improve editing experience for complex parameters
|
||||
|
||||
Right now, many large arrays or nested cell structures are still best represented as text expressions.
|
||||
This is acceptable for early integration but not ideal for end users.
|
||||
|
||||
Likely future upgrades:
|
||||
|
||||
- use `UITable` for well definitions
|
||||
- use `UITable` for schedules
|
||||
- use `UITable` for fracture engineering input
|
||||
- use dedicated table editors for relperm/PVT/adsorption data
|
||||
|
||||
## 6. Results page enhancement
|
||||
|
||||
The final result page should support:
|
||||
|
||||
- summary text
|
||||
- well response curves
|
||||
- Newton-vs-time or runtime diagnostics
|
||||
- 2D and 3D plots
|
||||
- selected existing post-processing functions
|
||||
|
||||
This is only partially addressed so far.
|
||||
|
||||
## Hard Parts
|
||||
|
||||
## 1. Parameters are not only in `main1.m`
|
||||
|
||||
This is the biggest structural difficulty.
|
||||
|
||||
Important parameters are scattered across:
|
||||
|
||||
- case `main1.m`
|
||||
- grid preprocessing files
|
||||
- SP/DP discretization files
|
||||
- physics setup files
|
||||
- solver-related helper files
|
||||
|
||||
This makes GUI extraction error-prone if only entry scripts are inspected.
|
||||
|
||||
## 2. Same function names appear in multiple case folders
|
||||
|
||||
Several case folders contain same-named files such as:
|
||||
|
||||
- `grid_discretization_SP_model.m`
|
||||
- `multi_component_flow.m`
|
||||
|
||||
This means runtime path resolution can break if the working directory or MATLAB path is not controlled carefully.
|
||||
|
||||
The current backend addresses this by resolving case folders explicitly before running.
|
||||
|
||||
## 3. MATLAB App Designer is not Qt-style UI-file driven
|
||||
|
||||
Unlike Qt `.ui`, MATLAB `.mlapp` is not a simple open text UI definition format.
|
||||
This means:
|
||||
|
||||
- generating App Designer GUI purely by external text editing is unreliable
|
||||
- manual drawing inside App Designer is the safer workflow
|
||||
|
||||
## 4. Complex data entry is awkward in basic controls
|
||||
|
||||
Several parameters are naturally tabular or nested:
|
||||
|
||||
- fracture engineering input
|
||||
- well definitions
|
||||
- well schedules
|
||||
- relperm tables
|
||||
- adsorption tables
|
||||
|
||||
These need careful component choice.
|
||||
If handled with only `TextArea`, the app will work but will not be user-friendly.
|
||||
|
||||
## 5. Encoding and Chinese path issues
|
||||
|
||||
Some files and folders contain Chinese names.
|
||||
Some comments also appear to have encoding issues.
|
||||
|
||||
Risks:
|
||||
|
||||
- MATLAB string/path handling may be fine, but external tooling and generated code may display garbage text
|
||||
- hardcoding such paths in generated code is risky
|
||||
|
||||
ASCII-safe identifiers and runtime folder resolution are preferred where possible.
|
||||
|
||||
## Easy-To-Break Areas
|
||||
|
||||
## 1. Component naming drift
|
||||
|
||||
If the `.mlapp` component names are changed casually after backend code is written, callbacks and data binding will break quickly.
|
||||
|
||||
Recommendation:
|
||||
|
||||
- finalize component names early
|
||||
- keep names stable
|
||||
|
||||
## 2. Array/cell parsing from UI text
|
||||
|
||||
If text areas are used for MATLAB expressions, malformed input can break parsing.
|
||||
|
||||
Examples:
|
||||
|
||||
- missing brackets
|
||||
- malformed cell arrays
|
||||
- inconsistent row widths
|
||||
|
||||
Recommendation:
|
||||
|
||||
- use text areas only as an intermediate step
|
||||
- replace key inputs with `UITable` later
|
||||
|
||||
## 3. Flow-model mutual exclusivity
|
||||
|
||||
Gas-water, oil-water, and multi-component are mutually exclusive.
|
||||
If the GUI keeps unrelated fields visible and active, users may edit values that are silently ignored or accidentally used.
|
||||
|
||||
Recommendation:
|
||||
|
||||
- show only the active model section
|
||||
- hide or disable the others
|
||||
|
||||
## 4. Schedule and well table consistency
|
||||
|
||||
The solver expects consistent relations among:
|
||||
|
||||
- `well1`
|
||||
- `welloc`
|
||||
- `well2`
|
||||
- `well_schedules`
|
||||
- `time`
|
||||
- `dtmin`
|
||||
- `dtmax`
|
||||
|
||||
If the user edits one without updating the others, runtime errors are likely.
|
||||
|
||||
## 5. Case-specific discretization assumptions
|
||||
|
||||
Case 1 includes irregular boundary polygon logic.
|
||||
Case 3 uses DP-specific fields.
|
||||
Other cases use different rock defaults.
|
||||
|
||||
If the GUI over-generalizes too early, it may hide case-specific assumptions that are required for correct runs.
|
||||
|
||||
## Recommended Next Step
|
||||
|
||||
The highest-value next step is:
|
||||
|
||||
1. manually build the `.mlapp` layout in App Designer
|
||||
2. keep component names fixed
|
||||
3. then connect each page to the existing backend functions and config structure
|
||||
|
||||
That is the safest path to a maintainable App Designer application.
|
||||
@@ -0,0 +1,332 @@
|
||||
classdef EDFMSimulatorApp < matlab.apps.AppBase
|
||||
properties (Access = public)
|
||||
UIFigure matlab.ui.Figure
|
||||
end
|
||||
|
||||
properties (Access = private)
|
||||
UI struct
|
||||
Config struct
|
||||
Results struct
|
||||
end
|
||||
|
||||
methods (Access = private)
|
||||
function startup(app)
|
||||
app.Config = load_case_template('case01');
|
||||
app.Results = struct();
|
||||
app.refreshUIFromConfig();
|
||||
app.appendLog('Loaded default template: case01');
|
||||
app.updateStatus('Ready');
|
||||
end
|
||||
|
||||
function createComponents(app)
|
||||
app.UIFigure = uifigure('Visible', 'off', 'Name', 'EDFM Simulator App');
|
||||
app.UIFigure.Position = [100 100 1500 900];
|
||||
|
||||
root = uigridlayout(app.UIFigure, [2 1]);
|
||||
root.RowHeight = {44, '1x'};
|
||||
|
||||
top = uigridlayout(root, [1 9]);
|
||||
top.ColumnWidth = {140, 110, 110, 110, 90, 110, 110, '1x', 180};
|
||||
app.UI.TemplateDropDown = uidropdown(top, 'Items', {'case01'}, 'Value', 'case01');
|
||||
app.UI.TemplateDropDown.Layout.Column = 1;
|
||||
app.UI.LoadTemplateButton = uibutton(top, 'push', 'Text', 'Load Template', ...
|
||||
'ButtonPushedFcn', @(~,~) app.onLoadTemplate());
|
||||
app.UI.LoadTemplateButton.Layout.Column = 2;
|
||||
app.UI.ImportConfigButton = uibutton(top, 'push', 'Text', 'Import Config', ...
|
||||
'ButtonPushedFcn', @(~,~) app.onImportConfig());
|
||||
app.UI.ImportConfigButton.Layout.Column = 3;
|
||||
app.UI.ExportConfigButton = uibutton(top, 'push', 'Text', 'Export Config', ...
|
||||
'ButtonPushedFcn', @(~,~) app.onExportConfig());
|
||||
app.UI.ExportConfigButton.Layout.Column = 4;
|
||||
app.UI.RunButton = uibutton(top, 'push', 'Text', 'Run', ...
|
||||
'ButtonPushedFcn', @(~,~) app.onRun());
|
||||
app.UI.RunButton.Layout.Column = 5;
|
||||
app.UI.ImportResultButton = uibutton(top, 'push', 'Text', 'Import Result', ...
|
||||
'ButtonPushedFcn', @(~,~) app.onImportResult());
|
||||
app.UI.ImportResultButton.Layout.Column = 6;
|
||||
app.UI.ExportResultButton = uibutton(top, 'push', 'Text', 'Export Result', ...
|
||||
'ButtonPushedFcn', @(~,~) app.onExportResult());
|
||||
app.UI.ExportResultButton.Layout.Column = 7;
|
||||
app.UI.StatusLabel = uilabel(top, 'Text', 'Status: Ready', 'HorizontalAlignment', 'right');
|
||||
app.UI.StatusLabel.Layout.Column = 9;
|
||||
|
||||
tabs = uitabgroup(root);
|
||||
tabs.Layout.Row = 2;
|
||||
app.UI.Tabs = tabs;
|
||||
app.UI.Part1Tab = uitab(tabs, 'Title', 'Part1 Model');
|
||||
app.UI.Part2Tab = uitab(tabs, 'Title', 'Part2 Grid');
|
||||
app.UI.Part3Tab = uitab(tabs, 'Title', 'Part3 Fracture');
|
||||
app.UI.Part4Tab = uitab(tabs, 'Title', 'Part4 Discretization');
|
||||
app.UI.Part5Tab = uitab(tabs, 'Title', 'Part5 Flow');
|
||||
app.UI.Part6Tab = uitab(tabs, 'Title', 'Part6 Wells');
|
||||
app.UI.Part7Tab = uitab(tabs, 'Title', 'Part7 Solver');
|
||||
app.UI.RunTab = uitab(tabs, 'Title', 'Run');
|
||||
app.UI.ResultTab = uitab(tabs, 'Title', 'Results');
|
||||
|
||||
app.buildPart1();
|
||||
app.buildPart2();
|
||||
app.buildPart3();
|
||||
app.buildPart4();
|
||||
app.buildPart5();
|
||||
app.buildPart6();
|
||||
app.buildPart7();
|
||||
app.buildRunTab();
|
||||
app.buildResultTab();
|
||||
|
||||
app.UIFigure.Visible = 'on';
|
||||
end
|
||||
|
||||
function buildPart1(app)
|
||||
g = uigridlayout(app.UI.Part1Tab, [4 2]); g.RowHeight = {30,30,30,'1x'}; g.ColumnWidth = {160,'1x'};
|
||||
uilabel(g, 'Text', 'Model Flag'); app.UI.ModelFlag = uidropdown(g, 'Items', {'1'}); app.UI.ModelFlag.Layout.Column = 2;
|
||||
lbl = uilabel(g, 'Text', 'Grid Model'); lbl.Layout.Row = 2; lbl.Layout.Column = 1;
|
||||
app.UI.GridModel = uidropdown(g, 'Items', {'1','2'}); app.UI.GridModel.Layout.Row = 2; app.UI.GridModel.Layout.Column = 2;
|
||||
lbl = uilabel(g, 'Text', 'Flow Model'); lbl.Layout.Row = 3; lbl.Layout.Column = 1;
|
||||
app.UI.FlowModel = uidropdown(g, 'Items', {'1','2','3'}); app.UI.FlowModel.Layout.Row = 3; app.UI.FlowModel.Layout.Column = 2;
|
||||
end
|
||||
|
||||
function buildPart2(app)
|
||||
g = uigridlayout(app.UI.Part2Tab, [4 2]); g.ColumnWidth = {130,'1x'}; g.RowHeight = {100,100,100,'1x'};
|
||||
app.createAreaField(g, 1, 'dx', 'Dx');
|
||||
app.createAreaField(g, 2, 'dy', 'Dy');
|
||||
app.createAreaField(g, 3, 'dz', 'Dz');
|
||||
app.createAreaField(g, 4, 'ntg', 'NTG');
|
||||
end
|
||||
|
||||
function buildPart3(app)
|
||||
g = uigridlayout(app.UI.Part3Tab, [5 2]); g.ColumnWidth = {160,'1x'}; g.RowHeight = {30,120,120,120,80};
|
||||
uilabel(g, 'Text', 'Input Style'); app.UI.InputStyle = uidropdown(g, 'Items', {'1','2','3','4'}); app.UI.InputStyle.Layout.Column = 2;
|
||||
app.createAreaField(g, 2, 'fractureInput', 'Input Content');
|
||||
app.createAreaField(g, 3, 'fractureLines', 'Fracture Lines');
|
||||
app.createAreaField(g, 4, 'fractureHeights', 'Fracture Heights');
|
||||
app.createAreaField(g, 5, 'flowBarrier', 'Flow Barrier Flags');
|
||||
end
|
||||
|
||||
function buildPart4(app)
|
||||
g = uigridlayout(app.UI.Part4Tab, [7 2]); g.ColumnWidth = {180,'1x'}; g.RowHeight = {90,60,70,70,70,30,'1x'};
|
||||
app.createAreaField(g, 1, 'boundary', 'Boundary Polygon');
|
||||
app.createAreaField(g, 2, 'invalidLayer', 'Invalid Layer');
|
||||
app.createAreaField(g, 3, 'matrixKx', 'Matrix kx');
|
||||
app.createAreaField(g, 4, 'matrixKy', 'Matrix ky');
|
||||
app.createAreaField(g, 5, 'matrixKz', 'Matrix kz');
|
||||
app.createAreaField(g, 6, 'matrixPori', 'Matrix pori');
|
||||
panel = uipanel(g); panel.Layout.Row = 7; panel.Layout.Column = 2; sub = uigridlayout(panel, [1 6]);
|
||||
uilabel(sub, 'Text', 'prpor'); app.UI.MatrixPrpor = uieditfield(sub, 'numeric');
|
||||
uilabel(sub, 'Text', 'cpor'); app.UI.MatrixCpor = uieditfield(sub, 'numeric');
|
||||
uilabel(sub, 'Text', 'rho'); app.UI.RockDensity = uieditfield(sub, 'numeric');
|
||||
end
|
||||
|
||||
function buildPart5(app)
|
||||
g = uigridlayout(app.UI.Part5Tab, [3 1]); g.RowHeight = {100,'1x',120};
|
||||
init = uipanel(g, 'Title', 'Initial State'); initg = uigridlayout(init, [2 4]);
|
||||
uilabel(initg, 'Text', 'Pressure'); uilabel(initg, 'Text', 'Sw'); uilabel(initg, 'Text', 'Cs'); uilabel(initg, 'Text', 'Cb');
|
||||
app.UI.InitialPressure = uieditfield(initg, 'numeric'); app.UI.InitialPressure.Layout.Row = 2;
|
||||
app.UI.InitialSw = uieditfield(initg, 'numeric'); app.UI.InitialSw.Layout.Row = 2;
|
||||
app.UI.InitialCs = uieditfield(initg, 'numeric'); app.UI.InitialCs.Layout.Row = 2;
|
||||
app.UI.InitialCb = uieditfield(initg, 'numeric'); app.UI.InitialCb.Layout.Row = 2;
|
||||
subtabs = uitabgroup(g);
|
||||
app.UI.GasTab = uitab(subtabs, 'Title', 'Gas-Water');
|
||||
app.UI.OilTab = uitab(subtabs, 'Title', 'Oil-Water');
|
||||
app.UI.MultiTab = uitab(subtabs, 'Title', 'Multi-Component');
|
||||
app.UI.GasArea = uitextarea(uigridlayout(app.UI.GasTab, [1 1]));
|
||||
app.UI.OilArea = uitextarea(uigridlayout(app.UI.OilTab, [1 1]));
|
||||
mg = uigridlayout(app.UI.MultiTab, [2 3]);
|
||||
app.UI.MultiAdsorption = uitextarea(mg); app.UI.MultiNc = uitextarea(mg); app.UI.MultiPc = uitextarea(mg);
|
||||
app.UI.MultiKrNoSurf = uitextarea(mg); app.UI.MultiKrSurf = uitextarea(mg); app.UI.MultiNote = uitextarea(mg, 'Editable', 'off', 'Value', {'Active flow model only.'});
|
||||
hint = uitextarea(g, 'Editable', 'off', 'Value', {'Flow models are mutually exclusive.', 'Only the selected model will be used at run time.'});
|
||||
hint.Layout.Row = 3;
|
||||
end
|
||||
|
||||
function buildPart6(app)
|
||||
g = uigridlayout(app.UI.Part6Tab, [4 2]); g.ColumnWidth = {160,'1x'}; g.RowHeight = {110,110,140,'1x'};
|
||||
app.createAreaField(g, 1, 'well1', 'Well1');
|
||||
app.createAreaField(g, 2, 'welloc', 'Well Locations');
|
||||
app.createAreaField(g, 3, 'well2', 'Well2');
|
||||
p = uipanel(g); p.Layout.Row = 4; p.Layout.Column = 2; sub = uigridlayout(p, [1 4]);
|
||||
app.UI.ScheduleArea = uitextarea(sub); app.UI.TimeArea = uitextarea(sub); app.UI.DtMinArea = uitextarea(sub); app.UI.DtMaxArea = uitextarea(sub);
|
||||
lbl = uilabel(g, 'Text', 'Schedule / Time / dt'); lbl.Layout.Row = 4; lbl.Layout.Column = 1;
|
||||
end
|
||||
|
||||
function buildPart7(app)
|
||||
g = uigridlayout(app.UI.Part7Tab, [2 6]);
|
||||
names = {'YitaP','YitaS','Omega','Nmax','EpsAve','EpsMax'};
|
||||
for i = 1:numel(names)
|
||||
lbl = uilabel(g, 'Text', names{i}); lbl.Layout.Row = 1; lbl.Layout.Column = i;
|
||||
app.UI.(names{i}) = uieditfield(g, 'numeric');
|
||||
app.UI.(names{i}).Layout.Row = 2; app.UI.(names{i}).Layout.Column = i;
|
||||
end
|
||||
end
|
||||
|
||||
function buildRunTab(app)
|
||||
g = uigridlayout(app.UI.RunTab, [2 1]); g.RowHeight = {40,'1x'};
|
||||
uibutton(g, 'push', 'Text', 'Run Current Config', 'ButtonPushedFcn', @(~,~) app.onRun());
|
||||
app.UI.RunLog = uitextarea(g, 'Editable', 'off'); app.UI.RunLog.Layout.Row = 2;
|
||||
end
|
||||
|
||||
function buildResultTab(app)
|
||||
g = uigridlayout(app.UI.ResultTab, [1 2]); g.ColumnWidth = {360,'1x'};
|
||||
app.UI.ResultSummary = uitextarea(g, 'Editable', 'off');
|
||||
app.UI.ResultAxes = uiaxes(g); title(app.UI.ResultAxes, 'Results');
|
||||
end
|
||||
|
||||
function createAreaField(app, parent, row, field_name, label_text)
|
||||
lbl = uilabel(parent, 'Text', label_text);
|
||||
lbl.Layout.Row = row;
|
||||
lbl.Layout.Column = 1;
|
||||
app.UI.(field_name) = uitextarea(parent);
|
||||
app.UI.(field_name).Layout.Row = row;
|
||||
app.UI.(field_name).Layout.Column = 2;
|
||||
end
|
||||
|
||||
function onLoadTemplate(app)
|
||||
app.Config = load_case_template(app.UI.TemplateDropDown.Value);
|
||||
app.refreshUIFromConfig();
|
||||
app.appendLog(['Loaded template: ', app.UI.TemplateDropDown.Value]);
|
||||
app.updateStatus('Template loaded');
|
||||
end
|
||||
|
||||
function onImportConfig(app)
|
||||
[f, p] = uigetfile('*.mat', 'Import Config'); if isequal(f, 0), return; end
|
||||
app.Config = load_config_mat(fullfile(p, f));
|
||||
app.refreshUIFromConfig();
|
||||
app.appendLog(['Imported config: ', fullfile(p, f)]);
|
||||
app.updateStatus('Config imported');
|
||||
end
|
||||
|
||||
function onExportConfig(app)
|
||||
app.pushUIToConfig();
|
||||
[f, p] = uiputfile('*.mat', 'Export Config', 'config.mat'); if isequal(f, 0), return; end
|
||||
save_config_mat(app.Config, fullfile(p, f));
|
||||
app.appendLog(['Exported config: ', fullfile(p, f)]);
|
||||
app.updateStatus('Config exported');
|
||||
end
|
||||
|
||||
function onImportResult(app)
|
||||
[f, p] = uigetfile('*.mat', 'Import Result'); if isequal(f, 0), return; end
|
||||
app.Results = load_results_mat(fullfile(p, f));
|
||||
app.refreshResults();
|
||||
app.updateStatus('Result imported');
|
||||
end
|
||||
|
||||
function onExportResult(app)
|
||||
if isempty(fieldnames(app.Results)), uialert(app.UIFigure, 'No results available.', 'Export Result'); return; end
|
||||
[f, p] = uiputfile('*.mat', 'Export Result', 'results.mat'); if isequal(f, 0), return; end
|
||||
save_results_mat(app.Results, fullfile(p, f));
|
||||
app.appendLog(['Exported result: ', fullfile(p, f)]);
|
||||
app.updateStatus('Result exported');
|
||||
end
|
||||
|
||||
function onRun(app)
|
||||
app.pushUIToConfig();
|
||||
app.updateStatus('Running');
|
||||
app.appendLog('Run started');
|
||||
drawnow;
|
||||
try
|
||||
log_text = evalc('[r, Times, OutputRs, Wellpara, trun] = run_case(app.Config);');
|
||||
app.Results = struct('r', r, 'Times', Times, 'OutputRs', {OutputRs}, 'Wellpara', {Wellpara}, 'trun', trun, 'captured_log', log_text);
|
||||
app.appendLog(log_text);
|
||||
app.refreshResults();
|
||||
app.UI.Tabs.SelectedTab = app.UI.ResultTab;
|
||||
app.updateStatus('Run completed');
|
||||
catch ME
|
||||
app.appendLog(getReport(ME, 'extended', 'hyperlinks', 'off'));
|
||||
app.updateStatus('Run failed');
|
||||
uialert(app.UIFigure, ME.message, 'Run Failed');
|
||||
end
|
||||
end
|
||||
|
||||
function refreshUIFromConfig(app)
|
||||
c = app.Config;
|
||||
app.UI.ModelFlag.Value = string(c.model.modelflag);
|
||||
app.UI.GridModel.Value = string(c.model.grid_model);
|
||||
app.UI.FlowModel.Value = string(c.model.flow_model);
|
||||
app.UI.Dx.Value = splitlines(app.toExpr(c.grid.dx)); app.UI.Dy.Value = splitlines(app.toExpr(c.grid.dy)); app.UI.Dz.Value = splitlines(app.toExpr(c.grid.dz)); app.UI.Ntg.Value = splitlines(app.toExpr(c.grid.NTG));
|
||||
app.UI.InputStyle.Value = string(c.fracture.input_style); app.UI.fractureInput.Value = splitlines(app.toExpr(c.fracture.input_content)); app.UI.fractureLines.Value = splitlines(app.toExpr(c.fracture.fractureLines)); app.UI.fractureHeights.Value = splitlines(app.toExpr(c.fracture.fractureHeights)); app.UI.flowBarrier.Value = splitlines(app.toExpr(c.fracture.flowBarrierFlags));
|
||||
app.UI.boundary.Value = splitlines(app.toExpr(c.discretization.sp.boundary_polygon)); app.UI.invalidLayer.Value = splitlines(app.toExpr(c.discretization.sp.invalid_layer)); app.UI.matrixKx.Value = splitlines(app.toExpr(c.discretization.sp.matrix.kx)); app.UI.matrixKy.Value = splitlines(app.toExpr(c.discretization.sp.matrix.ky)); app.UI.matrixKz.Value = splitlines(app.toExpr(c.discretization.sp.matrix.kz)); app.UI.matrixPori.Value = splitlines(app.toExpr(c.discretization.sp.matrix.pori));
|
||||
app.UI.MatrixPrpor.Value = c.discretization.sp.matrix.prpor; app.UI.MatrixCpor.Value = c.discretization.sp.matrix.cpor; app.UI.RockDensity.Value = c.discretization.sp.matrix.rock_density;
|
||||
app.UI.GasArea.Value = splitlines(app.toExpr(c.flow.gas_water.matrix_relperm_table)); app.UI.OilArea.Value = splitlines(app.toExpr(c.flow.oil_water.matrix_relperm_table)); app.UI.MultiAdsorption.Value = splitlines(app.toExpr(c.flow.multi_component.c_ca_table)); app.UI.MultiNc.Value = splitlines(app.toExpr(c.flow.multi_component.cs_Nc)); app.UI.MultiPc.Value = splitlines(app.toExpr(c.flow.multi_component.PC)); app.UI.MultiKrNoSurf.Value = splitlines(app.toExpr(c.flow.multi_component.kr_nosurf)); app.UI.MultiKrSurf.Value = splitlines(app.toExpr(c.flow.multi_component.kr_surf));
|
||||
app.UI.InitialPressure.Value = app.scalarValue(c.initial.pressure); app.UI.InitialSw.Value = app.scalarValue(c.initial.sw); app.UI.InitialCs.Value = app.scalarValue(c.initial.cs); app.UI.InitialCb.Value = app.scalarValue(c.initial.cb);
|
||||
app.UI.well1.Value = splitlines(app.toExpr(c.wells.well1)); app.UI.welloc.Value = splitlines(app.toExpr(c.wells.welloc)); app.UI.well2.Value = splitlines(app.toExpr(c.wells.well2)); app.UI.ScheduleArea.Value = splitlines(app.toExpr(c.schedule.well_schedules)); app.UI.TimeArea.Value = splitlines(app.toExpr(c.schedule.time)); app.UI.DtMinArea.Value = splitlines(app.toExpr(c.schedule.dtmin)); app.UI.DtMaxArea.Value = splitlines(app.toExpr(c.schedule.dtmax));
|
||||
app.UI.YitaP.Value = c.solver.yitap; app.UI.YitaS.Value = c.solver.yitas; app.UI.Omega.Value = c.solver.omega; app.UI.Nmax.Value = c.solver.Nmax; app.UI.EpsAve.Value = c.solver.epsave; app.UI.EpsMax.Value = c.solver.epsmax;
|
||||
end
|
||||
|
||||
function pushUIToConfig(app)
|
||||
c = app.Config;
|
||||
c.model.modelflag = str2double(app.UI.ModelFlag.Value); c.model.grid_model = str2double(app.UI.GridModel.Value); c.model.flow_model = str2double(app.UI.FlowModel.Value);
|
||||
c.grid.dx = app.parseExpr(app.UI.Dx.Value); c.grid.dy = app.parseExpr(app.UI.Dy.Value); c.grid.dz = app.parseExpr(app.UI.Dz.Value); c.grid.NTG = app.parseExpr(app.UI.Ntg.Value); c.grid.nx = numel(c.grid.dx); c.grid.ny = numel(c.grid.dy); c.grid.nz = numel(c.grid.dz);
|
||||
c.fracture.input_style = str2double(app.UI.InputStyle.Value); c.fracture.input_content = app.parseExpr(app.UI.fractureInput.Value); c.fracture.fractureLines = app.parseExpr(app.UI.fractureLines.Value); c.fracture.fractureHeights = app.parseExpr(app.UI.fractureHeights.Value); c.fracture.flowBarrierFlags = app.parseExpr(app.UI.flowBarrier.Value);
|
||||
c.discretization.sp.boundary_polygon = app.parseExpr(app.UI.boundary.Value); c.discretization.sp.invalid_layer = app.parseExpr(app.UI.invalidLayer.Value); c.discretization.sp.matrix.kx = app.parseExpr(app.UI.matrixKx.Value); c.discretization.sp.matrix.ky = app.parseExpr(app.UI.matrixKy.Value); c.discretization.sp.matrix.kz = app.parseExpr(app.UI.matrixKz.Value); c.discretization.sp.matrix.pori = app.parseExpr(app.UI.matrixPori.Value); c.discretization.sp.matrix.prpor = app.UI.MatrixPrpor.Value; c.discretization.sp.matrix.cpor = app.UI.MatrixCpor.Value; c.discretization.sp.matrix.rock_density = app.UI.RockDensity.Value;
|
||||
c.flow.gas_water.matrix_relperm_table = app.parseExpr(app.UI.GasArea.Value); c.flow.oil_water.matrix_relperm_table = app.parseExpr(app.UI.OilArea.Value); c.flow.multi_component.c_ca_table = app.parseExpr(app.UI.MultiAdsorption.Value); c.flow.multi_component.cs_Nc = app.parseExpr(app.UI.MultiNc.Value); c.flow.multi_component.PC = app.parseExpr(app.UI.MultiPc.Value); c.flow.multi_component.kr_nosurf = app.parseExpr(app.UI.MultiKrNoSurf.Value); c.flow.multi_component.kr_surf = app.parseExpr(app.UI.MultiKrSurf.Value);
|
||||
c.initial.pressure = app.UI.InitialPressure.Value; c.initial.sw = app.UI.InitialSw.Value; c.initial.cs = app.UI.InitialCs.Value; c.initial.cb = app.UI.InitialCb.Value;
|
||||
c.wells.well1 = app.parseExpr(app.UI.well1.Value); c.wells.welloc = app.parseExpr(app.UI.welloc.Value); c.wells.num_fracture_wells = numel(c.wells.welloc); c.wells.well2 = app.parseExpr(app.UI.well2.Value);
|
||||
c.schedule.well_schedules = app.parseExpr(app.UI.ScheduleArea.Value); c.schedule.time = app.parseExpr(app.UI.TimeArea.Value); c.schedule.dtmin = app.parseExpr(app.UI.DtMinArea.Value); c.schedule.dtmax = app.parseExpr(app.UI.DtMaxArea.Value); c.schedule.number_phases = size(c.schedule.well_schedules, 1);
|
||||
c.solver.yitap = app.UI.YitaP.Value; c.solver.yitas = app.UI.YitaS.Value; c.solver.omega = app.UI.Omega.Value; c.solver.Nmax = app.UI.Nmax.Value; c.solver.epsave = app.UI.EpsAve.Value; c.solver.epsmax = app.UI.EpsMax.Value;
|
||||
app.Config = c;
|
||||
end
|
||||
|
||||
function refreshResults(app)
|
||||
if isempty(fieldnames(app.Results)), app.UI.ResultSummary.Value = {'No results loaded.'}; cla(app.UI.ResultAxes); return; end
|
||||
summary = {};
|
||||
if isfield(app.Results, 'Times'), summary{end+1} = ['Time steps: ', num2str(numel(app.Results.Times))]; end %#ok<AGROW>
|
||||
if isfield(app.Results, 'trun') && isstruct(app.Results.trun)
|
||||
if isfield(app.Results.trun, 'run_time'), summary{end+1} = ['Run time: ', num2str(app.Results.trun.run_time)]; end %#ok<AGROW>
|
||||
if isfield(app.Results.trun, 'Newton_step'), summary{end+1} = ['Newton steps: ', num2str(app.Results.trun.Newton_step)]; end %#ok<AGROW>
|
||||
end
|
||||
app.UI.ResultSummary.Value = summary;
|
||||
cla(app.UI.ResultAxes);
|
||||
if isfield(app.Results, 'trun') && isfield(app.Results.trun, 'Newtons_vs_time') && ~isempty(app.Results.trun.Newtons_vs_time)
|
||||
plot(app.UI.ResultAxes, app.Results.trun.Newtons_vs_time(:,1), app.Results.trun.Newtons_vs_time(:,2), '-o'); title(app.UI.ResultAxes, 'Newtons vs Time'); xlabel(app.UI.ResultAxes, 'Time'); ylabel(app.UI.ResultAxes, 'Newton Count');
|
||||
elseif isfield(app.Results, 'Times') && ~isempty(app.Results.Times)
|
||||
plot(app.UI.ResultAxes, app.Results.Times, 1:numel(app.Results.Times), '-o'); title(app.UI.ResultAxes, 'Time Step Index'); xlabel(app.UI.ResultAxes, 'Time'); ylabel(app.UI.ResultAxes, 'Step');
|
||||
end
|
||||
end
|
||||
|
||||
function appendLog(app, txt)
|
||||
lines = string(txt); lines = splitlines(lines);
|
||||
current = string(app.UI.RunLog.Value);
|
||||
if isequal(current, ""), app.UI.RunLog.Value = cellstr(lines); else, app.UI.RunLog.Value = cellstr([current; lines]); end
|
||||
end
|
||||
|
||||
function updateStatus(app, txt)
|
||||
app.UI.StatusLabel.Text = ['Status: ', txt];
|
||||
end
|
||||
|
||||
function out = parseExpr(app, lines) %#ok<INUSL>
|
||||
txt = strtrim(strjoin(string(lines), newline));
|
||||
if txt == "", out = []; else, out = eval(txt); end %#ok<EVLDIR>
|
||||
end
|
||||
|
||||
function txt = toExpr(app, value) %#ok<INUSL>
|
||||
if isempty(value), txt = '[]'; return; end
|
||||
if isnumeric(value) || islogical(value), txt = mat2str(value); return; end
|
||||
if ischar(value), txt = ['''', strrep(value, '''', ''''''), '''']; return; end
|
||||
if isstring(value) && isscalar(value), txt = ['''', strrep(char(value), '''', ''''''), '''']; return; end
|
||||
if iscell(value)
|
||||
rows = cell(size(value,1),1);
|
||||
for i = 1:size(value,1)
|
||||
cols = cell(1,size(value,2));
|
||||
for j = 1:size(value,2), cols{j} = app.toExpr(value{i,j}); end
|
||||
rows{i} = strjoin(cols, ', ');
|
||||
end
|
||||
txt = ['{', strjoin(rows, [';', newline]), '}']; return;
|
||||
end
|
||||
txt = evalc('disp(value)');
|
||||
end
|
||||
|
||||
function value = scalarValue(app, raw) %#ok<INUSL>
|
||||
if isempty(raw), value = 0; elseif isscalar(raw), value = raw; else, value = raw(1); end
|
||||
end
|
||||
end
|
||||
|
||||
methods (Access = public)
|
||||
function app = EDFMSimulatorApp()
|
||||
createComponents(app);
|
||||
registerApp(app, app.UIFigure);
|
||||
runStartupFcn(app, @(~,~) app.startup());
|
||||
end
|
||||
|
||||
function delete(app)
|
||||
delete(app.UIFigure);
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,917 @@
|
||||
classdef EDFM_Simulator_App < matlab.apps.AppBase
|
||||
|
||||
% Properties that correspond to app components
|
||||
properties (Access = public)
|
||||
UIFigure matlab.ui.Figure
|
||||
MainGrid matlab.ui.container.GridLayout
|
||||
TopGrid matlab.ui.container.GridLayout
|
||||
|
||||
TemplateDropDown matlab.ui.control.DropDown
|
||||
LoadTemplateButton matlab.ui.control.Button
|
||||
ImportConfigButton matlab.ui.control.Button
|
||||
ExportConfigButton matlab.ui.control.Button
|
||||
RunButton matlab.ui.control.Button
|
||||
ImportResultButton matlab.ui.control.Button
|
||||
ExportResultButton matlab.ui.control.Button
|
||||
StatusLabel matlab.ui.control.Label
|
||||
|
||||
MainTabGroup matlab.ui.container.TabGroup
|
||||
Part1Tab matlab.ui.container.Tab
|
||||
Part2Tab matlab.ui.container.Tab
|
||||
Part3Tab matlab.ui.container.Tab
|
||||
Part4Tab matlab.ui.container.Tab
|
||||
Part5Tab matlab.ui.container.Tab
|
||||
Part6Tab matlab.ui.container.Tab
|
||||
Part7Tab matlab.ui.container.Tab
|
||||
RunTab matlab.ui.container.Tab
|
||||
ResultTab matlab.ui.container.Tab
|
||||
|
||||
Part1Grid matlab.ui.container.GridLayout
|
||||
ModelFlagLabel matlab.ui.control.Label
|
||||
ModelFlagDropDown matlab.ui.control.DropDown
|
||||
GridModelLabel matlab.ui.control.Label
|
||||
GridModelDropDown matlab.ui.control.DropDown
|
||||
FlowModelLabel matlab.ui.control.Label
|
||||
FlowModelDropDown matlab.ui.control.DropDown
|
||||
|
||||
Part2Grid matlab.ui.container.GridLayout
|
||||
DxLabel matlab.ui.control.Label
|
||||
DxTextArea matlab.ui.control.TextArea
|
||||
DyLabel matlab.ui.control.Label
|
||||
DyTextArea matlab.ui.control.TextArea
|
||||
DzLabel matlab.ui.control.Label
|
||||
DzTextArea matlab.ui.control.TextArea
|
||||
NTGLabel matlab.ui.control.Label
|
||||
NTGTextArea matlab.ui.control.TextArea
|
||||
|
||||
Part3Grid matlab.ui.container.GridLayout
|
||||
FractureInputStyleLabel matlab.ui.control.Label
|
||||
FractureInputStyleDropDown matlab.ui.control.DropDown
|
||||
FractureInputLabel matlab.ui.control.Label
|
||||
FractureInputTextArea matlab.ui.control.TextArea
|
||||
FractureLinesLabel matlab.ui.control.Label
|
||||
FractureLinesTextArea matlab.ui.control.TextArea
|
||||
FractureHeightsLabel matlab.ui.control.Label
|
||||
FractureHeightsTextArea matlab.ui.control.TextArea
|
||||
FlowBarrierFlagsLabel matlab.ui.control.Label
|
||||
FlowBarrierFlagsTextArea matlab.ui.control.TextArea
|
||||
|
||||
Part4Grid matlab.ui.container.GridLayout
|
||||
BoundaryLabel matlab.ui.control.Label
|
||||
BoundaryTextArea matlab.ui.control.TextArea
|
||||
InvalidLayerLabel matlab.ui.control.Label
|
||||
InvalidLayerTextArea matlab.ui.control.TextArea
|
||||
MatrixKxLabel matlab.ui.control.Label
|
||||
MatrixKxTextArea matlab.ui.control.TextArea
|
||||
MatrixKyLabel matlab.ui.control.Label
|
||||
MatrixKyTextArea matlab.ui.control.TextArea
|
||||
MatrixKzLabel matlab.ui.control.Label
|
||||
MatrixKzTextArea matlab.ui.control.TextArea
|
||||
MatrixPoriLabel matlab.ui.control.Label
|
||||
MatrixPoriTextArea matlab.ui.control.TextArea
|
||||
MatrixPrporLabel matlab.ui.control.Label
|
||||
MatrixPrporField matlab.ui.control.NumericEditField
|
||||
MatrixCporLabel matlab.ui.control.Label
|
||||
MatrixCporField matlab.ui.control.NumericEditField
|
||||
RockDensityLabel matlab.ui.control.Label
|
||||
RockDensityField matlab.ui.control.NumericEditField
|
||||
FractureKfLabel matlab.ui.control.Label
|
||||
FractureKfTextArea matlab.ui.control.TextArea
|
||||
FractureWfLabel matlab.ui.control.Label
|
||||
FractureWfTextArea matlab.ui.control.TextArea
|
||||
FracturePorfLabel matlab.ui.control.Label
|
||||
FracturePorfTextArea matlab.ui.control.TextArea
|
||||
|
||||
Part5Grid matlab.ui.container.GridLayout
|
||||
InitialPanel matlab.ui.container.Panel
|
||||
InitialGrid matlab.ui.container.GridLayout
|
||||
InitialPressureLabel matlab.ui.control.Label
|
||||
InitialPressureField matlab.ui.control.NumericEditField
|
||||
InitialSwLabel matlab.ui.control.Label
|
||||
InitialSwField matlab.ui.control.NumericEditField
|
||||
InitialCsLabel matlab.ui.control.Label
|
||||
InitialCsField matlab.ui.control.NumericEditField
|
||||
InitialCbLabel matlab.ui.control.Label
|
||||
InitialCbField matlab.ui.control.NumericEditField
|
||||
|
||||
FlowSubTabGroup matlab.ui.container.TabGroup
|
||||
GasWaterTab matlab.ui.container.Tab
|
||||
OilWaterTab matlab.ui.container.Tab
|
||||
MultiComponentTab matlab.ui.container.Tab
|
||||
|
||||
GasWaterGrid matlab.ui.container.GridLayout
|
||||
GasRelPermLabel matlab.ui.control.Label
|
||||
GasRelPermTextArea matlab.ui.control.TextArea
|
||||
GasPVTLabel matlab.ui.control.Label
|
||||
GasPVTTextArea matlab.ui.control.TextArea
|
||||
|
||||
OilWaterGrid matlab.ui.container.GridLayout
|
||||
OilRelPermLabel matlab.ui.control.Label
|
||||
OilRelPermTextArea matlab.ui.control.TextArea
|
||||
OilPVTLabel matlab.ui.control.Label
|
||||
OilPVTTextArea matlab.ui.control.TextArea
|
||||
|
||||
MultiComponentGrid matlab.ui.container.GridLayout
|
||||
AdsorptionLabel matlab.ui.control.Label
|
||||
AdsorptionTextArea matlab.ui.control.TextArea
|
||||
NcTableLabel matlab.ui.control.Label
|
||||
NcTableTextArea matlab.ui.control.TextArea
|
||||
KrNoSurfLabel matlab.ui.control.Label
|
||||
KrNoSurfTextArea matlab.ui.control.TextArea
|
||||
KrSurfLabel matlab.ui.control.Label
|
||||
KrSurfTextArea matlab.ui.control.TextArea
|
||||
PcTableLabel matlab.ui.control.Label
|
||||
PcTableTextArea matlab.ui.control.TextArea
|
||||
|
||||
Part6Grid matlab.ui.container.GridLayout
|
||||
Well1Label matlab.ui.control.Label
|
||||
Well1Table matlab.ui.control.Table
|
||||
FractureWellLocationLabel matlab.ui.control.Label
|
||||
FractureWellLocationTable matlab.ui.control.Table
|
||||
Well2Label matlab.ui.control.Label
|
||||
Well2Table matlab.ui.control.Table
|
||||
ScheduleLabel matlab.ui.control.Label
|
||||
ScheduleTable matlab.ui.control.Table
|
||||
TimeLabel matlab.ui.control.Label
|
||||
TimeTextArea matlab.ui.control.TextArea
|
||||
DtMinLabel matlab.ui.control.Label
|
||||
DtMinTextArea matlab.ui.control.TextArea
|
||||
DtMaxLabel matlab.ui.control.Label
|
||||
DtMaxTextArea matlab.ui.control.TextArea
|
||||
|
||||
Part7Grid matlab.ui.container.GridLayout
|
||||
YitaPLabel matlab.ui.control.Label
|
||||
YitaPField matlab.ui.control.NumericEditField
|
||||
YitaSLabel matlab.ui.control.Label
|
||||
YitaSField matlab.ui.control.NumericEditField
|
||||
OmegaLabel matlab.ui.control.Label
|
||||
OmegaField matlab.ui.control.NumericEditField
|
||||
NmaxLabel matlab.ui.control.Label
|
||||
NmaxField matlab.ui.control.NumericEditField
|
||||
EpsAveLabel matlab.ui.control.Label
|
||||
EpsAveField matlab.ui.control.NumericEditField
|
||||
EpsMaxLabel matlab.ui.control.Label
|
||||
EpsMaxField matlab.ui.control.NumericEditField
|
||||
|
||||
RunGrid matlab.ui.container.GridLayout
|
||||
RunCurrentConfigButton matlab.ui.control.Button
|
||||
CurrentStageLabel matlab.ui.control.Label
|
||||
CurrentTimeLabel matlab.ui.control.Label
|
||||
CurrentDtLabel matlab.ui.control.Label
|
||||
RunLogTextArea matlab.ui.control.TextArea
|
||||
|
||||
ResultGrid matlab.ui.container.GridLayout
|
||||
ResultLeftGrid matlab.ui.container.GridLayout
|
||||
ResultSummaryLabel matlab.ui.control.Label
|
||||
ResultSummaryTextArea matlab.ui.control.TextArea
|
||||
ResultTypeLabel matlab.ui.control.Label
|
||||
ResultTypeDropDown matlab.ui.control.DropDown
|
||||
PlotResultButton matlab.ui.control.Button
|
||||
ResultAxes matlab.ui.control.UIAxes
|
||||
end
|
||||
|
||||
% Component initialization
|
||||
methods (Access = private)
|
||||
|
||||
% Create UIFigure and components
|
||||
function createComponents(app)
|
||||
|
||||
% Create UIFigure and hide until all components are created
|
||||
app.UIFigure = uifigure('Visible', 'off');
|
||||
app.UIFigure.Position = [100 100 1500 920];
|
||||
app.UIFigure.Name = 'EDFM Simulator App';
|
||||
|
||||
% Create MainGrid
|
||||
app.MainGrid = uigridlayout(app.UIFigure);
|
||||
app.MainGrid.ColumnWidth = {'1x'};
|
||||
app.MainGrid.RowHeight = {48, '1x'};
|
||||
app.MainGrid.Padding = [8 8 8 8];
|
||||
|
||||
% Create TopGrid
|
||||
app.TopGrid = uigridlayout(app.MainGrid);
|
||||
app.TopGrid.Layout.Row = 1;
|
||||
app.TopGrid.Layout.Column = 1;
|
||||
app.TopGrid.RowHeight = {'1x'};
|
||||
app.TopGrid.ColumnWidth = {140, 110, 110, 110, 90, 110, 110, '1x', 180};
|
||||
app.TopGrid.ColumnSpacing = 8;
|
||||
app.TopGrid.Padding = [0 0 0 0];
|
||||
|
||||
% Create top controls
|
||||
app.TemplateDropDown = uidropdown(app.TopGrid);
|
||||
app.TemplateDropDown.Layout.Row = 1;
|
||||
app.TemplateDropDown.Layout.Column = 1;
|
||||
app.TemplateDropDown.Items = {'case01'};
|
||||
app.TemplateDropDown.Value = 'case01';
|
||||
|
||||
app.LoadTemplateButton = uibutton(app.TopGrid, 'push');
|
||||
app.LoadTemplateButton.Layout.Row = 1;
|
||||
app.LoadTemplateButton.Layout.Column = 2;
|
||||
app.LoadTemplateButton.Text = 'Load Template';
|
||||
|
||||
app.ImportConfigButton = uibutton(app.TopGrid, 'push');
|
||||
app.ImportConfigButton.Layout.Row = 1;
|
||||
app.ImportConfigButton.Layout.Column = 3;
|
||||
app.ImportConfigButton.Text = 'Import Config';
|
||||
|
||||
app.ExportConfigButton = uibutton(app.TopGrid, 'push');
|
||||
app.ExportConfigButton.Layout.Row = 1;
|
||||
app.ExportConfigButton.Layout.Column = 4;
|
||||
app.ExportConfigButton.Text = 'Export Config';
|
||||
|
||||
app.RunButton = uibutton(app.TopGrid, 'push');
|
||||
app.RunButton.Layout.Row = 1;
|
||||
app.RunButton.Layout.Column = 5;
|
||||
app.RunButton.Text = 'Run';
|
||||
|
||||
app.ImportResultButton = uibutton(app.TopGrid, 'push');
|
||||
app.ImportResultButton.Layout.Row = 1;
|
||||
app.ImportResultButton.Layout.Column = 6;
|
||||
app.ImportResultButton.Text = 'Import Result';
|
||||
|
||||
app.ExportResultButton = uibutton(app.TopGrid, 'push');
|
||||
app.ExportResultButton.Layout.Row = 1;
|
||||
app.ExportResultButton.Layout.Column = 7;
|
||||
app.ExportResultButton.Text = 'Export Result';
|
||||
|
||||
app.StatusLabel = uilabel(app.TopGrid);
|
||||
app.StatusLabel.Layout.Row = 1;
|
||||
app.StatusLabel.Layout.Column = 9;
|
||||
app.StatusLabel.HorizontalAlignment = 'right';
|
||||
app.StatusLabel.Text = 'Status: Ready';
|
||||
|
||||
% Create MainTabGroup
|
||||
app.MainTabGroup = uitabgroup(app.MainGrid);
|
||||
app.MainTabGroup.Layout.Row = 2;
|
||||
app.MainTabGroup.Layout.Column = 1;
|
||||
|
||||
% Create tabs
|
||||
app.Part1Tab = uitab(app.MainTabGroup);
|
||||
app.Part1Tab.Title = 'Part1 Model';
|
||||
|
||||
app.Part2Tab = uitab(app.MainTabGroup);
|
||||
app.Part2Tab.Title = 'Part2 Grid';
|
||||
|
||||
app.Part3Tab = uitab(app.MainTabGroup);
|
||||
app.Part3Tab.Title = 'Part3 Fracture';
|
||||
|
||||
app.Part4Tab = uitab(app.MainTabGroup);
|
||||
app.Part4Tab.Title = 'Part4 Discretization';
|
||||
|
||||
app.Part5Tab = uitab(app.MainTabGroup);
|
||||
app.Part5Tab.Title = 'Part5 Flow';
|
||||
|
||||
app.Part6Tab = uitab(app.MainTabGroup);
|
||||
app.Part6Tab.Title = 'Part6 Wells';
|
||||
|
||||
app.Part7Tab = uitab(app.MainTabGroup);
|
||||
app.Part7Tab.Title = 'Part7 Solver';
|
||||
|
||||
app.RunTab = uitab(app.MainTabGroup);
|
||||
app.RunTab.Title = 'Run';
|
||||
|
||||
app.ResultTab = uitab(app.MainTabGroup);
|
||||
app.ResultTab.Title = 'Results';
|
||||
|
||||
% ---------------- Part1 ----------------
|
||||
app.Part1Grid = uigridlayout(app.Part1Tab);
|
||||
app.Part1Grid.ColumnWidth = {180, '1x'};
|
||||
app.Part1Grid.RowHeight = {32, 32, 32, '1x'};
|
||||
app.Part1Grid.Padding = [12 12 12 12];
|
||||
|
||||
app.ModelFlagLabel = uilabel(app.Part1Grid);
|
||||
app.ModelFlagLabel.Layout.Row = 1;
|
||||
app.ModelFlagLabel.Layout.Column = 1;
|
||||
app.ModelFlagLabel.Text = 'Model Flag';
|
||||
|
||||
app.ModelFlagDropDown = uidropdown(app.Part1Grid);
|
||||
app.ModelFlagDropDown.Layout.Row = 1;
|
||||
app.ModelFlagDropDown.Layout.Column = 2;
|
||||
app.ModelFlagDropDown.Items = {'1'};
|
||||
app.ModelFlagDropDown.Value = '1';
|
||||
|
||||
app.GridModelLabel = uilabel(app.Part1Grid);
|
||||
app.GridModelLabel.Layout.Row = 2;
|
||||
app.GridModelLabel.Layout.Column = 1;
|
||||
app.GridModelLabel.Text = 'Grid Model';
|
||||
|
||||
app.GridModelDropDown = uidropdown(app.Part1Grid);
|
||||
app.GridModelDropDown.Layout.Row = 2;
|
||||
app.GridModelDropDown.Layout.Column = 2;
|
||||
app.GridModelDropDown.Items = {'1', '2'};
|
||||
app.GridModelDropDown.Value = '1';
|
||||
|
||||
app.FlowModelLabel = uilabel(app.Part1Grid);
|
||||
app.FlowModelLabel.Layout.Row = 3;
|
||||
app.FlowModelLabel.Layout.Column = 1;
|
||||
app.FlowModelLabel.Text = 'Flow Model';
|
||||
|
||||
app.FlowModelDropDown = uidropdown(app.Part1Grid);
|
||||
app.FlowModelDropDown.Layout.Row = 3;
|
||||
app.FlowModelDropDown.Layout.Column = 2;
|
||||
app.FlowModelDropDown.Items = {'1', '2', '3'};
|
||||
app.FlowModelDropDown.Value = '3';
|
||||
|
||||
% ---------------- Part2 ----------------
|
||||
app.Part2Grid = uigridlayout(app.Part2Tab);
|
||||
app.Part2Grid.ColumnWidth = {140, '1x'};
|
||||
app.Part2Grid.RowHeight = {110, 110, 110, '1x'};
|
||||
app.Part2Grid.Padding = [12 12 12 12];
|
||||
|
||||
app.DxLabel = uilabel(app.Part2Grid);
|
||||
app.DxLabel.Layout.Row = 1;
|
||||
app.DxLabel.Layout.Column = 1;
|
||||
app.DxLabel.Text = 'dx';
|
||||
|
||||
app.DxTextArea = uitextarea(app.Part2Grid);
|
||||
app.DxTextArea.Layout.Row = 1;
|
||||
app.DxTextArea.Layout.Column = 2;
|
||||
|
||||
app.DyLabel = uilabel(app.Part2Grid);
|
||||
app.DyLabel.Layout.Row = 2;
|
||||
app.DyLabel.Layout.Column = 1;
|
||||
app.DyLabel.Text = 'dy';
|
||||
|
||||
app.DyTextArea = uitextarea(app.Part2Grid);
|
||||
app.DyTextArea.Layout.Row = 2;
|
||||
app.DyTextArea.Layout.Column = 2;
|
||||
|
||||
app.DzLabel = uilabel(app.Part2Grid);
|
||||
app.DzLabel.Layout.Row = 3;
|
||||
app.DzLabel.Layout.Column = 1;
|
||||
app.DzLabel.Text = 'dz';
|
||||
|
||||
app.DzTextArea = uitextarea(app.Part2Grid);
|
||||
app.DzTextArea.Layout.Row = 3;
|
||||
app.DzTextArea.Layout.Column = 2;
|
||||
|
||||
app.NTGLabel = uilabel(app.Part2Grid);
|
||||
app.NTGLabel.Layout.Row = 4;
|
||||
app.NTGLabel.Layout.Column = 1;
|
||||
app.NTGLabel.Text = 'NTG';
|
||||
|
||||
app.NTGTextArea = uitextarea(app.Part2Grid);
|
||||
app.NTGTextArea.Layout.Row = 4;
|
||||
app.NTGTextArea.Layout.Column = 2;
|
||||
|
||||
% ---------------- Part3 ----------------
|
||||
app.Part3Grid = uigridlayout(app.Part3Tab);
|
||||
app.Part3Grid.ColumnWidth = {170, '1x'};
|
||||
app.Part3Grid.RowHeight = {32, 120, 120, 120, 90};
|
||||
app.Part3Grid.Padding = [12 12 12 12];
|
||||
|
||||
app.FractureInputStyleLabel = uilabel(app.Part3Grid);
|
||||
app.FractureInputStyleLabel.Layout.Row = 1;
|
||||
app.FractureInputStyleLabel.Layout.Column = 1;
|
||||
app.FractureInputStyleLabel.Text = 'Input Style';
|
||||
|
||||
app.FractureInputStyleDropDown = uidropdown(app.Part3Grid);
|
||||
app.FractureInputStyleDropDown.Layout.Row = 1;
|
||||
app.FractureInputStyleDropDown.Layout.Column = 2;
|
||||
app.FractureInputStyleDropDown.Items = {'1', '2', '3', '4'};
|
||||
app.FractureInputStyleDropDown.Value = '1';
|
||||
|
||||
app.FractureInputLabel = uilabel(app.Part3Grid);
|
||||
app.FractureInputLabel.Layout.Row = 2;
|
||||
app.FractureInputLabel.Layout.Column = 1;
|
||||
app.FractureInputLabel.Text = 'Input Content';
|
||||
|
||||
app.FractureInputTextArea = uitextarea(app.Part3Grid);
|
||||
app.FractureInputTextArea.Layout.Row = 2;
|
||||
app.FractureInputTextArea.Layout.Column = 2;
|
||||
|
||||
app.FractureLinesLabel = uilabel(app.Part3Grid);
|
||||
app.FractureLinesLabel.Layout.Row = 3;
|
||||
app.FractureLinesLabel.Layout.Column = 1;
|
||||
app.FractureLinesLabel.Text = 'Fracture Lines';
|
||||
|
||||
app.FractureLinesTextArea = uitextarea(app.Part3Grid);
|
||||
app.FractureLinesTextArea.Layout.Row = 3;
|
||||
app.FractureLinesTextArea.Layout.Column = 2;
|
||||
|
||||
app.FractureHeightsLabel = uilabel(app.Part3Grid);
|
||||
app.FractureHeightsLabel.Layout.Row = 4;
|
||||
app.FractureHeightsLabel.Layout.Column = 1;
|
||||
app.FractureHeightsLabel.Text = 'Fracture Heights';
|
||||
|
||||
app.FractureHeightsTextArea = uitextarea(app.Part3Grid);
|
||||
app.FractureHeightsTextArea.Layout.Row = 4;
|
||||
app.FractureHeightsTextArea.Layout.Column = 2;
|
||||
|
||||
app.FlowBarrierFlagsLabel = uilabel(app.Part3Grid);
|
||||
app.FlowBarrierFlagsLabel.Layout.Row = 5;
|
||||
app.FlowBarrierFlagsLabel.Layout.Column = 1;
|
||||
app.FlowBarrierFlagsLabel.Text = 'Flow Barrier Flags';
|
||||
|
||||
app.FlowBarrierFlagsTextArea = uitextarea(app.Part3Grid);
|
||||
app.FlowBarrierFlagsTextArea.Layout.Row = 5;
|
||||
app.FlowBarrierFlagsTextArea.Layout.Column = 2;
|
||||
|
||||
% ---------------- Part4 ----------------
|
||||
app.Part4Grid = uigridlayout(app.Part4Tab);
|
||||
app.Part4Grid.ColumnWidth = {180, '1x', 180, '1x'};
|
||||
app.Part4Grid.RowHeight = {90, 60, 90, 90, 90, 32, '1x'};
|
||||
app.Part4Grid.Padding = [12 12 12 12];
|
||||
|
||||
app.BoundaryLabel = uilabel(app.Part4Grid);
|
||||
app.BoundaryLabel.Layout.Row = 1;
|
||||
app.BoundaryLabel.Layout.Column = 1;
|
||||
app.BoundaryLabel.Text = 'Boundary Polygon';
|
||||
|
||||
app.BoundaryTextArea = uitextarea(app.Part4Grid);
|
||||
app.BoundaryTextArea.Layout.Row = 1;
|
||||
app.BoundaryTextArea.Layout.Column = [2 4];
|
||||
|
||||
app.InvalidLayerLabel = uilabel(app.Part4Grid);
|
||||
app.InvalidLayerLabel.Layout.Row = 2;
|
||||
app.InvalidLayerLabel.Layout.Column = 1;
|
||||
app.InvalidLayerLabel.Text = 'Invalid Layer';
|
||||
|
||||
app.InvalidLayerTextArea = uitextarea(app.Part4Grid);
|
||||
app.InvalidLayerTextArea.Layout.Row = 2;
|
||||
app.InvalidLayerTextArea.Layout.Column = [2 4];
|
||||
|
||||
app.MatrixKxLabel = uilabel(app.Part4Grid);
|
||||
app.MatrixKxLabel.Layout.Row = 3;
|
||||
app.MatrixKxLabel.Layout.Column = 1;
|
||||
app.MatrixKxLabel.Text = 'Matrix kx';
|
||||
|
||||
app.MatrixKxTextArea = uitextarea(app.Part4Grid);
|
||||
app.MatrixKxTextArea.Layout.Row = 3;
|
||||
app.MatrixKxTextArea.Layout.Column = 2;
|
||||
|
||||
app.MatrixKyLabel = uilabel(app.Part4Grid);
|
||||
app.MatrixKyLabel.Layout.Row = 3;
|
||||
app.MatrixKyLabel.Layout.Column = 3;
|
||||
app.MatrixKyLabel.Text = 'Matrix ky';
|
||||
|
||||
app.MatrixKyTextArea = uitextarea(app.Part4Grid);
|
||||
app.MatrixKyTextArea.Layout.Row = 3;
|
||||
app.MatrixKyTextArea.Layout.Column = 4;
|
||||
|
||||
app.MatrixKzLabel = uilabel(app.Part4Grid);
|
||||
app.MatrixKzLabel.Layout.Row = 4;
|
||||
app.MatrixKzLabel.Layout.Column = 1;
|
||||
app.MatrixKzLabel.Text = 'Matrix kz';
|
||||
|
||||
app.MatrixKzTextArea = uitextarea(app.Part4Grid);
|
||||
app.MatrixKzTextArea.Layout.Row = 4;
|
||||
app.MatrixKzTextArea.Layout.Column = 2;
|
||||
|
||||
app.MatrixPoriLabel = uilabel(app.Part4Grid);
|
||||
app.MatrixPoriLabel.Layout.Row = 4;
|
||||
app.MatrixPoriLabel.Layout.Column = 3;
|
||||
app.MatrixPoriLabel.Text = 'Matrix pori';
|
||||
|
||||
app.MatrixPoriTextArea = uitextarea(app.Part4Grid);
|
||||
app.MatrixPoriTextArea.Layout.Row = 4;
|
||||
app.MatrixPoriTextArea.Layout.Column = 4;
|
||||
|
||||
app.FractureKfLabel = uilabel(app.Part4Grid);
|
||||
app.FractureKfLabel.Layout.Row = 5;
|
||||
app.FractureKfLabel.Layout.Column = 1;
|
||||
app.FractureKfLabel.Text = 'Fracture Kf';
|
||||
|
||||
app.FractureKfTextArea = uitextarea(app.Part4Grid);
|
||||
app.FractureKfTextArea.Layout.Row = 5;
|
||||
app.FractureKfTextArea.Layout.Column = 2;
|
||||
|
||||
app.FractureWfLabel = uilabel(app.Part4Grid);
|
||||
app.FractureWfLabel.Layout.Row = 5;
|
||||
app.FractureWfLabel.Layout.Column = 3;
|
||||
app.FractureWfLabel.Text = 'Fracture Wf';
|
||||
|
||||
app.FractureWfTextArea = uitextarea(app.Part4Grid);
|
||||
app.FractureWfTextArea.Layout.Row = 5;
|
||||
app.FractureWfTextArea.Layout.Column = 4;
|
||||
|
||||
app.MatrixPrporLabel = uilabel(app.Part4Grid);
|
||||
app.MatrixPrporLabel.Layout.Row = 6;
|
||||
app.MatrixPrporLabel.Layout.Column = 1;
|
||||
app.MatrixPrporLabel.Text = 'Matrix prpor';
|
||||
|
||||
app.MatrixPrporField = uieditfield(app.Part4Grid, 'numeric');
|
||||
app.MatrixPrporField.Layout.Row = 6;
|
||||
app.MatrixPrporField.Layout.Column = 2;
|
||||
|
||||
app.MatrixCporLabel = uilabel(app.Part4Grid);
|
||||
app.MatrixCporLabel.Layout.Row = 6;
|
||||
app.MatrixCporLabel.Layout.Column = 3;
|
||||
app.MatrixCporLabel.Text = 'Matrix cpor';
|
||||
|
||||
app.MatrixCporField = uieditfield(app.Part4Grid, 'numeric');
|
||||
app.MatrixCporField.Layout.Row = 6;
|
||||
app.MatrixCporField.Layout.Column = 4;
|
||||
|
||||
app.RockDensityLabel = uilabel(app.Part4Grid);
|
||||
app.RockDensityLabel.Layout.Row = 7;
|
||||
app.RockDensityLabel.Layout.Column = 1;
|
||||
app.RockDensityLabel.Text = 'Rock Density';
|
||||
|
||||
app.RockDensityField = uieditfield(app.Part4Grid, 'numeric');
|
||||
app.RockDensityField.Layout.Row = 7;
|
||||
app.RockDensityField.Layout.Column = 2;
|
||||
|
||||
app.FracturePorfLabel = uilabel(app.Part4Grid);
|
||||
app.FracturePorfLabel.Layout.Row = 7;
|
||||
app.FracturePorfLabel.Layout.Column = 3;
|
||||
app.FracturePorfLabel.Text = 'Fracture Porf';
|
||||
|
||||
app.FracturePorfTextArea = uitextarea(app.Part4Grid);
|
||||
app.FracturePorfTextArea.Layout.Row = 7;
|
||||
app.FracturePorfTextArea.Layout.Column = 4;
|
||||
|
||||
% ---------------- Part5 ----------------
|
||||
app.Part5Grid = uigridlayout(app.Part5Tab);
|
||||
app.Part5Grid.ColumnWidth = {'1x'};
|
||||
app.Part5Grid.RowHeight = {110, '1x'};
|
||||
app.Part5Grid.Padding = [12 12 12 12];
|
||||
|
||||
app.InitialPanel = uipanel(app.Part5Grid);
|
||||
app.InitialPanel.Layout.Row = 1;
|
||||
app.InitialPanel.Layout.Column = 1;
|
||||
app.InitialPanel.Title = 'Initial State';
|
||||
|
||||
app.InitialGrid = uigridlayout(app.InitialPanel);
|
||||
app.InitialGrid.ColumnWidth = {120, 120, 120, 120};
|
||||
app.InitialGrid.RowHeight = {26, 32};
|
||||
|
||||
app.InitialPressureLabel = uilabel(app.InitialGrid);
|
||||
app.InitialPressureLabel.Layout.Row = 1;
|
||||
app.InitialPressureLabel.Layout.Column = 1;
|
||||
app.InitialPressureLabel.Text = 'Pressure';
|
||||
|
||||
app.InitialPressureField = uieditfield(app.InitialGrid, 'numeric');
|
||||
app.InitialPressureField.Layout.Row = 2;
|
||||
app.InitialPressureField.Layout.Column = 1;
|
||||
|
||||
app.InitialSwLabel = uilabel(app.InitialGrid);
|
||||
app.InitialSwLabel.Layout.Row = 1;
|
||||
app.InitialSwLabel.Layout.Column = 2;
|
||||
app.InitialSwLabel.Text = 'Sw';
|
||||
|
||||
app.InitialSwField = uieditfield(app.InitialGrid, 'numeric');
|
||||
app.InitialSwField.Layout.Row = 2;
|
||||
app.InitialSwField.Layout.Column = 2;
|
||||
|
||||
app.InitialCsLabel = uilabel(app.InitialGrid);
|
||||
app.InitialCsLabel.Layout.Row = 1;
|
||||
app.InitialCsLabel.Layout.Column = 3;
|
||||
app.InitialCsLabel.Text = 'Cs';
|
||||
|
||||
app.InitialCsField = uieditfield(app.InitialGrid, 'numeric');
|
||||
app.InitialCsField.Layout.Row = 2;
|
||||
app.InitialCsField.Layout.Column = 3;
|
||||
|
||||
app.InitialCbLabel = uilabel(app.InitialGrid);
|
||||
app.InitialCbLabel.Layout.Row = 1;
|
||||
app.InitialCbLabel.Layout.Column = 4;
|
||||
app.InitialCbLabel.Text = 'Cb';
|
||||
|
||||
app.InitialCbField = uieditfield(app.InitialGrid, 'numeric');
|
||||
app.InitialCbField.Layout.Row = 2;
|
||||
app.InitialCbField.Layout.Column = 4;
|
||||
|
||||
app.FlowSubTabGroup = uitabgroup(app.Part5Grid);
|
||||
app.FlowSubTabGroup.Layout.Row = 2;
|
||||
app.FlowSubTabGroup.Layout.Column = 1;
|
||||
|
||||
app.GasWaterTab = uitab(app.FlowSubTabGroup);
|
||||
app.GasWaterTab.Title = 'Gas-Water';
|
||||
|
||||
app.OilWaterTab = uitab(app.FlowSubTabGroup);
|
||||
app.OilWaterTab.Title = 'Oil-Water';
|
||||
|
||||
app.MultiComponentTab = uitab(app.FlowSubTabGroup);
|
||||
app.MultiComponentTab.Title = 'Multi-Component';
|
||||
|
||||
app.GasWaterGrid = uigridlayout(app.GasWaterTab);
|
||||
app.GasWaterGrid.ColumnWidth = {180, '1x'};
|
||||
app.GasWaterGrid.RowHeight = {140, '1x'};
|
||||
app.GasWaterGrid.Padding = [12 12 12 12];
|
||||
|
||||
app.GasRelPermLabel = uilabel(app.GasWaterGrid);
|
||||
app.GasRelPermLabel.Layout.Row = 1;
|
||||
app.GasRelPermLabel.Layout.Column = 1;
|
||||
app.GasRelPermLabel.Text = 'Gas RelPerm Table';
|
||||
|
||||
app.GasRelPermTextArea = uitextarea(app.GasWaterGrid);
|
||||
app.GasRelPermTextArea.Layout.Row = 1;
|
||||
app.GasRelPermTextArea.Layout.Column = 2;
|
||||
|
||||
app.GasPVTLabel = uilabel(app.GasWaterGrid);
|
||||
app.GasPVTLabel.Layout.Row = 2;
|
||||
app.GasPVTLabel.Layout.Column = 1;
|
||||
app.GasPVTLabel.Text = 'Gas PVT Text';
|
||||
|
||||
app.GasPVTTextArea = uitextarea(app.GasWaterGrid);
|
||||
app.GasPVTTextArea.Layout.Row = 2;
|
||||
app.GasPVTTextArea.Layout.Column = 2;
|
||||
|
||||
app.OilWaterGrid = uigridlayout(app.OilWaterTab);
|
||||
app.OilWaterGrid.ColumnWidth = {180, '1x'};
|
||||
app.OilWaterGrid.RowHeight = {140, '1x'};
|
||||
app.OilWaterGrid.Padding = [12 12 12 12];
|
||||
|
||||
app.OilRelPermLabel = uilabel(app.OilWaterGrid);
|
||||
app.OilRelPermLabel.Layout.Row = 1;
|
||||
app.OilRelPermLabel.Layout.Column = 1;
|
||||
app.OilRelPermLabel.Text = 'Oil RelPerm Table';
|
||||
|
||||
app.OilRelPermTextArea = uitextarea(app.OilWaterGrid);
|
||||
app.OilRelPermTextArea.Layout.Row = 1;
|
||||
app.OilRelPermTextArea.Layout.Column = 2;
|
||||
|
||||
app.OilPVTLabel = uilabel(app.OilWaterGrid);
|
||||
app.OilPVTLabel.Layout.Row = 2;
|
||||
app.OilPVTLabel.Layout.Column = 1;
|
||||
app.OilPVTLabel.Text = 'Oil PVT Text';
|
||||
|
||||
app.OilPVTTextArea = uitextarea(app.OilWaterGrid);
|
||||
app.OilPVTTextArea.Layout.Row = 2;
|
||||
app.OilPVTTextArea.Layout.Column = 2;
|
||||
|
||||
app.MultiComponentGrid = uigridlayout(app.MultiComponentTab);
|
||||
app.MultiComponentGrid.ColumnWidth = {180, '1x', 180, '1x'};
|
||||
app.MultiComponentGrid.RowHeight = {120, 120, 120};
|
||||
app.MultiComponentGrid.Padding = [12 12 12 12];
|
||||
|
||||
app.AdsorptionLabel = uilabel(app.MultiComponentGrid);
|
||||
app.AdsorptionLabel.Layout.Row = 1;
|
||||
app.AdsorptionLabel.Layout.Column = 1;
|
||||
app.AdsorptionLabel.Text = 'Adsorption Table';
|
||||
|
||||
app.AdsorptionTextArea = uitextarea(app.MultiComponentGrid);
|
||||
app.AdsorptionTextArea.Layout.Row = 1;
|
||||
app.AdsorptionTextArea.Layout.Column = 2;
|
||||
|
||||
app.NcTableLabel = uilabel(app.MultiComponentGrid);
|
||||
app.NcTableLabel.Layout.Row = 1;
|
||||
app.NcTableLabel.Layout.Column = 3;
|
||||
app.NcTableLabel.Text = 'Nc Table';
|
||||
|
||||
app.NcTableTextArea = uitextarea(app.MultiComponentGrid);
|
||||
app.NcTableTextArea.Layout.Row = 1;
|
||||
app.NcTableTextArea.Layout.Column = 4;
|
||||
|
||||
app.KrNoSurfLabel = uilabel(app.MultiComponentGrid);
|
||||
app.KrNoSurfLabel.Layout.Row = 2;
|
||||
app.KrNoSurfLabel.Layout.Column = 1;
|
||||
app.KrNoSurfLabel.Text = 'Kr No Surf';
|
||||
|
||||
app.KrNoSurfTextArea = uitextarea(app.MultiComponentGrid);
|
||||
app.KrNoSurfTextArea.Layout.Row = 2;
|
||||
app.KrNoSurfTextArea.Layout.Column = 2;
|
||||
|
||||
app.KrSurfLabel = uilabel(app.MultiComponentGrid);
|
||||
app.KrSurfLabel.Layout.Row = 2;
|
||||
app.KrSurfLabel.Layout.Column = 3;
|
||||
app.KrSurfLabel.Text = 'Kr Surf';
|
||||
|
||||
app.KrSurfTextArea = uitextarea(app.MultiComponentGrid);
|
||||
app.KrSurfTextArea.Layout.Row = 2;
|
||||
app.KrSurfTextArea.Layout.Column = 4;
|
||||
|
||||
app.PcTableLabel = uilabel(app.MultiComponentGrid);
|
||||
app.PcTableLabel.Layout.Row = 3;
|
||||
app.PcTableLabel.Layout.Column = 1;
|
||||
app.PcTableLabel.Text = 'Pc Table';
|
||||
|
||||
app.PcTableTextArea = uitextarea(app.MultiComponentGrid);
|
||||
app.PcTableTextArea.Layout.Row = 3;
|
||||
app.PcTableTextArea.Layout.Column = [2 4];
|
||||
|
||||
% ---------------- Part6 ----------------
|
||||
app.Part6Grid = uigridlayout(app.Part6Tab);
|
||||
app.Part6Grid.ColumnWidth = {180, '1x'};
|
||||
app.Part6Grid.RowHeight = {120, 120, 120, 160, 80, 80, '1x'};
|
||||
app.Part6Grid.Padding = [12 12 12 12];
|
||||
|
||||
app.Well1Label = uilabel(app.Part6Grid);
|
||||
app.Well1Label.Layout.Row = 1;
|
||||
app.Well1Label.Layout.Column = 1;
|
||||
app.Well1Label.Text = 'Well1';
|
||||
|
||||
app.Well1Table = uitable(app.Part6Grid);
|
||||
app.Well1Table.Layout.Row = 1;
|
||||
app.Well1Table.Layout.Column = 2;
|
||||
|
||||
app.FractureWellLocationLabel = uilabel(app.Part6Grid);
|
||||
app.FractureWellLocationLabel.Layout.Row = 2;
|
||||
app.FractureWellLocationLabel.Layout.Column = 1;
|
||||
app.FractureWellLocationLabel.Text = 'Fracture Well Locations';
|
||||
|
||||
app.FractureWellLocationTable = uitable(app.Part6Grid);
|
||||
app.FractureWellLocationTable.Layout.Row = 2;
|
||||
app.FractureWellLocationTable.Layout.Column = 2;
|
||||
|
||||
app.Well2Label = uilabel(app.Part6Grid);
|
||||
app.Well2Label.Layout.Row = 3;
|
||||
app.Well2Label.Layout.Column = 1;
|
||||
app.Well2Label.Text = 'Well2';
|
||||
|
||||
app.Well2Table = uitable(app.Part6Grid);
|
||||
app.Well2Table.Layout.Row = 3;
|
||||
app.Well2Table.Layout.Column = 2;
|
||||
|
||||
app.ScheduleLabel = uilabel(app.Part6Grid);
|
||||
app.ScheduleLabel.Layout.Row = 4;
|
||||
app.ScheduleLabel.Layout.Column = 1;
|
||||
app.ScheduleLabel.Text = 'Schedule';
|
||||
|
||||
app.ScheduleTable = uitable(app.Part6Grid);
|
||||
app.ScheduleTable.Layout.Row = 4;
|
||||
app.ScheduleTable.Layout.Column = 2;
|
||||
|
||||
app.TimeLabel = uilabel(app.Part6Grid);
|
||||
app.TimeLabel.Layout.Row = 5;
|
||||
app.TimeLabel.Layout.Column = 1;
|
||||
app.TimeLabel.Text = 'Time';
|
||||
|
||||
app.TimeTextArea = uitextarea(app.Part6Grid);
|
||||
app.TimeTextArea.Layout.Row = 5;
|
||||
app.TimeTextArea.Layout.Column = 2;
|
||||
|
||||
app.DtMinLabel = uilabel(app.Part6Grid);
|
||||
app.DtMinLabel.Layout.Row = 6;
|
||||
app.DtMinLabel.Layout.Column = 1;
|
||||
app.DtMinLabel.Text = 'dtmin';
|
||||
|
||||
app.DtMinTextArea = uitextarea(app.Part6Grid);
|
||||
app.DtMinTextArea.Layout.Row = 6;
|
||||
app.DtMinTextArea.Layout.Column = 2;
|
||||
|
||||
app.DtMaxLabel = uilabel(app.Part6Grid);
|
||||
app.DtMaxLabel.Layout.Row = 7;
|
||||
app.DtMaxLabel.Layout.Column = 1;
|
||||
app.DtMaxLabel.Text = 'dtmax';
|
||||
|
||||
app.DtMaxTextArea = uitextarea(app.Part6Grid);
|
||||
app.DtMaxTextArea.Layout.Row = 7;
|
||||
app.DtMaxTextArea.Layout.Column = 2;
|
||||
|
||||
% ---------------- Part7 ----------------
|
||||
app.Part7Grid = uigridlayout(app.Part7Tab);
|
||||
app.Part7Grid.ColumnWidth = {100, 100, 100, 100, 100, 100};
|
||||
app.Part7Grid.RowHeight = {26, 32, '1x'};
|
||||
app.Part7Grid.Padding = [12 12 12 12];
|
||||
|
||||
app.YitaPLabel = uilabel(app.Part7Grid);
|
||||
app.YitaPLabel.Layout.Row = 1;
|
||||
app.YitaPLabel.Layout.Column = 1;
|
||||
app.YitaPLabel.Text = 'yitap';
|
||||
|
||||
app.YitaPField = uieditfield(app.Part7Grid, 'numeric');
|
||||
app.YitaPField.Layout.Row = 2;
|
||||
app.YitaPField.Layout.Column = 1;
|
||||
|
||||
app.YitaSLabel = uilabel(app.Part7Grid);
|
||||
app.YitaSLabel.Layout.Row = 1;
|
||||
app.YitaSLabel.Layout.Column = 2;
|
||||
app.YitaSLabel.Text = 'yitas';
|
||||
|
||||
app.YitaSField = uieditfield(app.Part7Grid, 'numeric');
|
||||
app.YitaSField.Layout.Row = 2;
|
||||
app.YitaSField.Layout.Column = 2;
|
||||
|
||||
app.OmegaLabel = uilabel(app.Part7Grid);
|
||||
app.OmegaLabel.Layout.Row = 1;
|
||||
app.OmegaLabel.Layout.Column = 3;
|
||||
app.OmegaLabel.Text = 'omega';
|
||||
|
||||
app.OmegaField = uieditfield(app.Part7Grid, 'numeric');
|
||||
app.OmegaField.Layout.Row = 2;
|
||||
app.OmegaField.Layout.Column = 3;
|
||||
|
||||
app.NmaxLabel = uilabel(app.Part7Grid);
|
||||
app.NmaxLabel.Layout.Row = 1;
|
||||
app.NmaxLabel.Layout.Column = 4;
|
||||
app.NmaxLabel.Text = 'Nmax';
|
||||
|
||||
app.NmaxField = uieditfield(app.Part7Grid, 'numeric');
|
||||
app.NmaxField.Layout.Row = 2;
|
||||
app.NmaxField.Layout.Column = 4;
|
||||
|
||||
app.EpsAveLabel = uilabel(app.Part7Grid);
|
||||
app.EpsAveLabel.Layout.Row = 1;
|
||||
app.EpsAveLabel.Layout.Column = 5;
|
||||
app.EpsAveLabel.Text = 'epsave';
|
||||
|
||||
app.EpsAveField = uieditfield(app.Part7Grid, 'numeric');
|
||||
app.EpsAveField.Layout.Row = 2;
|
||||
app.EpsAveField.Layout.Column = 5;
|
||||
|
||||
app.EpsMaxLabel = uilabel(app.Part7Grid);
|
||||
app.EpsMaxLabel.Layout.Row = 1;
|
||||
app.EpsMaxLabel.Layout.Column = 6;
|
||||
app.EpsMaxLabel.Text = 'epsmax';
|
||||
|
||||
app.EpsMaxField = uieditfield(app.Part7Grid, 'numeric');
|
||||
app.EpsMaxField.Layout.Row = 2;
|
||||
app.EpsMaxField.Layout.Column = 6;
|
||||
|
||||
% ---------------- RunTab ----------------
|
||||
app.RunGrid = uigridlayout(app.RunTab);
|
||||
app.RunGrid.ColumnWidth = {140, 180, 180, '1x'};
|
||||
app.RunGrid.RowHeight = {36, '1x'};
|
||||
app.RunGrid.Padding = [12 12 12 12];
|
||||
|
||||
app.RunCurrentConfigButton = uibutton(app.RunGrid, 'push');
|
||||
app.RunCurrentConfigButton.Layout.Row = 1;
|
||||
app.RunCurrentConfigButton.Layout.Column = 1;
|
||||
app.RunCurrentConfigButton.Text = 'Run Current Config';
|
||||
|
||||
app.CurrentStageLabel = uilabel(app.RunGrid);
|
||||
app.CurrentStageLabel.Layout.Row = 1;
|
||||
app.CurrentStageLabel.Layout.Column = 2;
|
||||
app.CurrentStageLabel.Text = 'Stage: -';
|
||||
|
||||
app.CurrentTimeLabel = uilabel(app.RunGrid);
|
||||
app.CurrentTimeLabel.Layout.Row = 1;
|
||||
app.CurrentTimeLabel.Layout.Column = 3;
|
||||
app.CurrentTimeLabel.Text = 'Time: -';
|
||||
|
||||
app.CurrentDtLabel = uilabel(app.RunGrid);
|
||||
app.CurrentDtLabel.Layout.Row = 1;
|
||||
app.CurrentDtLabel.Layout.Column = 4;
|
||||
app.CurrentDtLabel.Text = 'dt: -';
|
||||
|
||||
app.RunLogTextArea = uitextarea(app.RunGrid);
|
||||
app.RunLogTextArea.Layout.Row = 2;
|
||||
app.RunLogTextArea.Layout.Column = [1 4];
|
||||
app.RunLogTextArea.Editable = 'off';
|
||||
|
||||
% ---------------- ResultTab ----------------
|
||||
app.ResultGrid = uigridlayout(app.ResultTab);
|
||||
app.ResultGrid.ColumnWidth = {360, '1x'};
|
||||
app.ResultGrid.RowHeight = {'1x'};
|
||||
app.ResultGrid.Padding = [12 12 12 12];
|
||||
|
||||
app.ResultLeftGrid = uigridlayout(app.ResultGrid);
|
||||
app.ResultLeftGrid.Layout.Row = 1;
|
||||
app.ResultLeftGrid.Layout.Column = 1;
|
||||
app.ResultLeftGrid.ColumnWidth = {'1x'};
|
||||
app.ResultLeftGrid.RowHeight = {24, 180, 24, 32, 36, '1x'};
|
||||
|
||||
app.ResultSummaryLabel = uilabel(app.ResultLeftGrid);
|
||||
app.ResultSummaryLabel.Layout.Row = 1;
|
||||
app.ResultSummaryLabel.Layout.Column = 1;
|
||||
app.ResultSummaryLabel.Text = 'Result Summary';
|
||||
|
||||
app.ResultSummaryTextArea = uitextarea(app.ResultLeftGrid);
|
||||
app.ResultSummaryTextArea.Layout.Row = 2;
|
||||
app.ResultSummaryTextArea.Layout.Column = 1;
|
||||
app.ResultSummaryTextArea.Editable = 'off';
|
||||
|
||||
app.ResultTypeLabel = uilabel(app.ResultLeftGrid);
|
||||
app.ResultTypeLabel.Layout.Row = 3;
|
||||
app.ResultTypeLabel.Layout.Column = 1;
|
||||
app.ResultTypeLabel.Text = 'Result Type';
|
||||
|
||||
app.ResultTypeDropDown = uidropdown(app.ResultLeftGrid);
|
||||
app.ResultTypeDropDown.Layout.Row = 4;
|
||||
app.ResultTypeDropDown.Layout.Column = 1;
|
||||
app.ResultTypeDropDown.Items = {'Time Steps', 'Newtons vs Time'};
|
||||
app.ResultTypeDropDown.Value = 'Time Steps';
|
||||
|
||||
app.PlotResultButton = uibutton(app.ResultLeftGrid, 'push');
|
||||
app.PlotResultButton.Layout.Row = 5;
|
||||
app.PlotResultButton.Layout.Column = 1;
|
||||
app.PlotResultButton.Text = 'Plot Result';
|
||||
|
||||
app.ResultAxes = uiaxes(app.ResultGrid);
|
||||
app.ResultAxes.Layout.Row = 1;
|
||||
app.ResultAxes.Layout.Column = 2;
|
||||
title(app.ResultAxes, 'Results');
|
||||
xlabel(app.ResultAxes, 'X');
|
||||
ylabel(app.ResultAxes, 'Y');
|
||||
|
||||
% Show the figure after all components are created
|
||||
app.UIFigure.Visible = 'on';
|
||||
end
|
||||
end
|
||||
|
||||
% App creation and deletion
|
||||
methods (Access = public)
|
||||
|
||||
% Construct app
|
||||
function app = EDFM_Simulator_App
|
||||
|
||||
% Create UIFigure and components
|
||||
createComponents(app)
|
||||
|
||||
% Register the app with App Designer
|
||||
registerApp(app, app.UIFigure)
|
||||
|
||||
if nargout == 0
|
||||
clear app
|
||||
end
|
||||
end
|
||||
|
||||
% Code that executes before app deletion
|
||||
function delete(app)
|
||||
|
||||
% Delete UIFigure when app is deleted
|
||||
delete(app.UIFigure)
|
||||
end
|
||||
end
|
||||
end
|
||||
Binary file not shown.
@@ -0,0 +1,5 @@
|
||||
function app = launch_edfm_simulator_app()
|
||||
%LAUNCH_EDFM_SIMULATOR_APP Launch the EDFM Simulator App.
|
||||
|
||||
startup;
|
||||
app = EDFMSimulatorApp();
|
||||
@@ -0,0 +1,248 @@
|
||||
function config = create_empty_config()
|
||||
%CREATE_EMPTY_CONFIG Create a unified GUI/runtime config skeleton.
|
||||
|
||||
config = struct();
|
||||
|
||||
config.meta = struct( ...
|
||||
'case_name', '', ...
|
||||
'case_id', '', ...
|
||||
'description', '', ...
|
||||
'source_case_folder', '', ...
|
||||
'created_from_template', '', ...
|
||||
'version', '0.1');
|
||||
|
||||
config.model = struct( ...
|
||||
'modelflag', 1, ...
|
||||
'grid_model', 1, ...
|
||||
'flow_model', 1);
|
||||
|
||||
config.grid = struct( ...
|
||||
'dx', [], ...
|
||||
'dy', [], ...
|
||||
'dz', [], ...
|
||||
'nx', 0, ...
|
||||
'ny', 0, ...
|
||||
'nz', 0, ...
|
||||
'NTG', [], ...
|
||||
'coordinates', [], ...
|
||||
'nodes', [], ...
|
||||
'nP', 0, ...
|
||||
'nmc', 0, ...
|
||||
'dxv', [], ...
|
||||
'dyv', [], ...
|
||||
'dzv', [], ...
|
||||
'zm', [], ...
|
||||
'vm', [], ...
|
||||
'xrao', [], ...
|
||||
'yrao', [], ...
|
||||
'zrao', [], ...
|
||||
'cell_mid_coords', []);
|
||||
|
||||
config.fracture = struct( ...
|
||||
'input_style', 1, ...
|
||||
'input_content', {{}}, ...
|
||||
'f', [], ...
|
||||
'fellip', [], ...
|
||||
'fractureLines', [], ...
|
||||
'fractureHeights', [], ...
|
||||
'flowBarrierFlags', [], ...
|
||||
'frac_information', [], ...
|
||||
'nf', 0);
|
||||
|
||||
config.discretization = struct( ...
|
||||
'mode', 1, ...
|
||||
'use_operator', true, ...
|
||||
'sp', struct( ...
|
||||
'boundary_polygon', [], ...
|
||||
'invalid_layer', [], ...
|
||||
'valid_grids', [], ...
|
||||
'matrix', struct( ...
|
||||
'kx', [], ...
|
||||
'ky', [], ...
|
||||
'kz', [], ...
|
||||
'pori', [], ...
|
||||
'prpor', 20, ...
|
||||
'cpor', 1.0e-5, ...
|
||||
'rock_density', 2700), ...
|
||||
'fracture', struct( ...
|
||||
'Kf', [], ...
|
||||
'Wf', [], ...
|
||||
'Porf', [], ...
|
||||
'prporf', 20, ...
|
||||
'cporf', 1.0e-5), ...
|
||||
'stress', struct( ...
|
||||
'fracture_factor', 0, ...
|
||||
'matrix_factor', 0, ...
|
||||
'ref_pressure', 20)), ...
|
||||
'dp', struct( ...
|
||||
'valid_grids', [], ...
|
||||
'NTG', [], ...
|
||||
'prpor', 20, ...
|
||||
'cpor', 1.0e-5, ...
|
||||
'rock_density', 2700, ...
|
||||
'fracture_layer', struct( ...
|
||||
'kx', [], ...
|
||||
'ky', [], ...
|
||||
'kz', [], ...
|
||||
'pori', []), ...
|
||||
'matrix_layer', struct( ...
|
||||
'kx', [], ...
|
||||
'ky', [], ...
|
||||
'kz', [], ...
|
||||
'pori', []), ...
|
||||
'shape_factor', [], ...
|
||||
'fracture', struct( ...
|
||||
'Kf', [], ...
|
||||
'Wf', [], ...
|
||||
'Porf', [], ...
|
||||
'prporf', 20, ...
|
||||
'cporf', 1.0e-5), ...
|
||||
'stress', struct( ...
|
||||
'fracture_factor', 0, ...
|
||||
'matrix_factor', 0, ...
|
||||
'ref_pressure', 20)), ...
|
||||
'notes', '');
|
||||
|
||||
config.flow = struct( ...
|
||||
'gas_water', struct( ...
|
||||
'gas_prop', struct( ...
|
||||
'VL', 0, ...
|
||||
'PL', 0, ...
|
||||
'Kn', 0, ...
|
||||
'Kn_modified_factor', 1, ...
|
||||
'beta_non_darcy_flow', 0), ...
|
||||
'p_grad_threshold', 0, ...
|
||||
'density_g_sc', 0, ...
|
||||
'density_w_sc', 1000, ...
|
||||
'gas_model', 1, ...
|
||||
'prg', [], ...
|
||||
'Bgi', [], ...
|
||||
'cg', [], ...
|
||||
'vgi', [], ...
|
||||
'cvg', [], ...
|
||||
'Ppr', [], ...
|
||||
'BG', [], ...
|
||||
'MUG', [], ...
|
||||
'prw', [], ...
|
||||
'Bwi', [], ...
|
||||
'cw', [], ...
|
||||
'vwi', [], ...
|
||||
'cvw', [], ...
|
||||
'ifpcgl', 0, ...
|
||||
'Ppr', [], ...
|
||||
'BG', [], ...
|
||||
'MUG', [], ...
|
||||
'matrix_relperm_table', [], ...
|
||||
'fracture_relperm_table', []), ...
|
||||
'oil_water', struct( ...
|
||||
'density_o_sc', 0, ...
|
||||
'density_w_sc', 1000, ...
|
||||
'oil_model', 1, ...
|
||||
'pro', [], ...
|
||||
'Boi', [], ...
|
||||
'co', [], ...
|
||||
'voi', [], ...
|
||||
'cvo', [], ...
|
||||
'Ppr', [], ...
|
||||
'BO', [], ...
|
||||
'MUO', [], ...
|
||||
'prw', [], ...
|
||||
'Bwi', [], ...
|
||||
'cw', [], ...
|
||||
'vwi', [], ...
|
||||
'cvw', [], ...
|
||||
'ifpcow', 0, ...
|
||||
'Ppr', [], ...
|
||||
'BO', [], ...
|
||||
'MUO', [], ...
|
||||
'matrix_relperm_table', [], ...
|
||||
'fracture_relperm_table', [], ...
|
||||
'beta_non_darcy_flow', 0, ...
|
||||
'p_grad_threshold', 0), ...
|
||||
'multi_component', struct( ...
|
||||
'Ds', [], ...
|
||||
'Db', [], ...
|
||||
'c_ca_table', [], ...
|
||||
'cs_data', [], ...
|
||||
'cb_data', [], ...
|
||||
'csa_data', [], ...
|
||||
'cba_data', [], ...
|
||||
'R', [], ...
|
||||
'Vm', [], ...
|
||||
'Temperature', [], ...
|
||||
'chemistry_cof', [], ...
|
||||
'x_matrix', 0.9, ...
|
||||
'x_fracture', 1.0, ...
|
||||
'cs_Nc', [], ...
|
||||
'Nc_nosurf', [], ...
|
||||
'Nc_surf', [], ...
|
||||
'kr_nosurf', [], ...
|
||||
'kr_surf', [], ...
|
||||
'PC', [], ...
|
||||
'cs_Nc_fracture', [], ...
|
||||
'kr_nosurf_fracture', [], ...
|
||||
'kr_surf_fracture', [], ...
|
||||
'PC_fracture', [], ...
|
||||
'ifpcgl', 0, ...
|
||||
'p_grad_threshold', 0, ...
|
||||
'gas_prop', struct( ...
|
||||
'VL', 0, ...
|
||||
'PL', 0, ...
|
||||
'Kn', 0, ...
|
||||
'Kn_modified_factor', 1, ...
|
||||
'stress_factor_fracture', 0, ...
|
||||
'stress_factor_matrix', 0, ...
|
||||
'stress_factor_ref_pressure', 20, ...
|
||||
'beta_non_darcy_flow', 0), ...
|
||||
'density_g_sc', 0, ...
|
||||
'density_w_sc', 1000, ...
|
||||
'gas_model', 1, ...
|
||||
'prg', [], ...
|
||||
'Bgi', [], ...
|
||||
'cg', [], ...
|
||||
'vgi', [], ...
|
||||
'cvg', [], ...
|
||||
'Ppr', [], ...
|
||||
'BG', [], ...
|
||||
'MUG', [], ...
|
||||
'prw', [], ...
|
||||
'Bwi', [], ...
|
||||
'cw', [], ...
|
||||
'vwi', [], ...
|
||||
'cvw', [], ...
|
||||
'number_state_variables', 4));
|
||||
|
||||
config.initial = struct( ...
|
||||
'pressure', [], ...
|
||||
'sw', [], ...
|
||||
'cs', [], ...
|
||||
'cb', []);
|
||||
|
||||
config.wells = struct( ...
|
||||
'well1', {{}}, ...
|
||||
'num_fracture_wells', 0, ...
|
||||
'welloc', {{}}, ...
|
||||
'perfnum', {{}}, ...
|
||||
'well2', {{}}, ...
|
||||
'Wellc', []);
|
||||
|
||||
config.schedule = struct( ...
|
||||
'number_phases', 0, ...
|
||||
'well_schedules', {{}}, ...
|
||||
'time', [], ...
|
||||
'dtmax', [], ...
|
||||
'dtmin', []);
|
||||
|
||||
config.solver = struct( ...
|
||||
'yitap', 5, ...
|
||||
'yitas', 0.04, ...
|
||||
'omega', 0.5, ...
|
||||
'Nmax', 50, ...
|
||||
'epsave', 1e-6, ...
|
||||
'epsmax', 1e-6);
|
||||
|
||||
config.output = struct( ...
|
||||
'save_input_path', '', ...
|
||||
'save_result_path', '', ...
|
||||
'result_name', '', ...
|
||||
'plot_requests', {{}});
|
||||
@@ -0,0 +1,13 @@
|
||||
function config = load_config_json(file_path)
|
||||
%LOAD_CONFIG_JSON Load a config struct from a JSON file.
|
||||
|
||||
arguments
|
||||
file_path (1,:) char
|
||||
end
|
||||
|
||||
if ~exist(file_path, 'file')
|
||||
error('load_config_json:FileNotFound', 'Config file not found: %s', file_path);
|
||||
end
|
||||
|
||||
json_text = fileread(file_path);
|
||||
config = jsondecode(json_text);
|
||||
@@ -0,0 +1,18 @@
|
||||
function config = load_config_mat(file_path)
|
||||
%LOAD_CONFIG_MAT Load config struct from a MAT file.
|
||||
|
||||
arguments
|
||||
file_path (1,:) char
|
||||
end
|
||||
|
||||
if ~exist(file_path, 'file')
|
||||
error('load_config_mat:FileNotFound', 'Config file not found: %s', file_path);
|
||||
end
|
||||
|
||||
data = load(file_path, '-mat');
|
||||
if ~isfield(data, 'config')
|
||||
error('load_config_mat:MissingConfigVariable', ...
|
||||
'MAT file does not contain variable ''config'': %s', file_path);
|
||||
end
|
||||
|
||||
config = data.config;
|
||||
@@ -0,0 +1,21 @@
|
||||
function save_config_json(config, file_path)
|
||||
%SAVE_CONFIG_JSON Save a config struct to a JSON file.
|
||||
|
||||
arguments
|
||||
config (1,1) struct
|
||||
file_path (1,:) char
|
||||
end
|
||||
|
||||
folder_path = fileparts(file_path);
|
||||
if ~isempty(folder_path) && ~exist(folder_path, 'dir')
|
||||
mkdir(folder_path);
|
||||
end
|
||||
|
||||
json_text = jsonencode(config, PrettyPrint=true);
|
||||
fid = fopen(file_path, 'w');
|
||||
if fid == -1
|
||||
error('save_config_json:FileOpenFailed', 'Cannot open file: %s', file_path);
|
||||
end
|
||||
|
||||
cleanup_obj = onCleanup(@() fclose(fid));
|
||||
fprintf(fid, '%s', json_text);
|
||||
@@ -0,0 +1,14 @@
|
||||
function save_config_mat(config, file_path)
|
||||
%SAVE_CONFIG_MAT Save config struct to a MAT file.
|
||||
|
||||
arguments
|
||||
config (1,1) struct
|
||||
file_path (1,:) char
|
||||
end
|
||||
|
||||
folder_path = fileparts(file_path);
|
||||
if ~isempty(folder_path) && ~exist(folder_path, 'dir')
|
||||
mkdir(folder_path);
|
||||
end
|
||||
|
||||
save(file_path, 'config', '-mat');
|
||||
@@ -0,0 +1,18 @@
|
||||
function results = load_results_mat(file_path)
|
||||
%LOAD_RESULTS_MAT Load results struct from a MAT file.
|
||||
|
||||
arguments
|
||||
file_path (1,:) char
|
||||
end
|
||||
|
||||
if ~exist(file_path, 'file')
|
||||
error('load_results_mat:FileNotFound', 'Results file not found: %s', file_path);
|
||||
end
|
||||
|
||||
data = load(file_path, '-mat');
|
||||
if ~isfield(data, 'results')
|
||||
error('load_results_mat:MissingResultsVariable', ...
|
||||
'MAT file does not contain variable ''results'': %s', file_path);
|
||||
end
|
||||
|
||||
results = data.results;
|
||||
@@ -0,0 +1,14 @@
|
||||
function save_results_mat(results, file_path)
|
||||
%SAVE_RESULTS_MAT Save results struct to a MAT file.
|
||||
|
||||
arguments
|
||||
results (1,1) struct
|
||||
file_path (1,:) char
|
||||
end
|
||||
|
||||
folder_path = fileparts(file_path);
|
||||
if ~isempty(folder_path) && ~exist(folder_path, 'dir')
|
||||
mkdir(folder_path);
|
||||
end
|
||||
|
||||
save(file_path, 'results', '-mat');
|
||||
@@ -0,0 +1,413 @@
|
||||
function [r, Times, OutputRs, Wellpara, trun] = run_case(config)
|
||||
%RUN_CASE Execute a simulation from unified config.
|
||||
%
|
||||
% This is the first migration step from hard-coded main1.m scripts toward a
|
||||
% unified GUI entry point. The current implementation is intended to
|
||||
% reproduce case-template runs while the remaining flow-model internals are
|
||||
% still being normalized.
|
||||
|
||||
arguments
|
||||
config (1,1) struct
|
||||
end
|
||||
|
||||
project_root = fileparts(fileparts(fileparts(mfilename('fullpath'))));
|
||||
source_case_folder = resolve_source_case_folder(project_root, config.meta);
|
||||
if isempty(source_case_folder)
|
||||
error('run_case:MissingSourceCaseFolder', ...
|
||||
'config.meta.source_case_folder is required.');
|
||||
end
|
||||
|
||||
if ~isfolder(source_case_folder)
|
||||
error('run_case:SourceCaseFolderNotFound', ...
|
||||
'Source case folder not found: %s', source_case_folder);
|
||||
end
|
||||
|
||||
addpath(genpath(project_root));
|
||||
|
||||
old_dir = pwd;
|
||||
cleanup_obj = onCleanup(@() cd(old_dir));
|
||||
cd(source_case_folder);
|
||||
|
||||
overall_tic = tic;
|
||||
|
||||
config.grid.nx = numel(config.grid.dx);
|
||||
config.grid.ny = numel(config.grid.dy);
|
||||
config.grid.nz = numel(config.grid.dz);
|
||||
|
||||
r = GridProp_pre( ...
|
||||
config.grid.dx, ...
|
||||
config.grid.dy, ...
|
||||
config.grid.dz, ...
|
||||
config.grid.nx, ...
|
||||
config.grid.ny, ...
|
||||
config.grid.nz, ...
|
||||
config.grid.NTG);
|
||||
|
||||
[f, fellip, frac_information, nf] = build_fracture_inputs(config.fracture);
|
||||
|
||||
modelflag = config.model.modelflag;
|
||||
grid_model = config.model.grid_model;
|
||||
flow_model = config.model.flow_model;
|
||||
|
||||
if grid_model == 1
|
||||
r = grid_discretization_SP_model(modelflag, r, f, frac_information, fellip, nf);
|
||||
elseif grid_model == 2
|
||||
r = grid_discretization_DP_model(modelflag, r, f, frac_information, fellip, nf);
|
||||
else
|
||||
error('run_case:UnsupportedGridModel', 'Unsupported grid model: %d', grid_model);
|
||||
end
|
||||
|
||||
os = OperatorRS(r.N, r.nex, r.nc);
|
||||
|
||||
[fluid_model, state0] = build_flow_inputs(flow_model, r, config);
|
||||
|
||||
well1 = handle_well1(config.wells.well1, r);
|
||||
[well2, welloc] = build_fracture_wells(config.wells, r);
|
||||
Wellc = handle_well1_well2(well1, well2, welloc, r);
|
||||
|
||||
[Times, OutputRs, Wellpara, trun] = solver_NR( ...
|
||||
r, ...
|
||||
flow_model, ...
|
||||
fluid_model, ...
|
||||
os, ...
|
||||
state0, ...
|
||||
config.solver.yitap, ...
|
||||
config.solver.yitas, ...
|
||||
config.solver.omega, ...
|
||||
config.solver.Nmax, ...
|
||||
config.solver.epsave, ...
|
||||
config.solver.epsmax, ...
|
||||
config.schedule.dtmin, ...
|
||||
config.schedule.dtmax, ...
|
||||
Wellc, ...
|
||||
config.schedule.time, ...
|
||||
config.schedule.well_schedules);
|
||||
|
||||
trun.run_time = toc(overall_tic);
|
||||
end
|
||||
|
||||
function source_case_folder = resolve_source_case_folder(project_root, meta_config)
|
||||
source_case_folder = meta_config.source_case_folder;
|
||||
|
||||
if isfolder(source_case_folder)
|
||||
return;
|
||||
end
|
||||
|
||||
case_id = lower(string(meta_config.case_id));
|
||||
switch case_id
|
||||
case "case01"
|
||||
source_case_folder = find_case_folder_by_index(project_root, 1);
|
||||
otherwise
|
||||
if isempty(source_case_folder) || startsWith(string(source_case_folder), "CASE")
|
||||
source_case_folder = '';
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function source_case_folder = find_case_folder_by_index(project_root, case_index)
|
||||
folder_candidates = dir(fullfile(project_root, sprintf('*%d-*', case_index)));
|
||||
folder_candidates = folder_candidates([folder_candidates.isdir]);
|
||||
|
||||
if isempty(folder_candidates)
|
||||
source_case_folder = '';
|
||||
else
|
||||
source_case_folder = fullfile(project_root, folder_candidates(1).name);
|
||||
end
|
||||
end
|
||||
|
||||
function [f, fellip, frac_information, nf] = build_fracture_inputs(fracture_config)
|
||||
input_style = fracture_config.input_style;
|
||||
|
||||
switch input_style
|
||||
case 1
|
||||
[f, fellip] = sort_fracture(fracture_config.input_content);
|
||||
m = size(f, 1);
|
||||
n = size(fellip, 1);
|
||||
nf = (m + n) / 5;
|
||||
frac_information = fractureInformation_input_engineering_vector( ...
|
||||
f, fellip, fracture_config.flowBarrierFlags);
|
||||
case 2
|
||||
f = fracture_config.f;
|
||||
fellip = fracture_config.fellip;
|
||||
m = size(f, 1);
|
||||
n = size(fellip, 1);
|
||||
nf = (m + n) / 5;
|
||||
frac_information = fractureInformation_input_engineering_vector(f, fellip);
|
||||
case 3
|
||||
fellip = fracture_config.fellip;
|
||||
[f, frac_information] = input_fracture_2D( ...
|
||||
fracture_config.fractureLines, ...
|
||||
fracture_config.fractureHeights, ...
|
||||
fracture_config.flowBarrierFlags);
|
||||
m = size(f, 1);
|
||||
n = size(fellip, 1);
|
||||
nf = (m + n) / 5;
|
||||
otherwise
|
||||
error('run_case:UnsupportedFractureInputStyle', ...
|
||||
'Unsupported fracture input style: %d', input_style);
|
||||
end
|
||||
end
|
||||
|
||||
function [fluid_model, state0] = build_flow_inputs(flow_model, r, config)
|
||||
switch flow_model
|
||||
case 1
|
||||
if has_complete_gas_water_config(config.flow.gas_water)
|
||||
[fluid_model, state0] = build_gas_water_flow_from_config( ...
|
||||
config.flow.gas_water, config.initial, r);
|
||||
else
|
||||
[fluid_model, state0] = gas_water_flow(r);
|
||||
end
|
||||
case 2
|
||||
if has_complete_oil_water_config(config.flow.oil_water)
|
||||
[fluid_model, state0] = build_oil_water_flow_from_config( ...
|
||||
config.flow.oil_water, config.initial, r);
|
||||
else
|
||||
[fluid_model, state0] = oil_water_flow(r);
|
||||
end
|
||||
case 3
|
||||
if has_complete_multicomponent_config(config.flow.multi_component)
|
||||
[fluid_model, state0] = build_multi_component_flow_from_config( ...
|
||||
config.flow.multi_component, config.initial, r);
|
||||
else
|
||||
[fluid_model, state0] = multi_component_flow(r);
|
||||
end
|
||||
otherwise
|
||||
error('run_case:UnsupportedFlowModel', ...
|
||||
'Unsupported flow model: %d', flow_model);
|
||||
end
|
||||
end
|
||||
|
||||
function tf = has_complete_gas_water_config(gw)
|
||||
required_fields = { ...
|
||||
'density_g_sc', 'density_w_sc', 'gas_model', 'prw', 'Bwi', 'cw', ...
|
||||
'vwi', 'cvw', 'ifpcgl', 'matrix_relperm_table', 'fracture_relperm_table', ...
|
||||
'p_grad_threshold'};
|
||||
|
||||
tf = true;
|
||||
for i = 1:numel(required_fields)
|
||||
field_name = required_fields{i};
|
||||
if ~isfield(gw, field_name) || isempty(gw.(field_name))
|
||||
tf = false;
|
||||
return;
|
||||
end
|
||||
end
|
||||
|
||||
if ~isfield(gw, 'gas_prop') || isempty(gw.gas_prop)
|
||||
tf = false;
|
||||
return;
|
||||
end
|
||||
|
||||
if gw.gas_model == 1
|
||||
tf = all(isfield(gw, {'prg', 'Bgi', 'cg', 'vgi', 'cvg'})) && ...
|
||||
~isempty(gw.prg) && ~isempty(gw.Bgi) && ~isempty(gw.cg) && ...
|
||||
~isempty(gw.vgi) && ~isempty(gw.cvg);
|
||||
else
|
||||
tf = all(isfield(gw, {'Ppr', 'BG', 'MUG'})) && ...
|
||||
~isempty(gw.Ppr) && ~isempty(gw.BG) && ~isempty(gw.MUG);
|
||||
end
|
||||
end
|
||||
|
||||
function tf = has_complete_oil_water_config(ow)
|
||||
required_fields = { ...
|
||||
'density_o_sc', 'density_w_sc', 'oil_model', 'prw', 'Bwi', 'cw', ...
|
||||
'vwi', 'cvw', 'ifpcow', 'matrix_relperm_table', 'fracture_relperm_table', ...
|
||||
'beta_non_darcy_flow', 'p_grad_threshold'};
|
||||
|
||||
tf = true;
|
||||
for i = 1:numel(required_fields)
|
||||
field_name = required_fields{i};
|
||||
if ~isfield(ow, field_name) || isempty(ow.(field_name))
|
||||
tf = false;
|
||||
return;
|
||||
end
|
||||
end
|
||||
|
||||
if ow.oil_model == 1
|
||||
tf = all(isfield(ow, {'pro', 'Boi', 'co', 'voi', 'cvo'})) && ...
|
||||
~isempty(ow.pro) && ~isempty(ow.Boi) && ~isempty(ow.co) && ...
|
||||
~isempty(ow.voi) && ~isempty(ow.cvo);
|
||||
else
|
||||
tf = all(isfield(ow, {'Ppr', 'BO', 'MUO'})) && ...
|
||||
~isempty(ow.Ppr) && ~isempty(ow.BO) && ~isempty(ow.MUO);
|
||||
end
|
||||
end
|
||||
|
||||
function [f, state0] = build_gas_water_flow_from_config(gw, initial_config, r)
|
||||
if gw.gas_model == 1
|
||||
[Ppr, BG, MUG] = cal_gas_prop(gw.prg, gw.Bgi, gw.cg, gw.vgi, gw.cvg);
|
||||
else
|
||||
Ppr = gw.Ppr;
|
||||
BG = gw.BG;
|
||||
MUG = gw.MUG;
|
||||
end
|
||||
|
||||
matrix_table = gw.matrix_relperm_table;
|
||||
fracture_table = gw.fracture_relperm_table;
|
||||
|
||||
f = fluidPVT_gas_water_flow( ...
|
||||
Ppr, BG, MUG, gw.Bwi, gw.prw, gw.cw, gw.vwi, gw.cvw, ...
|
||||
matrix_table(:, 1), matrix_table(:, 3), matrix_table(:, 2), matrix_table(:, 4), ...
|
||||
fracture_table(:, 1), fracture_table(:, 3), fracture_table(:, 2), fracture_table(:, 4), ...
|
||||
gw.density_g_sc, gw.ifpcgl, r.rpt);
|
||||
|
||||
gas_prop = gw.gas_prop;
|
||||
c1 = 1;
|
||||
c2 = 8 / 9;
|
||||
gas_prop.Kn_modified_factor = 1 + 8 * c1 * gas_prop.Kn + 16 * c2 * gas_prop.Kn^2;
|
||||
|
||||
f.Dwsi = gw.density_w_sc;
|
||||
f.Dgsi = gw.density_g_sc;
|
||||
f.gas_prop = gas_prop;
|
||||
f.p_grad_threshold = gw.p_grad_threshold;
|
||||
|
||||
total_cells = r.nmc + r.nfc;
|
||||
pressure0 = expand_initial_value(initial_config.pressure, total_cells);
|
||||
sw0 = expand_initial_value(initial_config.sw, total_cells);
|
||||
state0 = initialRS_gas_water_flow(pressure0, sw0);
|
||||
end
|
||||
|
||||
function [f, state0] = build_oil_water_flow_from_config(ow, initial_config, r)
|
||||
if ow.oil_model == 1
|
||||
[Ppr, BO, MUO] = cal_oil_prop(ow.pro, ow.Boi, ow.co, ow.voi, ow.cvo);
|
||||
else
|
||||
Ppr = ow.Ppr;
|
||||
BO = ow.BO;
|
||||
MUO = ow.MUO;
|
||||
end
|
||||
|
||||
matrix_table = ow.matrix_relperm_table;
|
||||
fracture_table = ow.fracture_relperm_table;
|
||||
|
||||
f = fluidPVT_oil_water_flow( ...
|
||||
Ppr, BO, MUO, ow.Bwi, ow.prw, ow.cw, ow.vwi, ow.cvw, ...
|
||||
matrix_table(:, 1), matrix_table(:, 3), matrix_table(:, 2), matrix_table(:, 4), ...
|
||||
fracture_table(:, 1), fracture_table(:, 3), fracture_table(:, 2), fracture_table(:, 4), ...
|
||||
ow.density_o_sc, ow.ifpcow, r.rpt);
|
||||
|
||||
f.beta_non_Darcy_flow = ow.beta_non_darcy_flow;
|
||||
f.Dwsi = ow.density_w_sc;
|
||||
f.Dosi = ow.density_o_sc;
|
||||
f.p_grad_threshold = ow.p_grad_threshold;
|
||||
|
||||
total_cells = r.nmc + r.nfc;
|
||||
pressure0 = expand_initial_value(initial_config.pressure, total_cells);
|
||||
sw0 = expand_initial_value(initial_config.sw, total_cells);
|
||||
state0 = initialRS_oil_water_flow(pressure0, sw0);
|
||||
end
|
||||
|
||||
function tf = has_complete_multicomponent_config(mc)
|
||||
required_fields = { ...
|
||||
'Ds', 'Db', 'c_ca_table', 'R', 'Vm', 'Temperature', ...
|
||||
'cs_Nc', 'kr_nosurf', 'kr_surf', 'PC', ...
|
||||
'cs_Nc_fracture', 'kr_nosurf_fracture', 'kr_surf_fracture', 'PC_fracture', ...
|
||||
'density_g_sc', 'density_w_sc', 'gas_model', 'prw', 'Bwi', 'cw', 'vwi', 'cvw'};
|
||||
|
||||
tf = true;
|
||||
for i = 1:numel(required_fields)
|
||||
field_name = required_fields{i};
|
||||
if ~isfield(mc, field_name) || isempty(mc.(field_name))
|
||||
tf = false;
|
||||
return;
|
||||
end
|
||||
end
|
||||
|
||||
if ~isfield(mc, 'gas_prop') || isempty(mc.gas_prop)
|
||||
tf = false;
|
||||
return;
|
||||
end
|
||||
|
||||
if mc.gas_model == 1
|
||||
tf = all(isfield(mc, {'prg', 'Bgi', 'cg', 'vgi', 'cvg'})) && ...
|
||||
~isempty(mc.prg) && ~isempty(mc.Bgi) && ~isempty(mc.cg) && ...
|
||||
~isempty(mc.vgi) && ~isempty(mc.cvg);
|
||||
else
|
||||
tf = all(isfield(mc, {'Ppr', 'BG', 'MUG'})) && ...
|
||||
~isempty(mc.Ppr) && ~isempty(mc.BG) && ~isempty(mc.MUG);
|
||||
end
|
||||
end
|
||||
|
||||
function [f, state0] = build_multi_component_flow_from_config(mc, initial_config, r)
|
||||
cs_data = mc.c_ca_table(:, 1);
|
||||
cb_data = mc.c_ca_table(:, 1);
|
||||
csa_data = mc.c_ca_table(:, 2) * 1e-3;
|
||||
cba_data = mc.c_ca_table(:, 3) * 1e-3;
|
||||
Nc_nosurf = min(mc.cs_Nc(:, 2));
|
||||
Nc_surf = max(mc.cs_Nc(:, 2));
|
||||
|
||||
if mc.gas_model == 1
|
||||
[Ppr, BG, MUG] = cal_gas_prop(mc.prg, mc.Bgi, mc.cg, mc.vgi, mc.cvg);
|
||||
else
|
||||
Ppr = mc.Ppr;
|
||||
BG = mc.BG;
|
||||
MUG = mc.MUG;
|
||||
end
|
||||
|
||||
f = fluidPVT_new( ...
|
||||
Ppr, BG, MUG, mc.Bwi, mc.prw, mc.cw, mc.vwi, mc.cvw, ...
|
||||
mc.ifpcgl, r.rpt, cs_data, csa_data, cb_data, cba_data, ...
|
||||
mc.cs_Nc, Nc_nosurf, Nc_surf, mc.kr_nosurf, mc.kr_surf, mc.PC, ...
|
||||
mc.cs_Nc_fracture, mc.kr_nosurf_fracture, mc.kr_surf_fracture, mc.PC_fracture);
|
||||
|
||||
gas_prop = mc.gas_prop;
|
||||
c1 = 1;
|
||||
c2 = 8 / 9;
|
||||
gas_prop.Kn_modified_factor = 1 + 8 * c1 * gas_prop.Kn + 16 * c2 * gas_prop.Kn^2;
|
||||
|
||||
f.Dwsi = mc.density_w_sc;
|
||||
f.Dgsi = mc.density_g_sc;
|
||||
f.gas_prop = gas_prop;
|
||||
f.Ds = mc.Ds;
|
||||
f.Db = mc.Db;
|
||||
f.chemistry_cof = mc.R * mc.Temperature / mc.Vm * 1e-3 / 10;
|
||||
f.p_grad_threshold = mc.p_grad_threshold;
|
||||
f.number_state_variables = mc.number_state_variables;
|
||||
|
||||
total_cells = r.nmc + r.nfc;
|
||||
matrix_x = default_if_empty(mc, 'x_matrix', 0.9);
|
||||
fracture_x = default_if_empty(mc, 'x_fracture', 1.0);
|
||||
f.x_total = [matrix_x * ones(r.nmc, 1); fracture_x * ones(r.nfc, 1)];
|
||||
f.chemistry_potential = f.chemistry_cof * log(f.x_total);
|
||||
|
||||
pressure0 = expand_initial_value(initial_config.pressure, total_cells);
|
||||
sw0 = expand_initial_value(initial_config.sw, total_cells);
|
||||
cs0 = expand_initial_value(initial_config.cs, total_cells);
|
||||
cb0 = expand_initial_value(initial_config.cb, total_cells);
|
||||
state0 = initialRS(pressure0, sw0, cs0, cb0);
|
||||
end
|
||||
|
||||
function value = expand_initial_value(raw_value, total_cells)
|
||||
if isscalar(raw_value)
|
||||
value = raw_value * ones(total_cells, 1);
|
||||
else
|
||||
value = raw_value;
|
||||
end
|
||||
end
|
||||
|
||||
function value = default_if_empty(s, field_name, fallback)
|
||||
if isfield(s, field_name) && ~isempty(s.(field_name))
|
||||
value = s.(field_name);
|
||||
else
|
||||
value = fallback;
|
||||
end
|
||||
end
|
||||
|
||||
function [well2, welloc] = build_fracture_wells(wells_config, r)
|
||||
num_fracture_wells = wells_config.num_fracture_wells;
|
||||
welloc = wells_config.welloc;
|
||||
perfnum = cell(num_fracture_wells, 1);
|
||||
|
||||
for i = 1:num_fracture_wells
|
||||
perfnum{i, 1} = findWelloc(r, welloc{i, 1});
|
||||
end
|
||||
|
||||
well2 = cell(num_fracture_wells, 6);
|
||||
for i = 1:num_fracture_wells
|
||||
if numel(wells_config.well2) >= i && ~isempty(wells_config.well2{i, 1})
|
||||
well2(i, :) = wells_config.well2(i, :);
|
||||
well2{i, 2} = length(perfnum{i, 1});
|
||||
well2{i, 3} = perfnum{i, 1};
|
||||
else
|
||||
well2(i, :) = {sprintf('wf%d', i), length(perfnum{i, 1}), perfnum{i, 1}, 0.178/2, 0, 4};
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,25 @@
|
||||
function config = load_case_template(case_id)
|
||||
%LOAD_CASE_TEMPLATE Load a predefined case template into unified config.
|
||||
|
||||
arguments
|
||||
case_id
|
||||
end
|
||||
|
||||
case_key = normalize_case_id(case_id);
|
||||
|
||||
switch case_key
|
||||
case "case01"
|
||||
config = load_case_template_case01();
|
||||
otherwise
|
||||
error('load_case_template:UnsupportedCase', ...
|
||||
'Unsupported case template: %s', string(case_key));
|
||||
end
|
||||
end
|
||||
|
||||
function case_key = normalize_case_id(case_id)
|
||||
if isnumeric(case_id)
|
||||
case_key = "case" + compose("%02d", case_id);
|
||||
else
|
||||
case_key = lower(string(case_id));
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,189 @@
|
||||
function config = load_case_template_case01()
|
||||
%LOAD_CASE_TEMPLATE_CASE01 Build config for case 1.
|
||||
|
||||
config = create_empty_config();
|
||||
|
||||
config.meta.case_name = 'case01_multicomponent_irregular_domain';
|
||||
config.meta.case_id = 'case01';
|
||||
config.meta.description = 'Multicomponent flow with irregular heterogeneous domain';
|
||||
config.meta.source_case_folder = 'CASE01_FOLDER';
|
||||
config.meta.created_from_template = 'case01';
|
||||
|
||||
config.model.modelflag = 1;
|
||||
config.model.grid_model = 1;
|
||||
config.model.flow_model = 3;
|
||||
|
||||
config.grid.dx = 50 * ones(1, 20);
|
||||
config.grid.dy = 50 * ones(1, 10);
|
||||
config.grid.dz = 10 * ones(1, 1);
|
||||
config.grid.nx = numel(config.grid.dx);
|
||||
config.grid.ny = numel(config.grid.dy);
|
||||
config.grid.nz = numel(config.grid.dz);
|
||||
config.grid.NTG = ones(config.grid.nx * config.grid.ny * config.grid.nz, 1);
|
||||
|
||||
config.fracture.input_style = 1;
|
||||
config.fracture.input_content = {
|
||||
[255,255,5],90,90,0,200,10,1;
|
||||
[305,255,5],90,90,0,200,10,1;
|
||||
[355,255,5],90,90,0,200,10,1;
|
||||
[405,255,5],90,90,0,200,10,1;
|
||||
[455,255,5],90,90,0,200,10,1;
|
||||
[505,255,5],90,90,0,200,10,1;
|
||||
[555,255,5],90,90,0,200,10,1;
|
||||
[605,255,5],90,90,0,200,10,1;
|
||||
[655,255,5],90,90,0,200,10,1;
|
||||
[705,255,5],90,90,0,200,10,1;
|
||||
[755,255,5],90,90,0,200,10,1;
|
||||
};
|
||||
config.fracture.flowBarrierFlags = [];
|
||||
|
||||
config.discretization.mode = 1;
|
||||
config.discretization.sp.boundary_polygon = [
|
||||
0,100;
|
||||
800,50;
|
||||
1000,150;
|
||||
1000,350;
|
||||
800,450;
|
||||
0,400;
|
||||
0,100];
|
||||
config.discretization.sp.invalid_layer = [];
|
||||
config.discretization.sp.matrix.prpor = 20;
|
||||
config.discretization.sp.matrix.cpor = 1.0e-5;
|
||||
config.discretization.sp.matrix.rock_density = 2700;
|
||||
config.discretization.sp.fracture.prporf = 20;
|
||||
config.discretization.sp.fracture.cporf = 1.0e-5;
|
||||
config.discretization.sp.stress.fracture_factor = 0.0;
|
||||
config.discretization.sp.stress.matrix_factor = 0.0;
|
||||
config.discretization.sp.stress.ref_pressure = 20;
|
||||
|
||||
config.flow.multi_component.Ds = 0.76e-9;
|
||||
config.flow.multi_component.Db = 2.2e-9;
|
||||
config.flow.multi_component.c_ca_table = [
|
||||
0 0 0;
|
||||
0.05 1 0.075;
|
||||
0.1 1.75 0.125;
|
||||
0.2 3 0.2;
|
||||
0.5 4.35 0.325;
|
||||
1 4.55 0.365];
|
||||
config.flow.multi_component.R = 0.008314;
|
||||
config.flow.multi_component.Vm = 18.02e-6;
|
||||
config.flow.multi_component.Temperature = 293.15;
|
||||
config.flow.multi_component.x_matrix = 0.9;
|
||||
config.flow.multi_component.x_fracture = 1.0;
|
||||
config.flow.multi_component.cs_Nc = [
|
||||
0 1.6e-6 30;
|
||||
0.1 9.5e-6 10;
|
||||
0.2 2.5e-5 4;
|
||||
0.5 5.8e-5 1.4;
|
||||
1 8.2e-5 1;
|
||||
2 8.8e-5 0.75];
|
||||
config.flow.multi_component.kr_nosurf = [
|
||||
0 0 0.64;
|
||||
0.25 0 0.64;
|
||||
0.30 0.072 0.6;
|
||||
0.40 0.14 0.56;
|
||||
0.50 0.26 0.48;
|
||||
0.60 0.4 0.38;
|
||||
0.70 0.56 0.26;
|
||||
0.85 0.88 0;
|
||||
1 0.88 0];
|
||||
config.flow.multi_component.kr_surf = [
|
||||
0 0 0.6;
|
||||
0.18 0 0.6;
|
||||
0.25 0.056 0.56;
|
||||
0.30 0.1 0.52;
|
||||
0.40 0.19 0.42;
|
||||
0.50 0.29 0.3;
|
||||
0.60 0.37 0.19;
|
||||
0.75 0.46 0;
|
||||
1 0.46 0];
|
||||
config.flow.multi_component.PC = [
|
||||
0 3.8916;
|
||||
0.2 3.8916;
|
||||
0.316 0.5796;
|
||||
0.435 0.3724;
|
||||
0.562 0.2425;
|
||||
0.614 0.0608;
|
||||
0.702 0.0372;
|
||||
0.812 0.0137;
|
||||
0.875 0.0104;
|
||||
0.906 0.009;
|
||||
0.937 0.0075;
|
||||
0.969 0.0059;
|
||||
1 0];
|
||||
config.flow.multi_component.cs_Nc_fracture = config.flow.multi_component.cs_Nc;
|
||||
config.flow.multi_component.kr_nosurf_fracture = config.flow.multi_component.kr_nosurf;
|
||||
config.flow.multi_component.kr_surf_fracture = config.flow.multi_component.kr_surf;
|
||||
config.flow.multi_component.PC_fracture = config.flow.multi_component.PC;
|
||||
config.flow.multi_component.ifpcgl = 0;
|
||||
config.flow.multi_component.p_grad_threshold = 0.01;
|
||||
config.flow.multi_component.gas_prop.VL = 0.0;
|
||||
config.flow.multi_component.gas_prop.PL = 3.5;
|
||||
config.flow.multi_component.gas_prop.Kn = 0;
|
||||
config.flow.multi_component.gas_prop.stress_factor_fracture = 0.0;
|
||||
config.flow.multi_component.gas_prop.stress_factor_matrix = 0.0;
|
||||
config.flow.multi_component.gas_prop.stress_factor_ref_pressure = 20;
|
||||
config.flow.multi_component.gas_prop.beta_non_darcy_flow = 0;
|
||||
config.flow.multi_component.density_g_sc = 800;
|
||||
config.flow.multi_component.gas_model = 1;
|
||||
config.flow.multi_component.prg = 20;
|
||||
config.flow.multi_component.Bgi = 1;
|
||||
config.flow.multi_component.cg = 5e-4;
|
||||
config.flow.multi_component.vgi = 6;
|
||||
config.flow.multi_component.cvg = 0;
|
||||
config.flow.multi_component.density_w_sc = 1000;
|
||||
config.flow.multi_component.prw = 20;
|
||||
config.flow.multi_component.Bwi = 1.0;
|
||||
config.flow.multi_component.cw = 4.0e-4;
|
||||
config.flow.multi_component.vwi = 1;
|
||||
config.flow.multi_component.cvw = 0;
|
||||
config.flow.multi_component.number_state_variables = 4;
|
||||
|
||||
config.initial.pressure = 20;
|
||||
config.initial.sw = 0.2;
|
||||
config.initial.cs = 0.0;
|
||||
config.initial.cb = 0.0;
|
||||
|
||||
config.wells.well1 = {};
|
||||
config.wells.num_fracture_wells = 1;
|
||||
config.wells.welloc = {
|
||||
[
|
||||
255,255,5;
|
||||
305,255,5;
|
||||
355,255,5;
|
||||
405,255,5;
|
||||
455,255,5;
|
||||
505,255,5;
|
||||
555,255,5;
|
||||
605,255,5;
|
||||
655,255,5;
|
||||
705,255,5;
|
||||
755,255,5
|
||||
]};
|
||||
config.wells.well2 = {
|
||||
'w1', 0, [], 0.178/2, 0, 4
|
||||
};
|
||||
|
||||
config.schedule.number_phases = 3;
|
||||
config.schedule.time = [10; 30; 200];
|
||||
config.schedule.dtmax = [0.1; 0.5; 0.5];
|
||||
config.schedule.dtmin = [0.001; 0.001; 0.001];
|
||||
config.schedule.well_schedules = {
|
||||
{
|
||||
'w1','open','inj','const_pwf',40,40,'Cs_inj',0.5,'Cb_inj',1
|
||||
};
|
||||
{
|
||||
'w1','open','pro','const_q',0,0
|
||||
};
|
||||
{
|
||||
'w1','open','pro','const_pwf',10,10
|
||||
}};
|
||||
|
||||
config.solver.yitap = 5;
|
||||
config.solver.yitas = 0.04;
|
||||
config.solver.omega = 0.5;
|
||||
config.solver.Nmax = 50;
|
||||
config.solver.epsave = 1e-6;
|
||||
config.solver.epsmax = 1e-6;
|
||||
|
||||
config.output.result_name = 'case01_default_run';
|
||||
Reference in New Issue
Block a user