# Fracture Well UI Redesign Plan ## Problem Summary Current `Wells` page structure is not suitable for the following scenario: - reservoir may contain zero fracture wells - reservoir may contain one fracture well - reservoir may contain multiple fracture wells - `num_fracture_wells` must equal the fracture-well count - `welloc{i,1}` stores perforation coordinates for fracture well `i` - perforation coordinates are often fracture coordinates, but they may also be independent coordinates - fracture engineering input can stay unified in `fracture.input_content` - perforation data cannot be merged into one shared array, otherwise multiple fracture wells cannot be distinguished The current controller only reads and writes the first entry of `c.wells.welloc`, so the present UI effectively assumes only one fracture well. ## Current Constraint In Existing Code Existing runtime logic already supports multiple fracture wells in principle: - `run_case.m` - `build_fracture_wells(...)` loops over `num_fracture_wells` - original case files - example case 7 uses `num_fracture_wells = 6` - `welloc{1}` to `welloc{6}` are defined separately - `well2` also has 6 rows and matches them one by one The main mismatch is in the GUI/controller layer: - `FractureWellLocationTable` is a single table - controller uses `unwrapFirstCell(c.wells.welloc)` - controller writes back with `replaceFirstCell(...)` So the GUI schema is the real bottleneck. ## Recommended UI Principle Do not organize the fracture-well section as: - one table for all perforation coordinates only Instead organize it as: - one summary table for fracture well definitions - one detail editor for the currently selected fracture well's perforation coordinates This is the safest structure because: - it supports `0 / 1 / N` fracture wells - each fracture well keeps its own `welloc{i,1}` - `well2(i,:)` and `welloc{i,1}` can stay naturally linked by row index - fracture geometry remains independent in `fracture.input_content` ## Recommended Data Mapping ### Keep These Backend Fields Keep the runtime/backend idea below: ```matlab c.wells.num_fracture_wells c.wells.well2 c.wells.welloc ``` Recommended interpretation: - `c.wells.num_fracture_wells = size(c.wells.well2, 1)` - `c.wells.welloc{i,1}` is the perforation coordinate matrix of fracture well `i` - `size(c.wells.welloc, 1)` should equal `size(c.wells.well2, 1)` Recommended invariant: ```matlab num_fracture_wells == size(well2,1) == numel(welloc) ``` ### Suggested Meaning Of `well2` Treat `well2` as the fracture-well summary table only. Recommended editable columns: 1. `well_name` 2. `rw` 3. `skin` 4. `welltype` Recommended non-editable or derived columns: 1. `nperf` 2. `perf_index` Reason: - `nperf` is derived from `welloc{i,1}` - `perf_index` is generated by `findWelloc(...)` - these two should not be manually edited in the GUI If keeping the current 6-column backend shape for compatibility, then GUI can still display 6 columns, but: - column 2 `nperf` should be read-only - column 3 `perf_index` should be read-only or hidden ## Recommended Wells Page Layout ### Section A: Conventional Wells Keep existing `Well1Table`. This remains for ordinary wells already handled by `handle_well1(...)`. ### Section B: Fracture Wells Summary Repurpose current `Well2Table` into a fracture-well summary table. Recommended label: - `Fracture Wells` Recommended columns: 1. `well_name` 2. `rw` 3. `skin` 4. `welltype` 5. `nperf` optional read-only display Buttons: - `Add Fracture Well` - `Delete Fracture Well` Behavior: - add one row to `well2` - also create one empty `welloc{i,1} = []` - delete row `i` from both `well2` and `welloc` - after any add/delete: - `num_fracture_wells = size(well2,1)` ### Section C: Perforation Detail Editor Do not keep one generic `FractureWellLocationTable` without context. Replace it conceptually with: - one selector showing which fracture well is being edited - one table that edits only that well's perforation coordinates Recommended controls: 1. `SelectedFracWellDropDown` or `SelectedFracWellListBox` 2. `FractureWellLocationTable` 3. `Add Perf Row` 4. `Delete Perf Row` 5. optional helper text label Recommended table columns: 1. `x` 2. `y` 3. `z` Behavior: - when user selects fracture well `i` - table shows `welloc{i,1}` - when table changes - write back to `welloc{i,1}` - when no fracture well exists - disable this table and show hint text like: - `No fracture well is defined. Please add a fracture well first.` This is the key redesign. ## Relationship Between Fracture Input And Perforation Input These two parts should stay separate in the UI. ### Fracture Tab Keep: - `fracture.input_content` This is for fracture geometry/engineering input. ### Wells Tab Keep separate: - fracture-well summary - per-well perforation coordinates Reason: - fractures describe the reservoir fracture system - perforations describe where a specific fracture well connects to the model - one fracture well may connect to one or more fracture coordinates - perforation coordinates may match fracture coordinates, but not always So they should not be merged into the same editable widget. ## Whether `num_fracture_wells` Should Be A Separate UI Field Recommendation: - do not expose `num_fracture_wells` as an independent editable numeric field Instead: - derive it automatically from fracture-well summary row count Reason: - avoids inconsistency - user only manages actual fracture-well rows - controller maintains `num_fracture_wells` ## Recommended App Designer Changes These are the parts you should change manually in `.mlapp`. ### Minimum Change Version If you want the smallest UI change: 1. keep `Well1Table` 2. keep `Well2Table` 3. keep `FractureWellLocationTable` 4. add one selector control above `FractureWellLocationTable` - name suggestion: `SelectedFracWellDropDown` 5. change labels so that: - `Well2Label` -> `Fracture Wells` - `WellLocationLabel` -> `Perforation Coordinates` 6. change `FractureWellLocationTable` columns from one generic column to three columns: - `x`, `y`, `z` 7. add a small note label: - `Each fracture well has its own perforation coordinate list.` This is the recommended minimum viable fix. ### Better Version If you can slightly improve layout: Use a 3-block layout in `WellsTab`: 1. top-left: `Well1Table` 2. top-right: `Well2Table` 3. bottom-wide: selected fracture well perforation editor This will be clearer than the current four unrelated tables. ## Recommended Table Definitions ### `Well1Table` No major structural change required. ### `Well2Table` Recommended columns: 1. `well_name` 2. `rw` 3. `skin` 4. `welltype` Optional extra read-only columns: 5. `nperf` If you want to keep backend compatibility without changing much controller code later, you may still visually keep 6 columns: 1. `well_name` 2. `nperf` read-only 3. `perf_index` hidden or read-only expression 4. `rw` 5. `skin` 6. `welltype` But from user experience perspective, 4 editable columns are better. ### `FractureWellLocationTable` Recommended columns: 1. `x` 2. `y` 3. `z` Each row is one perforation point for the currently selected fracture well. ## Controller Change Direction When you later modify `EDFMAppController.m`, the well section should change conceptually as follows. ### Current Wrong Logic ```matlab obj.setTableValue('FractureWellLocationTable', obj.unwrapFirstCell(c.wells.welloc)); ... fractureWellLocation = obj.getNumericTableValue('FractureWellLocationTable', obj.unwrapFirstCell(c.wells.welloc)); c.wells.welloc = obj.replaceFirstCell(c.wells.welloc, fractureWellLocation); c.wells.num_fracture_wells = numel(c.wells.welloc); ``` This only handles the first fracture well. ### Target Logic Need a selected index such as: ```matlab selectedFracWellIndex ``` Read UI: ```matlab c.wells.well2 = ... c.wells.num_fracture_wells = size(c.wells.well2,1); ensure c.wells.welloc has same length c.wells.welloc{selectedFracWellIndex,1} = currentPerfTable ``` Write UI: ```matlab set Well2Table from c.wells.well2 refresh fracture-well selector items load FractureWellLocationTable from c.wells.welloc{selectedFracWellIndex,1} ``` ## Validation Rules To Add When this section is later coded, these checks are recommended: 1. `size(well2,1) == numel(welloc)` 2. `num_fracture_wells == size(well2,1)` 3. each `welloc{i,1}` must be empty or an `N x 3` numeric matrix 4. if `well2(i,1)` is empty, generate default name like `wf1`, `wf2` 5. when no fracture well exists: - `well2 = {}` - `welloc = {}` - `num_fracture_wells = 0` 6. if user deletes a fracture well, also delete its perforation list ## Practical Recommendation For your current stage, the best balance is: 1. fracture geometry remains in `FractureTab` 2. ordinary wells remain in `Well1Table` 3. fracture wells use `Well2Table` 4. perforations are edited through one selected-well detail table 5. `num_fracture_wells` is auto-derived, not manually entered This will match both: - the old case-script logic - the future GUI editing logic And it also naturally supports the case where there is no fracture well. ## Manual UI Rename Suggestions Suggested visible labels: - `Well1Label` -> `Conventional Wells` - `Well2Label` -> `Fracture Wells` - `WellLocationLabel` -> `Perforation Coordinates` - `ScheduleLabel` keep as `Schedule` Suggested new control names if you add them: - `SelectedFracWellDropDown` - `SelectedFracWellDropDownLabel` - `FracWellHintLabel` ## Conclusion The main point is: - fracture information can stay unified in `fracture.input_content` - perforation information must be stored per fracture well - therefore the GUI must be changed from "one perforation table" to "fracture-well summary + selected-well perforation detail" That is the most stable and least confusing design for the current codebase.