Files
3D_EDFM_SIM-X/docs/fracture_well_ui_redesign_plan.md
2026-04-03 15:51:34 +08:00

9.7 KiB

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.

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

Keep These Backend Fields

Keep the runtime/backend idea below:

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:

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

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

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.

Well1Table

No major structural change required.

Well2Table

Recommended columns:

  1. well_name
  2. rw
  3. skin
  4. welltype

Optional extra read-only columns:

  1. 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

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:

selectedFracWellIndex

Read UI:

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:

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.