gea-program 0.85.0__tar.gz → 0.86.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (434) hide show
  1. {gea_program-0.85.0/gea_program.egg-info → gea_program-0.86.0}/PKG-INFO +23 -4
  2. {gea_program-0.85.0 → gea_program-0.86.0}/README.md +22 -3
  3. {gea_program-0.85.0 → gea_program-0.86.0}/gea/__init__.py +1 -1
  4. {gea_program-0.85.0 → gea_program-0.86.0}/gea/__main__.py +38 -0
  5. {gea_program-0.85.0 → gea_program-0.86.0}/gea/acceptance_tests.py +232 -0
  6. {gea_program-0.85.0 → gea_program-0.86.0}/gea/dossier.py +7 -1
  7. gea_program-0.86.0/gea/front.py +792 -0
  8. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/driller.md +1 -1
  9. gea_program-0.86.0/gea/help/front.md +13 -0
  10. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/install.md +2 -2
  11. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/reader.md +1 -1
  12. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/recorder.md +1 -1
  13. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/01-install.md +2 -2
  14. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/14-production-pages.md +6 -5
  15. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/19-dossier-reader.md +1 -1
  16. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/22-updates.md +1 -1
  17. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/23-vpn.md +1 -1
  18. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/25-install-recorder.md +2 -2
  19. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/29-driller-rig.md +1 -1
  20. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial.md +2 -2
  21. {gea_program-0.85.0 → gea_program-0.86.0}/gea/helplib.py +2 -1
  22. {gea_program-0.85.0 → gea_program-0.86.0}/gea/plume.py +38 -12
  23. {gea_program-0.85.0 → gea_program-0.86.0}/gea/service.py +12 -0
  24. {gea_program-0.85.0 → gea_program-0.86.0}/gea/web/app.html +69 -3
  25. {gea_program-0.85.0 → gea_program-0.86.0}/gea/well3d.py +13 -1
  26. {gea_program-0.85.0 → gea_program-0.86.0/gea_program.egg-info}/PKG-INFO +23 -4
  27. {gea_program-0.85.0 → gea_program-0.86.0}/gea_program.egg-info/SOURCES.txt +2 -0
  28. {gea_program-0.85.0 → gea_program-0.86.0}/pyproject.toml +1 -1
  29. {gea_program-0.85.0 → gea_program-0.86.0}/LICENSE +0 -0
  30. {gea_program-0.85.0 → gea_program-0.86.0}/gea/BENCH_TEST_PROTOCOL.md +0 -0
  31. {gea_program-0.85.0 → gea_program-0.86.0}/gea/accuracy_statement.py +0 -0
  32. {gea_program-0.85.0 → gea_program-0.86.0}/gea/alarm_engine.py +0 -0
  33. {gea_program-0.85.0 → gea_program-0.86.0}/gea/alerts.py +0 -0
  34. {gea_program-0.85.0 → gea_program-0.86.0}/gea/backup.py +0 -0
  35. {gea_program-0.85.0 → gea_program-0.86.0}/gea/bench.py +0 -0
  36. {gea_program-0.85.0 → gea_program-0.86.0}/gea/bit_seismic.py +0 -0
  37. {gea_program-0.85.0 → gea_program-0.86.0}/gea/blind_harness.py +0 -0
  38. {gea_program-0.85.0 → gea_program-0.86.0}/gea/casing_design.py +0 -0
  39. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/acex_lomonosov_age_depth_model.provenance.json +0 -0
  40. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/acex_lomonosov_age_depth_model.txt +0 -0
  41. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/agassiz77_canada_temperature.csv +0 -0
  42. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/agassiz77_canada_temperature.provenance.json +0 -0
  43. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/barbados_110_consolidation.provenance.json +0 -0
  44. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/barbados_110_consolidation.txt +0 -0
  45. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/bengal_u1452_grain_size.provenance.json +0 -0
  46. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/bengal_u1452_grain_size.txt +0 -0
  47. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/blake_164_methane_isotopes.provenance.json +0 -0
  48. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/blake_164_methane_isotopes.txt +0 -0
  49. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.provenance.json +0 -0
  50. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.txt +0 -0
  51. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/collingwood_1_28_ks_complete.las +0 -0
  52. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/collingwood_1_28_ks_complete.provenance.json +0 -0
  53. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/costa_rica_odp_friction_envelope.provenance.json +0 -0
  54. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/costa_rica_odp_friction_envelope.txt +0 -0
  55. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.provenance.json +0 -0
  56. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.txt +0 -0
  57. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/dsdp_504b_physical_properties.provenance.json +0 -0
  58. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/dsdp_504b_physical_properties.txt +0 -0
  59. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/dsdp_504b_sound_velocity.provenance.json +0 -0
  60. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/dsdp_504b_sound_velocity.txt +0 -0
  61. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/elgygytgyn_5011_turbidites.provenance.json +0 -0
  62. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/elgygytgyn_5011_turbidites.txt +0 -0
  63. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/epica_domec_co2_800kyr.provenance.json +0 -0
  64. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/epica_domec_co2_800kyr.txt +0 -0
  65. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/fram_909_organic_petrography.provenance.json +0 -0
  66. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/fram_909_organic_petrography.txt +0 -0
  67. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/gbr_325_coral_uth_ages.provenance.json +0 -0
  68. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/gbr_325_coral_uth_ages.txt +0 -0
  69. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/gisp2_greenland_temperature.csv +0 -0
  70. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/gisp2_greenland_temperature.provenance.json +0 -0
  71. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/gom_308_t2p_insitu.provenance.json +0 -0
  72. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/gom_308_t2p_insitu.txt +0 -0
  73. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/guaymas_385_dom_d13c.provenance.json +0 -0
  74. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/guaymas_385_dom_d13c.txt +0 -0
  75. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/hikurangi_u1520_friction_insitu.provenance.json +0 -0
  76. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/hikurangi_u1520_friction_insitu.txt +0 -0
  77. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.provenance.json +0 -0
  78. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.txt +0 -0
  79. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/iodp_u1324_pore_pressure.provenance.json +0 -0
  80. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/iodp_u1324_pore_pressure.txt +0 -0
  81. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/jfast_c0019_slow_slip_events.provenance.json +0 -0
  82. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/jfast_c0019_slow_slip_events.txt +0 -0
  83. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/kennetcook_2_p129_excerpt.las +0 -0
  84. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/kennetcook_2_p129_excerpt.provenance.json +0 -0
  85. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/ktb_hb_bhgm_density.dat +0 -0
  86. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/ktb_hb_bhgm_density.provenance.json +0 -0
  87. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/ktb_hb_complog_6020_excerpt.provenance.json +0 -0
  88. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/ktb_hb_complog_6020_excerpt.txt +0 -0
  89. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/ktb_hb_hlog246_temperature.dat +0 -0
  90. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/ktb_hb_hlog246_temperature.provenance.json +0 -0
  91. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/ktb_hb_rockmech_compress.dat +0 -0
  92. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/ktb_hb_rockmech_compress.provenance.json +0 -0
  93. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.dat +0 -0
  94. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.provenance.json +0 -0
  95. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/ktb_vb_rockmech_compress.dat +0 -0
  96. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/ktb_vb_rockmech_compress.provenance.json +0 -0
  97. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/ktb_vb_vlog251_temperature.dat +0 -0
  98. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/ktb_vb_vlog251_temperature.provenance.json +0 -0
  99. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/l06_06_nl_survey.csv +0 -0
  100. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/l06_06_nl_survey.provenance.json +0 -0
  101. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/l07_01_nl_excerpt.las +0 -0
  102. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/l07_01_nl_excerpt.provenance.json +0 -0
  103. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/mariana_1200_serpentinite_geochem.provenance.json +0 -0
  104. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/mariana_1200_serpentinite_geochem.txt +0 -0
  105. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/med_160_sapropels.provenance.json +0 -0
  106. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/med_160_sapropels.txt +0 -0
  107. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/nankai_megasplay_shear_strength.provenance.json +0 -0
  108. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/nankai_megasplay_shear_strength.txt +0 -0
  109. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/odp_1027b_thermal_conductivity.provenance.json +0 -0
  110. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/odp_1027b_thermal_conductivity.txt +0 -0
  111. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/odp_1027c_cork_temperature.provenance.json +0 -0
  112. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/odp_1027c_cork_temperature.txt +0 -0
  113. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/odp_1165b_thermal_conductivity.provenance.json +0 -0
  114. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/odp_1165b_thermal_conductivity.txt +0 -0
  115. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.provenance.json +0 -0
  116. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.txt +0 -0
  117. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/odp_504b_dike_elastic_moduli.provenance.json +0 -0
  118. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/odp_504b_dike_elastic_moduli.txt +0 -0
  119. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/odp_504b_leg137_borehole_fluids.provenance.json +0 -0
  120. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/odp_504b_leg137_borehole_fluids.txt +0 -0
  121. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.provenance.json +0 -0
  122. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.txt +0 -0
  123. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/peru_201_sulfate_reduction.provenance.json +0 -0
  124. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/peru_201_sulfate_reduction.txt +0 -0
  125. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/scorpio_e1_sa_excerpt.las +0 -0
  126. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/scorpio_e1_sa_excerpt.provenance.json +0 -0
  127. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/sumatra_362_cohesion.provenance.json +0 -0
  128. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/sumatra_362_cohesion.txt +0 -0
  129. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/university_6_17_no1_tx_excerpt.las +0 -0
  130. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/university_6_17_no1_tx_excerpt.provenance.json +0 -0
  131. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/ursa_308_xrd_mineralogy.provenance.json +0 -0
  132. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/ursa_308_xrd_mineralogy.txt +0 -0
  133. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/volve_15_9_19_sr_excerpt.las +0 -0
  134. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/volve_15_9_19_sr_excerpt.provenance.json +0 -0
  135. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/volve_15_9_19a_core_excerpt.csv +0 -0
  136. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/volve_15_9_19a_core_excerpt.provenance.json +0 -0
  137. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/volve_f12_f14_production_excerpt.csv +0 -0
  138. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/volve_f12_f14_production_excerpt.provenance.json +0 -0
  139. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/walvis_208_petm_carbonate.provenance.json +0 -0
  140. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/walvis_208_petm_carbonate.txt +0 -0
  141. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/woodlark_1109_rock_eval.provenance.json +0 -0
  142. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog/woodlark_1109_rock_eval.txt +0 -0
  143. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog_map.py +0 -0
  144. {gea_program-0.85.0 → gea_program-0.86.0}/gea/catalog_register.py +0 -0
  145. {gea_program-0.85.0 → gea_program-0.86.0}/gea/certificates.py +0 -0
  146. {gea_program-0.85.0 → gea_program-0.86.0}/gea/cli.py +0 -0
  147. {gea_program-0.85.0 → gea_program-0.86.0}/gea/client_reports.py +0 -0
  148. {gea_program-0.85.0 → gea_program-0.86.0}/gea/collision.py +0 -0
  149. {gea_program-0.85.0 → gea_program-0.86.0}/gea/config_versioning.py +0 -0
  150. {gea_program-0.85.0 → gea_program-0.86.0}/gea/conformance.py +0 -0
  151. {gea_program-0.85.0 → gea_program-0.86.0}/gea/control_room.py +0 -0
  152. {gea_program-0.85.0 → gea_program-0.86.0}/gea/correlation.py +0 -0
  153. {gea_program-0.85.0 → gea_program-0.86.0}/gea/dashboard.py +0 -0
  154. {gea_program-0.85.0 → gea_program-0.86.0}/gea/declarations.py +0 -0
  155. {gea_program-0.85.0 → gea_program-0.86.0}/gea/decline.py +0 -0
  156. {gea_program-0.85.0 → gea_program-0.86.0}/gea/deviation.py +0 -0
  157. {gea_program-0.85.0 → gea_program-0.86.0}/gea/dlis.py +0 -0
  158. {gea_program-0.85.0 → gea_program-0.86.0}/gea/dnp3.py +0 -0
  159. {gea_program-0.85.0 → gea_program-0.86.0}/gea/doctor.py +0 -0
  160. {gea_program-0.85.0 → gea_program-0.86.0}/gea/dossier_verify.py +0 -0
  161. {gea_program-0.85.0 → gea_program-0.86.0}/gea/downhole_engine.py +0 -0
  162. {gea_program-0.85.0 → gea_program-0.86.0}/gea/drift_monitor.py +0 -0
  163. {gea_program-0.85.0 → gea_program-0.86.0}/gea/drill_string.py +0 -0
  164. {gea_program-0.85.0 → gea_program-0.86.0}/gea/driller_link.py +0 -0
  165. {gea_program-0.85.0 → gea_program-0.86.0}/gea/earth_model.py +0 -0
  166. {gea_program-0.85.0 → gea_program-0.86.0}/gea/economics.py +0 -0
  167. {gea_program-0.85.0 → gea_program-0.86.0}/gea/ed25519.py +0 -0
  168. {gea_program-0.85.0 → gea_program-0.86.0}/gea/edr.py +0 -0
  169. {gea_program-0.85.0 → gea_program-0.86.0}/gea/elevation.py +0 -0
  170. {gea_program-0.85.0 → gea_program-0.86.0}/gea/etp.py +0 -0
  171. {gea_program-0.85.0 → gea_program-0.86.0}/gea/etp12_schemas.json +0 -0
  172. {gea_program-0.85.0 → gea_program-0.86.0}/gea/example_register_map.json +0 -0
  173. {gea_program-0.85.0 → gea_program-0.86.0}/gea/fat_sat.py +0 -0
  174. {gea_program-0.85.0 → gea_program-0.86.0}/gea/field_pull.py +0 -0
  175. {gea_program-0.85.0 → gea_program-0.86.0}/gea/files.py +0 -0
  176. {gea_program-0.85.0 → gea_program-0.86.0}/gea/fixtures/README.md +0 -0
  177. {gea_program-0.85.0 → gea_program-0.86.0}/gea/fixtures/comcat_delaware_basin_2026-09.txt +0 -0
  178. {gea_program-0.85.0 → gea_program-0.86.0}/gea/fixtures/comcat_mahoning_1990-2026.txt +0 -0
  179. {gea_program-0.85.0 → gea_program-0.86.0}/gea/fixtures/comcat_youngstown_2011-2012.txt +0 -0
  180. {gea_program-0.85.0 → gea_program-0.86.0}/gea/fixtures/ne_110m_coastline.json +0 -0
  181. {gea_program-0.85.0 → gea_program-0.86.0}/gea/fluid.py +0 -0
  182. {gea_program-0.85.0 → gea_program-0.86.0}/gea/follower.py +0 -0
  183. {gea_program-0.85.0 → gea_program-0.86.0}/gea/forward_model.py +0 -0
  184. {gea_program-0.85.0 → gea_program-0.86.0}/gea/frac_hits.py +0 -0
  185. {gea_program-0.85.0 → gea_program-0.86.0}/gea/friction_priors.py +0 -0
  186. {gea_program-0.85.0 → gea_program-0.86.0}/gea/gamma.py +0 -0
  187. {gea_program-0.85.0 → gea_program-0.86.0}/gea/gauge_aging.py +0 -0
  188. {gea_program-0.85.0 → gea_program-0.86.0}/gea/gauge_specs.py +0 -0
  189. {gea_program-0.85.0 → gea_program-0.86.0}/gea/geodesy.py +0 -0
  190. {gea_program-0.85.0 → gea_program-0.86.0}/gea/geomag.py +0 -0
  191. {gea_program-0.85.0 → gea_program-0.86.0}/gea/gravity_reference.py +0 -0
  192. {gea_program-0.85.0 → gea_program-0.86.0}/gea/hartip.py +0 -0
  193. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/IT_SECURITY.md +0 -0
  194. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/TESTER_GUIDE.md +0 -0
  195. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/alarms.md +0 -0
  196. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/alerts.md +0 -0
  197. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/audit-update.md +0 -0
  198. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/backup.md +0 -0
  199. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/bit-image.md +0 -0
  200. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/casing.md +0 -0
  201. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/catalog.md +0 -0
  202. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/charts.md +0 -0
  203. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/collision.md +0 -0
  204. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/company-sign-in.md +0 -0
  205. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/conformance.md +0 -0
  206. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/control-room.md +0 -0
  207. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/data-in.md +0 -0
  208. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/declare.md +0 -0
  209. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/decline.md +0 -0
  210. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/dlis.md +0 -0
  211. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/doctor.md +0 -0
  212. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/dossier.md +0 -0
  213. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/drift.md +0 -0
  214. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/drillstring.md +0 -0
  215. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/economics.md +0 -0
  216. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/edr.md +0 -0
  217. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/etp.md +0 -0
  218. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/field-ports.md +0 -0
  219. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/files.md +0 -0
  220. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/fluid.md +0 -0
  221. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/frac-hits.md +0 -0
  222. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/historian.md +0 -0
  223. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/https.md +0 -0
  224. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/hydraulics.md +0 -0
  225. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/instruments.md +0 -0
  226. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/interval.md +0 -0
  227. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/invoice-check.md +0 -0
  228. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/map.md +0 -0
  229. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/month-end.md +0 -0
  230. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/notifications.md +0 -0
  231. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/opseis.md +0 -0
  232. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/osdu.md +0 -0
  233. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/pad-summary.md +0 -0
  234. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/patches.md +0 -0
  235. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/penetrator.md +0 -0
  236. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/plan.md +0 -0
  237. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/plume.md +0 -0
  238. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/pore-pressure.md +0 -0
  239. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/ppdm.md +0 -0
  240. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/quakeml.md +0 -0
  241. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/quality.md +0 -0
  242. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/records.md +0 -0
  243. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/report-history.md +0 -0
  244. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/rig-time.md +0 -0
  245. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/rocks.md +0 -0
  246. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/seedlink.md +0 -0
  247. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/seismic.md +0 -0
  248. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/setup.md +0 -0
  249. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/simulation.md +0 -0
  250. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/site.md +0 -0
  251. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/sites.md +0 -0
  252. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/slip.md +0 -0
  253. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/soak.md +0 -0
  254. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/sra.md +0 -0
  255. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/start.md +0 -0
  256. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/structure.md +0 -0
  257. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tools.md +0 -0
  258. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/torque-drag.md +0 -0
  259. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/transients.md +0 -0
  260. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/02-sign-in.md +0 -0
  261. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/03-site.md +0 -0
  262. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/04-add-well.md +0 -0
  263. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/05-records.md +0 -0
  264. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/06-well-page.md +0 -0
  265. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/07-declare.md +0 -0
  266. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/08-patches.md +0 -0
  267. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/09-alarms.md +0 -0
  268. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/10-control-room.md +0 -0
  269. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/11-summary-month.md +0 -0
  270. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/12-where-the-well-is.md +0 -0
  271. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/13-drilling-pages.md +0 -0
  272. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/15-seismic.md +0 -0
  273. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/16-seismicity.md +0 -0
  274. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/17-recorder-office.md +0 -0
  275. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/18-reports.md +0 -0
  276. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/20-admin.md +0 -0
  277. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/21-upkeep.md +0 -0
  278. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/24-the-box.md +0 -0
  279. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/26-monitor.md +0 -0
  280. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/27-mirror-vpn.md +0 -0
  281. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/tutorial/28-driller-office.md +0 -0
  282. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/upkeep.md +0 -0
  283. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/vibration.md +0 -0
  284. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/vpn.md +0 -0
  285. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/well-report.md +0 -0
  286. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/well-tests.md +0 -0
  287. {gea_program-0.85.0 → gea_program-0.86.0}/gea/help/well3d.md +0 -0
  288. {gea_program-0.85.0 → gea_program-0.86.0}/gea/housekeeping.py +0 -0
  289. {gea_program-0.85.0 → gea_program-0.86.0}/gea/hydraulics.py +0 -0
  290. {gea_program-0.85.0 → gea_program-0.86.0}/gea/icon.py +0 -0
  291. {gea_program-0.85.0 → gea_program-0.86.0}/gea/interval.py +0 -0
  292. {gea_program-0.85.0 → gea_program-0.86.0}/gea/inverse_engine.py +0 -0
  293. {gea_program-0.85.0 → gea_program-0.86.0}/gea/invoice_check.py +0 -0
  294. {gea_program-0.85.0 → gea_program-0.86.0}/gea/jobs.py +0 -0
  295. {gea_program-0.85.0 → gea_program-0.86.0}/gea/launcher.py +0 -0
  296. {gea_program-0.85.0 → gea_program-0.86.0}/gea/live_ports.py +0 -0
  297. {gea_program-0.85.0 → gea_program-0.86.0}/gea/loadtest.py +0 -0
  298. {gea_program-0.85.0 → gea_program-0.86.0}/gea/matplotlib_demo.py +0 -0
  299. {gea_program-0.85.0 → gea_program-0.86.0}/gea/modbus.py +0 -0
  300. {gea_program-0.85.0 → gea_program-0.86.0}/gea/modbus_rtu.py +0 -0
  301. {gea_program-0.85.0 → gea_program-0.86.0}/gea/model_card.py +0 -0
  302. {gea_program-0.85.0 → gea_program-0.86.0}/gea/month_end.py +0 -0
  303. {gea_program-0.85.0 → gea_program-0.86.0}/gea/mqtt_port.py +0 -0
  304. {gea_program-0.85.0 → gea_program-0.86.0}/gea/notify.py +0 -0
  305. {gea_program-0.85.0 → gea_program-0.86.0}/gea/oidc.py +0 -0
  306. {gea_program-0.85.0 → gea_program-0.86.0}/gea/oidc_mock.py +0 -0
  307. {gea_program-0.85.0 → gea_program-0.86.0}/gea/op_seismicity.py +0 -0
  308. {gea_program-0.85.0 → gea_program-0.86.0}/gea/opcua_port.py +0 -0
  309. {gea_program-0.85.0 → gea_program-0.86.0}/gea/operator_app.py +0 -0
  310. {gea_program-0.85.0 → gea_program-0.86.0}/gea/osdu.py +0 -0
  311. {gea_program-0.85.0 → gea_program-0.86.0}/gea/pad_summary.py +0 -0
  312. {gea_program-0.85.0 → gea_program-0.86.0}/gea/patches.py +0 -0
  313. {gea_program-0.85.0 → gea_program-0.86.0}/gea/pdf_report.py +0 -0
  314. {gea_program-0.85.0 → gea_program-0.86.0}/gea/penetrator.py +0 -0
  315. {gea_program-0.85.0 → gea_program-0.86.0}/gea/permits.py +0 -0
  316. {gea_program-0.85.0 → gea_program-0.86.0}/gea/piwebapi.py +0 -0
  317. {gea_program-0.85.0 → gea_program-0.86.0}/gea/pore_pressure.py +0 -0
  318. {gea_program-0.85.0 → gea_program-0.86.0}/gea/ports.py +0 -0
  319. {gea_program-0.85.0 → gea_program-0.86.0}/gea/ppdm.py +0 -0
  320. {gea_program-0.85.0 → gea_program-0.86.0}/gea/profile_catalog.py +0 -0
  321. {gea_program-0.85.0 → gea_program-0.86.0}/gea/project.py +0 -0
  322. {gea_program-0.85.0 → gea_program-0.86.0}/gea/qt6_downhole_app.py +0 -0
  323. {gea_program-0.85.0 → gea_program-0.86.0}/gea/quakeml.py +0 -0
  324. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reader.py +0 -0
  325. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reader_app.py +0 -0
  326. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reconciler.py +0 -0
  327. {gea_program-0.85.0 → gea_program-0.86.0}/gea/recorder_link.py +0 -0
  328. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/IU_ANMO_10_BHZ_response.provenance.json +0 -0
  329. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/IU_ANMO_10_BHZ_response.xml +0 -0
  330. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/WMM2025.COF +0 -0
  331. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/eia_henry_hub_daily.csv.gz +0 -0
  332. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/eia_prices.provenance.json +0 -0
  333. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/eia_wti_daily.csv.gz +0 -0
  334. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/iscwsa_rev4_example.json +0 -0
  335. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/iscwsa_rev5_example.json +0 -0
  336. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/l0701_sonic_gr.las.gz +0 -0
  337. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/l0701_sonic_gr.provenance.json +0 -0
  338. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/libmseed_steim.provenance.json +0 -0
  339. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/libmseed_steim1_4096.mseed +0 -0
  340. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/libmseed_steim2_4096.mseed +0 -0
  341. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/libmseed_steim2_512.mseed +0 -0
  342. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/mahoning_example.json +0 -0
  343. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/mud_motor_specs.json +0 -0
  344. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/owsg_tool_models.json +0 -0
  345. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/penetrator_ratings.json +0 -0
  346. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/seismicity_protocols.json +0 -0
  347. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/tool_sources.json +0 -0
  348. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/us_outline.json +0 -0
  349. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/us_outline.provenance.json +0 -0
  350. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/volve_3d.provenance.json +0 -0
  351. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/volve_f4_interpretation.las.gz +0 -0
  352. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/volve_f4_logs.provenance.json +0 -0
  353. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/volve_f4_lwd.las.gz +0 -0
  354. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/volve_surfaces.json.gz +0 -0
  355. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/volve_traj_F-10.xml.gz +0 -0
  356. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/volve_traj_F-4.xml.gz +0 -0
  357. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/volve_traj_F-5_12.25in.xml.gz +0 -0
  358. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/volve_traj_F-5_17.5in.xml.gz +0 -0
  359. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/volve_traj_F-5_36in.xml.gz +0 -0
  360. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/volve_traj_F-5_8.5in.xml.gz +0 -0
  361. {gea_program-0.85.0 → gea_program-0.86.0}/gea/reference/volve_well_picks.csv.gz +0 -0
  362. {gea_program-0.85.0 → gea_program-0.86.0}/gea/report_history.py +0 -0
  363. {gea_program-0.85.0 → gea_program-0.86.0}/gea/rig_state.py +0 -0
  364. {gea_program-0.85.0 → gea_program-0.86.0}/gea/rock_inventory.py +0 -0
  365. {gea_program-0.85.0 → gea_program-0.86.0}/gea/sample_record.py +0 -0
  366. {gea_program-0.85.0 → gea_program-0.86.0}/gea/sample_well_profile.csv +0 -0
  367. {gea_program-0.85.0 → gea_program-0.86.0}/gea/sbom.py +0 -0
  368. {gea_program-0.85.0 → gea_program-0.86.0}/gea/seedlink.py +0 -0
  369. {gea_program-0.85.0 → gea_program-0.86.0}/gea/segy.py +0 -0
  370. {gea_program-0.85.0 → gea_program-0.86.0}/gea/seismic.py +0 -0
  371. {gea_program-0.85.0 → gea_program-0.86.0}/gea/seismic_array.py +0 -0
  372. {gea_program-0.85.0 → gea_program-0.86.0}/gea/seismic_assoc.py +0 -0
  373. {gea_program-0.85.0 → gea_program-0.86.0}/gea/seismic_detect.py +0 -0
  374. {gea_program-0.85.0 → gea_program-0.86.0}/gea/seismic_film.py +0 -0
  375. {gea_program-0.85.0 → gea_program-0.86.0}/gea/seismic_harmonic.py +0 -0
  376. {gea_program-0.85.0 → gea_program-0.86.0}/gea/seismic_qc.py +0 -0
  377. {gea_program-0.85.0 → gea_program-0.86.0}/gea/seismic_response.py +0 -0
  378. {gea_program-0.85.0 → gea_program-0.86.0}/gea/seismic_signature.py +0 -0
  379. {gea_program-0.85.0 → gea_program-0.86.0}/gea/seismic_track.py +0 -0
  380. {gea_program-0.85.0 → gea_program-0.86.0}/gea/seismic_uncertainty.py +0 -0
  381. {gea_program-0.85.0 → gea_program-0.86.0}/gea/seismic_unlisted.py +0 -0
  382. {gea_program-0.85.0 → gea_program-0.86.0}/gea/seismic_watch.py +0 -0
  383. {gea_program-0.85.0 → gea_program-0.86.0}/gea/sensor_swap.py +0 -0
  384. {gea_program-0.85.0 → gea_program-0.86.0}/gea/series_cache.py +0 -0
  385. {gea_program-0.85.0 → gea_program-0.86.0}/gea/service_life.py +0 -0
  386. {gea_program-0.85.0 → gea_program-0.86.0}/gea/setup_checklist.py +0 -0
  387. {gea_program-0.85.0 → gea_program-0.86.0}/gea/shapefile.py +0 -0
  388. {gea_program-0.85.0 → gea_program-0.86.0}/gea/shell.py +0 -0
  389. {gea_program-0.85.0 → gea_program-0.86.0}/gea/shut_in.py +0 -0
  390. {gea_program-0.85.0 → gea_program-0.86.0}/gea/simulation.py +0 -0
  391. {gea_program-0.85.0 → gea_program-0.86.0}/gea/site_map.py +0 -0
  392. {gea_program-0.85.0 → gea_program-0.86.0}/gea/sla_report.py +0 -0
  393. {gea_program-0.85.0 → gea_program-0.86.0}/gea/slip.py +0 -0
  394. {gea_program-0.85.0 → gea_program-0.86.0}/gea/soak.py +0 -0
  395. {gea_program-0.85.0 → gea_program-0.86.0}/gea/sra.py +0 -0
  396. {gea_program-0.85.0 → gea_program-0.86.0}/gea/store_forward.py +0 -0
  397. {gea_program-0.85.0 → gea_program-0.86.0}/gea/strata_join.py +0 -0
  398. {gea_program-0.85.0 → gea_program-0.86.0}/gea/structure.py +0 -0
  399. {gea_program-0.85.0 → gea_program-0.86.0}/gea/supervisor.py +0 -0
  400. {gea_program-0.85.0 → gea_program-0.86.0}/gea/survey_cmd.py +0 -0
  401. {gea_program-0.85.0 → gea_program-0.86.0}/gea/survey_view.py +0 -0
  402. {gea_program-0.85.0 → gea_program-0.86.0}/gea/telemetry.py +0 -0
  403. {gea_program-0.85.0 → gea_program-0.86.0}/gea/timestamp.py +0 -0
  404. {gea_program-0.85.0 → gea_program-0.86.0}/gea/tls.py +0 -0
  405. {gea_program-0.85.0 → gea_program-0.86.0}/gea/tool_catalog.py +0 -0
  406. {gea_program-0.85.0 → gea_program-0.86.0}/gea/tool_library.py +0 -0
  407. {gea_program-0.85.0 → gea_program-0.86.0}/gea/tool_taxonomy.py +0 -0
  408. {gea_program-0.85.0 → gea_program-0.86.0}/gea/torque_drag.py +0 -0
  409. {gea_program-0.85.0 → gea_program-0.86.0}/gea/transient.py +0 -0
  410. {gea_program-0.85.0 → gea_program-0.86.0}/gea/tray.py +0 -0
  411. {gea_program-0.85.0 → gea_program-0.86.0}/gea/tutorial.py +0 -0
  412. {gea_program-0.85.0 → gea_program-0.86.0}/gea/updates.py +0 -0
  413. {gea_program-0.85.0 → gea_program-0.86.0}/gea/vibration.py +0 -0
  414. {gea_program-0.85.0 → gea_program-0.86.0}/gea/vpn.py +0 -0
  415. {gea_program-0.85.0 → gea_program-0.86.0}/gea/web/reader.html +0 -0
  416. {gea_program-0.85.0 → gea_program-0.86.0}/gea/well_assembler.py +0 -0
  417. {gea_program-0.85.0 → gea_program-0.86.0}/gea/well_records.py +0 -0
  418. {gea_program-0.85.0 → gea_program-0.86.0}/gea/well_report.py +0 -0
  419. {gea_program-0.85.0 → gea_program-0.86.0}/gea/well_test_validation.py +0 -0
  420. {gea_program-0.85.0 → gea_program-0.86.0}/gea/wellplan.py +0 -0
  421. {gea_program-0.85.0 → gea_program-0.86.0}/gea/wellpos.py +0 -0
  422. {gea_program-0.85.0 → gea_program-0.86.0}/gea/winident.py +0 -0
  423. {gea_program-0.85.0 → gea_program-0.86.0}/gea/wits0.py +0 -0
  424. {gea_program-0.85.0 → gea_program-0.86.0}/gea/witsml.py +0 -0
  425. {gea_program-0.85.0 → gea_program-0.86.0}/gea/workspace.py +0 -0
  426. {gea_program-0.85.0 → gea_program-0.86.0}/gea/workspaces.py +0 -0
  427. {gea_program-0.85.0 → gea_program-0.86.0}/gea/x25519.py +0 -0
  428. {gea_program-0.85.0 → gea_program-0.86.0}/gea/xlsx_read.py +0 -0
  429. {gea_program-0.85.0 → gea_program-0.86.0}/gea_program.egg-info/dependency_links.txt +0 -0
  430. {gea_program-0.85.0 → gea_program-0.86.0}/gea_program.egg-info/entry_points.txt +0 -0
  431. {gea_program-0.85.0 → gea_program-0.86.0}/gea_program.egg-info/requires.txt +0 -0
  432. {gea_program-0.85.0 → gea_program-0.86.0}/gea_program.egg-info/top_level.txt +0 -0
  433. {gea_program-0.85.0 → gea_program-0.86.0}/setup.cfg +0 -0
  434. {gea_program-0.85.0 → gea_program-0.86.0}/tests/test_acceptance.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gea-program
3
- Version: 0.85.0
3
+ Version: 0.86.0
4
4
  Summary: GEA-Program: downhole gauge monitoring - canonical measurement records, quality rules, drift evaluation with a re-fit change log, well-test validation, alarm management, model cards, store-and-forward, monthly SLA measurement, FAT/SAT protocols and a dashboard, generated from live objects in the client's reporting outline.
5
5
  Author: Daniel T. Murphy
6
6
  License: MPL-2.0
@@ -847,7 +847,7 @@ unsigned, the key hand-overs - and shows the reports as they were signed. A
847
847
  reader made from the workspace knows the site's key fingerprints, so it
848
848
  says whether a dossier is the site's; it allows no network request, and it
849
849
  leaves the trusted time-stamp to `verify_dossier.py`. For a client who wants
850
- it installed, every release also carries `GEA-Reader-Setup-0.85.0.exe`: GEA
850
+ it installed, every release also carries `GEA-Reader-Setup-0.86.0.exe`: GEA
851
851
  Reader as a Windows program of its own - its own icon and taskbar button,
852
852
  Check with GEA Reader on a dossier's right-click menu, fingerprints the client
853
853
  saves kept on that computer, nothing of GEA-Program. `gea help reader`.
@@ -981,6 +981,25 @@ against it. The same contours drawn at the declared top in the 3D tab and
981
981
  carried in the dossier. Every figure a SIMULATION, said on every line. The
982
982
  **Pressure plume** tab, `gea plume`, `gea help plume`.
983
983
 
984
+ ### Fluid front
985
+
986
+ Where the injected water itself has gone. The pressure plume is miles wide;
987
+ the water, which has to push the formation's own out of the pore space, is
988
+ hundreds of feet from the well. On a fine grid around each injection well
989
+ the wells' steady flow is solved once per well (conjugate gradients, the
990
+ sealing faults closed) and the injected water moved with it - the fraction
991
+ of the thickness it fills, spreading under its own weight against the
992
+ formation water's by the sharp-interface equations, so a denser water runs
993
+ out along the base and a lighter one along the top. The tip, the half and
994
+ the whole thickness against a piston of the same volume; the day the water
995
+ reaches each producer, its share of that producer's stream and the TDS that
996
+ predicts, beside the TDS the producer's own report measures and the share
997
+ that implies; continued and shut in for five years; every injected barrel
998
+ accounted - in place, produced back, across a fault, beyond the grid. Drawn
999
+ in plan, in section and, at its depths, in the 3D tab. Every figure a
1000
+ SIMULATION, said on every line. The **Fluid front** tab, `gea front`,
1001
+ `gea help front`.
1002
+
984
1003
  ### Plan vs actual and the survey tools
985
1004
 
986
1005
  Each well against its directional plan: at every survey station, how far
@@ -1645,7 +1664,7 @@ attaches the zips to the GitHub release of that tag.
1645
1664
 
1646
1665
  ### The Windows installer
1647
1666
 
1648
- Every release also carries `GEA-Program-Setup-0.85.0.exe` (for 0.85.0): the
1667
+ Every release also carries `GEA-Program-Setup-0.86.0.exe` (for 0.86.0): the
1649
1668
  same Windows kit installed like any Windows program, for the signed-in user
1650
1669
  alone and with no administrator rights (`%LOCALAPPDATA%\Programs\GEA-Program`).
1651
1670
  It asks for the site workspace (an existing one such as `C:\site` is used as
@@ -1664,7 +1683,7 @@ it, removes the program and leaves the workspace. Silent, for a site's
1664
1683
  software deployment:
1665
1684
 
1666
1685
  ```
1667
- GEA-Program-Setup-0.85.0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /SITENAME="Pad 3" /TASKS="desktopicon"
1686
+ GEA-Program-Setup-0.86.0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /SITENAME="Pad 3" /TASKS="desktopicon"
1668
1687
  ```
1669
1688
 
1670
1689
  The setup is built by Inno Setup 6 from `tools/installer.iss` in the same
@@ -808,7 +808,7 @@ unsigned, the key hand-overs - and shows the reports as they were signed. A
808
808
  reader made from the workspace knows the site's key fingerprints, so it
809
809
  says whether a dossier is the site's; it allows no network request, and it
810
810
  leaves the trusted time-stamp to `verify_dossier.py`. For a client who wants
811
- it installed, every release also carries `GEA-Reader-Setup-0.85.0.exe`: GEA
811
+ it installed, every release also carries `GEA-Reader-Setup-0.86.0.exe`: GEA
812
812
  Reader as a Windows program of its own - its own icon and taskbar button,
813
813
  Check with GEA Reader on a dossier's right-click menu, fingerprints the client
814
814
  saves kept on that computer, nothing of GEA-Program. `gea help reader`.
@@ -942,6 +942,25 @@ against it. The same contours drawn at the declared top in the 3D tab and
942
942
  carried in the dossier. Every figure a SIMULATION, said on every line. The
943
943
  **Pressure plume** tab, `gea plume`, `gea help plume`.
944
944
 
945
+ ### Fluid front
946
+
947
+ Where the injected water itself has gone. The pressure plume is miles wide;
948
+ the water, which has to push the formation's own out of the pore space, is
949
+ hundreds of feet from the well. On a fine grid around each injection well
950
+ the wells' steady flow is solved once per well (conjugate gradients, the
951
+ sealing faults closed) and the injected water moved with it - the fraction
952
+ of the thickness it fills, spreading under its own weight against the
953
+ formation water's by the sharp-interface equations, so a denser water runs
954
+ out along the base and a lighter one along the top. The tip, the half and
955
+ the whole thickness against a piston of the same volume; the day the water
956
+ reaches each producer, its share of that producer's stream and the TDS that
957
+ predicts, beside the TDS the producer's own report measures and the share
958
+ that implies; continued and shut in for five years; every injected barrel
959
+ accounted - in place, produced back, across a fault, beyond the grid. Drawn
960
+ in plan, in section and, at its depths, in the 3D tab. Every figure a
961
+ SIMULATION, said on every line. The **Fluid front** tab, `gea front`,
962
+ `gea help front`.
963
+
945
964
  ### Plan vs actual and the survey tools
946
965
 
947
966
  Each well against its directional plan: at every survey station, how far
@@ -1606,7 +1625,7 @@ attaches the zips to the GitHub release of that tag.
1606
1625
 
1607
1626
  ### The Windows installer
1608
1627
 
1609
- Every release also carries `GEA-Program-Setup-0.85.0.exe` (for 0.85.0): the
1628
+ Every release also carries `GEA-Program-Setup-0.86.0.exe` (for 0.86.0): the
1610
1629
  same Windows kit installed like any Windows program, for the signed-in user
1611
1630
  alone and with no administrator rights (`%LOCALAPPDATA%\Programs\GEA-Program`).
1612
1631
  It asks for the site workspace (an existing one such as `C:\site` is used as
@@ -1625,7 +1644,7 @@ it, removes the program and leaves the workspace. Silent, for a site's
1625
1644
  software deployment:
1626
1645
 
1627
1646
  ```
1628
- GEA-Program-Setup-0.85.0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /SITENAME="Pad 3" /TASKS="desktopicon"
1647
+ GEA-Program-Setup-0.86.0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /SITENAME="Pad 3" /TASKS="desktopicon"
1629
1648
  ```
1630
1649
 
1631
1650
  The setup is built by Inno Setup 6 from `tools/installer.iss` in the same
@@ -123,7 +123,7 @@ from .profile_catalog import (
123
123
  read_pangaea_txt,
124
124
  )
125
125
 
126
- __version__ = "0.85.0"
126
+ __version__ = "0.86.0"
127
127
  __all__ = [
128
128
  "aging_rate", "rate_psi_yr", "accuracy_psi",
129
129
  "Sensor", "SimulatorConfig", "DownholeEngine",
@@ -603,6 +603,14 @@ def main(argv=None) -> int:
603
603
  p_pm.add_argument("--write", action="store_true", help="write reports/plume/plume.json and .md")
604
604
  p_pm.add_argument("--actor", type=str, default="cli")
605
605
  p_pm.add_argument("--json", action="store_true")
606
+ p_ff = sub.add_parser("front", help="the fluid front (SIMULATION): where the injected water itself has gone - the fraction of the thickness it fills on a fine grid around each injection well, moved by the wells' steady flow and spread by its own weight against the formation water's; the day it reaches each producer, its share of the stream and the TDS that predicts beside the measured one; every injected barrel accounted")
607
+ p_ff.add_argument("--workspace", type=str, default=None, help="the workspace folder; without one the self-test runs (the piston radius, the doublet's breakthrough, the tongue, a sealing fault)")
608
+ p_ff.add_argument("--well", type=str, default=None, help="one injection well's front (default: every injection well in the ledger)")
609
+ p_ff.add_argument("--cells", type=int, default=None, help="settings: cells per side of the grid, odd, 41 to 141 (default 81)")
610
+ p_ff.add_argument("--projection-days", type=int, default=None, help="settings: how far beyond the record to project, 365 to 7300 (default 1825)")
611
+ p_ff.add_argument("--write", action="store_true", help="write reports/front/front.json and .md")
612
+ p_ff.add_argument("--actor", type=str, default="cli")
613
+ p_ff.add_argument("--json", action="store_true")
606
614
  p_os = sub.add_parser("seismicity", help="operations and seismicity: each well's drilling, completion and disposal windows against the earthquake catalogue around it - the events during and after each, the levels a regulator's protocol would reach, and the rate during operations against the rest of the record; the Mahoning Valley worked example")
607
615
  p_os.add_argument("--workspace", type=str, default=None)
608
616
  p_os.add_argument("--scene", type=str, default=None, choices=("workspace", "mahoning"), help="your wells (the default with --workspace) or the public worked example")
@@ -2738,6 +2746,36 @@ def main(argv=None) -> int:
2738
2746
  else:
2739
2747
  print(_PM.text(p))
2740
2748
  return 0
2749
+ elif a.cmd == "front":
2750
+ import json as _json
2751
+ from . import front as _FF
2752
+ from .cli import _safe_stdout
2753
+ from .workspace import Workspace, WorkspaceError
2754
+ _safe_stdout()
2755
+ if not a.workspace:
2756
+ r = _FF.selftest()
2757
+ print(_json.dumps(r, default=str) if a.json else "\n".join(f"{'PASS' if c['pass'] else 'FAIL'} {c['check']}: {c['value']}" for c in r["checks"]) + f"\n{'OK' if r['ok'] else 'FAILED'} - {r['label']}")
2758
+ return 0 if r["ok"] else 1
2759
+ try:
2760
+ ws = Workspace(a.workspace)
2761
+ except WorkspaceError as e:
2762
+ raise SystemExit(f"front: {e}")
2763
+ try:
2764
+ if a.cells is not None or a.projection_days is not None:
2765
+ st_ = _FF.set_settings(ws, a.actor, a.cells, a.projection_days)
2766
+ print("settings: " + ", ".join(f"{k} {v}" for k, v in st_.items() if k in ("cells", "projection_days")))
2767
+ return 0
2768
+ if a.write:
2769
+ from . import __version__ as _ver86
2770
+ r = _FF.write_report(ws, _ver86, a.actor)
2771
+ print(f"written: {', '.join(r['files'])} under {r['folder']}")
2772
+ p = r["page"]
2773
+ else:
2774
+ p = _FF.page(ws, a.well)
2775
+ except (_FF.FrontError, WorkspaceError, ValueError, OSError) as e:
2776
+ raise SystemExit(f"front: {e.args[0] if e.args else e}")
2777
+ print(_json.dumps(p, default=str) if a.json else _FF.text(p))
2778
+ return 0
2741
2779
  elif a.cmd == "seismicity":
2742
2780
  import json as _json
2743
2781
  from . import op_seismicity as _OS
@@ -17839,6 +17839,237 @@ def section_ec_plume(tmp: str) -> None:
17839
17839
  + (f" [failed: {', '.join(failed3)}]" if failed3 else ""))
17840
17840
 
17841
17841
 
17842
+ def section_ed_front(tmp: str) -> None:
17843
+ """Section ED - the fluid front: the steady unit flow and the transport on labelled grids (the piston radius, the
17844
+ doublet's analytic breakthrough, the tongue of a denser water, shut-in slumping, a sealing fault, every barrel
17845
+ in place); the workspace (the injector's front on its own fine grid with the near producer in it and the far one
17846
+ beyond, the densities and the gravity number, the snapshots through the record and the two projections, the
17847
+ producer's arrival, share and predicted TDS beside its report's measured TDS and the share that implies, the
17848
+ account closing, the water across an open fault named and none across a sealing one, a front without densities
17849
+ a piston, the settings with their refusals, the report, the interface in 3D between the declared top and base, the
17850
+ dossier's results); the routes, the tab, the command, the help, the README and the lesson."""
17851
+ import http.cookiejar
17852
+ import math
17853
+ import subprocess as _sp
17854
+ import urllib.error
17855
+ import urllib.request
17856
+ import zipfile as _zf
17857
+ from datetime import datetime, timedelta
17858
+ from . import __version__ as _ver
17859
+ from . import client_reports as CR
17860
+ from . import dossier as DZ
17861
+ from . import fluid as FL
17862
+ from . import front as FR
17863
+ from . import geodesy as GD
17864
+ from . import helplib as H
17865
+ from . import plume as PM
17866
+ from . import shapefile as SF
17867
+ from . import well3d as W3
17868
+ from .service import Service, Users
17869
+ from .workspace import Workspace
17870
+ pkg = Path(__file__).parent
17871
+ d = Path(tmp, "ed"); d.mkdir()
17872
+ # -- ED1 the arithmetic ---------------------------------------------------------------------------------------------------
17873
+ st = FR.selftest()
17874
+ k, h, phi, mu = 20.0, 60.0, 0.15, 0.8
17875
+ n = 61; g = PM.Grid(n, 40.0, h, phi, k, mu, 1.0); vp = 40.0 * 40.0 * h * phi / 5.614583
17876
+ u = FR.solve_unit(g, 0.0, 0.0, k * h); uo = FR.solve_unit(g, 5000.0, 0.0, k * h) # a well on the grid, and one far beyond it
17877
+ c = u["cell"]
17878
+ w = FR.Water(g, vp, 0.0); q = 2000.0
17879
+ w.advance(100.0, u["Fx"] * q, u["Fy"] * q, {c: q}, {}, max_dt=1.0)
17880
+ rp = FL.swept_radius_ft(q * 100.0, h, phi); r = w.radii(0.0, 0.0)
17881
+ w2 = w.clone(); w2.advance(50.0, u["Fx"] * q, u["Fy"] * q, {c: q}, {}, max_dt=1.0)
17882
+ Gc = FR.gravity_coefficient(k, mu, -0.05, h)
17883
+ c1 = {
17884
+ "selftest": st["ok"] and st["label"] == "SIMULATION" and len(st["checks"]) == 10,
17885
+ "unit": u["converged"] and abs(float(FR._outflow(g, u["p"])[c]) - 1.0) < 1e-8 and uo["converged"] and uo["cell"] is None
17886
+ and abs(float(FR._outflow(g, uo["p"])[1:-1, 1:-1].sum())) < 1e-8 and float(uo["Fx"][n // 2, n // 2]) < 0.0,
17887
+ "piston": abs(r["half_equivalent_ft"] - rp) < 40.0 and r["full_equivalent_ft"] < r["half_equivalent_ft"] < r["tip_equivalent_ft"] and abs(w.in_place() / (q * 100.0) - 1.0) < 1e-6,
17888
+ "clone": abs(w.in_place() - q * 100.0) < 1.0 and abs(w2.in_place() - q * 150.0) < 1.0 and w2.days == 150.0 and w.days == 100.0,
17889
+ "gravity": abs(Gc - 0.001127 * (k / mu) * 0.433 * 0.05 * h * h) < 1e-9 and FR.gravity_coefficient(k, mu, 0.0, h) == 0.0,
17890
+ "limiter": float(FR._lim(np.array([1.0]), np.array([3.0]))[0]) == 1.5 and float(FR._lim(np.array([1.0]), np.array([-1.0]))[0]) == 0.0,
17891
+ "regime": "piston" in FR._regime(None) and "piston" in FR._regime(0.01) and "tongue" in FR._regime(1.0) and "thin tongue" in FR._regime(50.0),
17892
+ }
17893
+ failed1 = [k_ for k_, v in c1.items() if not v]
17894
+ ok(not failed1,
17895
+ "ED1 the arithmetic: the self-test's ten checks on labelled grids (the unit flow, the radial share, the piston radius, the sharp front, every barrel in place, the "
17896
+ "tongue of a denser water, shut-in slumping, the doublet's analytic breakthrough between the 1% and 20% days, its account closing, nothing beyond a sealing "
17897
+ "fault); a well on the grid passing exactly its rate and a well beyond it acting through the edge with no source inside; a hundred days at 2,000 bbl/d with the "
17898
+ "half contour at the piston radius within a cell; a state cloned and advanced apart from its original; the gravity coefficient by its formula, none without a "
17899
+ "density difference; van Leer's limiter; the regimes' words" + (f" [failed: {', '.join(failed1)}]" if failed1 else ""))
17900
+ # -- ED2 the workspace --------------------------------------------------------------------------------------------------
17901
+ wsp = str(d / "ws"); ws = Workspace.create(wsp, "Pad 3", actor="tester")
17902
+ inj = ws.add_well_records("SWD 1", actor="tester"); prod = ws.add_well_records("Producer 7H", actor="tester"); far = ws.add_well_records("Far 2", actor="tester")
17903
+ dlat = 500.0 * 0.3048 / 111195.0
17904
+ for w_, la, lo in ((inj, 31.96, -102.24), (prod, 31.96 + dlat, -102.24), (far, 32.05, -102.30)):
17905
+ ws.set_well(w_["id"], surface={"lat": la, "lon": lo, "datum": "NAD83", "elevation": {"ft": 2900.0, "datum": "KB", "source": "test plat"}}, actor="tester")
17906
+ ws.set_well(inj["id"], disposal={"top_interval_ft": 8700.0, "base_interval_ft": 9300.0, "depth_reference": "TVD", "depth_tier": "deep"}, actor="tester")
17907
+ kmlon = 1 / (111.195 * math.cos(math.radians(31.96)))
17908
+ feats = [([[(-102.24 + 0.12 * kmlon, 31.955), (-102.24 + 0.12 * kmlon, 31.965)]], {"name": "East fault"})] # 394 ft east of the injector, north-south
17909
+ wkt = 'GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]]'
17910
+ SF.write(str(d / "faults"), "PolyLine", feats, [("name", "C", 20, 0)], wkt)
17911
+ with _zf.ZipFile(str(d / "faults.zip"), "w") as z:
17912
+ for ext in (".shp", ".shx", ".dbf", ".prj"):
17913
+ z.write(str(d / ("faults" + ext)), "faults" + ext)
17914
+ lay = ws.add_layer(str(d / "faults.zip"), "Gate faults", actor="tester", feature_kind="fault", citation="the gate's own layer")
17915
+ empty = FR.page(ws)
17916
+ FL.declare_well(ws, "tester", inj["id"], role="injection", formation="Ellenburger", source="completion report W-2")
17917
+ FL.declare_well(ws, "tester", prod["id"], role="production", formation="Ellenburger", source="permit")
17918
+ FL.declare_well(ws, "tester", far["id"], role="production", formation="Ellenburger", source="permit")
17919
+ sc = FL.synthetic_scene(days=240, leak_fraction=0.0, seed=5) # 8,000 bbl/d at 120,000 mg/L
17920
+ FL.attach_report(ws, "tester", inj["id"], "h10.csv", sc["csv"].encode(), "H-10 (gate)")
17921
+ prow = []
17922
+ for i in range(240): # the producer's water: 60,000 mg/L until day 150, then rising to 81,000
17923
+ tds = 60000 + (0 if i < 150 else min(1.0, (i - 150) / 80.0) * 21000)
17924
+ prow.append(f"{(datetime(2026, 1, 1) + timedelta(days=i)).strftime('%Y-%m-%d')},{50 + i % 7},{2000 + i % 11},{round(tds / 3000) * 3000}")
17925
+ FL.attach_report(ws, "tester", prod["id"], "prod.csv", ("Date,Oil (bbl),Water (bbl),TDS (mg/L)\n" + "\n".join(prow) + "\n").encode(), "production report (gate)")
17926
+ FL.attach_report(ws, "tester", far["id"], "far.csv", ("Date,Water (bbl)\n" + "\n".join(f"{(datetime(2026, 1, 1) + timedelta(days=i)).strftime('%Y-%m-%d')},400" for i in range(240)) + "\n").encode(), "report (gate)")
17927
+ FL.declare_formation(ws, "tester", "Ellenburger", "petrophysics (gate)", porosity=0.12, thickness_ft=100.0, area_acres=11000.0, water_tds_mgl=60000.0)
17928
+ undeclared = FR.page(ws)
17929
+ FL.declare_formation(ws, "tester", "Ellenburger", "petrophysics (gate)", k_md=50.0, mu_cp=0.6, p_initial_psi=3000.0)
17930
+ refused = {}
17931
+ for name, fn in (("cells_even", lambda: FR.set_settings(ws, "tester", cells=80)), ("cells_small", lambda: FR.set_settings(ws, "tester", cells=21)),
17932
+ ("cells_big", lambda: FR.set_settings(ws, "tester", cells=301)), ("proj_short", lambda: FR.set_settings(ws, "tester", projection_days=100)),
17933
+ ("proj_long", lambda: FR.set_settings(ws, "tester", projection_days=99999))):
17934
+ try:
17935
+ fn(); refused[name] = False
17936
+ except FR.FrontError:
17937
+ refused[name] = True
17938
+ FR.set_settings(ws, "tester", cells=61, projection_days=730)
17939
+ pg = FR.page(ws); fr = pg["fronts"][0]
17940
+ again = FR.page(ws)
17941
+ rec = [s_ for s_ in fr["snapshots"] if s_["kind"] == "record"]; cont = [s_ for s_ in fr["snapshots"] if s_["kind"] == "continued"]; shut = [s_ for s_ in fr["snapshots"] if s_["kind"] == "shut-in"]
17942
+ pr = {r_["well"]: r_ for r_ in fr["producers"]}; near = pr[prod["id"]]; a = fr["account"]; dn = fr["density"]
17943
+ m_last = near["measured"][-1]
17944
+ PM.set_settings(ws, "tester", sealing={lay["id"]: True}, source="the gate's fault study")
17945
+ fr2 = FR.page(ws)["fronts"][0]
17946
+ rec2 = [s_ for s_ in fr2["snapshots"] if s_["kind"] == "record"][-1]
17947
+ PM.set_settings(ws, "tester", sealing={lay["id"]: False})
17948
+ # a front built without densities, straight from the ledger's shape: a piston, and the page says why
17949
+ bare_w = {"well": "I", "display": "I", "formation": "F", "role": "injection", "surface": {"lat": 31.0, "lon": -102.0, "datum": "WGS84"},
17950
+ "days": [{"date": (datetime(2026, 1, 1) + timedelta(days=i)).strftime("%Y-%m-%d"), "volume_bbl": 3000.0, "sg": None, "tds_mgl": None} for i in range(60)]}
17951
+ bare = FR.build(bare_w, {"k_md": 30.0, "thickness_ft": 50.0, "porosity": 0.2}, [bare_w], {"cells": 41, "projection_days": 365})
17952
+ brec = [s_ for s_ in bare["snapshots"] if s_["kind"] == "record"][-1]; bshut = [s_ for s_ in bare["snapshots"] if s_["kind"] == "shut-in"]
17953
+ wr = FR.write_report(ws, _ver, "tester")
17954
+ txt = (Path(wr["folder"]) / "front.md").read_text(encoding="utf-8").lower()
17955
+ frame = GD._tm(31.96, -102.24, 1.0, 0.0, 0.0, "WGS84")
17956
+ l3, sk3 = FR.scene_layers(ws, frame)
17957
+ z_top, z_base = 5800.0 * 0.3048, 5900.0 * 0.3048
17958
+ zs = {l_["id"]: sorted({ln["z"] for ln in l_["lines"]}) for l_ in l3}
17959
+ tipz = [ln["z"] for l_ in l3 for ln in l_["lines"] if ln["v"].startswith("0.05 ")]; fullz = [ln["z"] for l_ in l3 for ln in l_["lines"] if ln["v"].startswith("0.95 ")]
17960
+ sc3 = W3.workspace_scene(ws)
17961
+ PM.write_report(ws, _ver, "tester")
17962
+ dz = DZ.build(ws, "tester", _ver, None)
17963
+ names = _zf.ZipFile(Path(ws.reports_dir, dz["path"])).namelist()
17964
+ audit = Path(ws.audit_path).read_text(encoding="utf-8")
17965
+ c2 = {
17966
+ "empty": empty["status"] == "EMPTY" and "No front" in empty["lines"][0],
17967
+ "undeclared": undeclared["fronts"][0]["status"] == "NOT DECLARED" and "k md" in undeclared["fronts"][0]["notes"][0],
17968
+ "refusals": all(refused.values()),
17969
+ "grid": fr["status"] == "OK" and fr["label"] == "SIMULATION" and fr["frame"]["cells"] == 61 and 20.0 < fr["frame"]["dx_ft"] < 200.0 and fr["properties"]["uniform"]
17970
+ and {w_["well"]: w_["in_grid"] for w_ in fr["wells"]} == {inj["id"]: True, prod["id"]: True, far["id"]: False} and again["generated_utc"] == pg["generated_utc"],
17971
+ "density": abs(dn["injected_sg"] - 1.0812) < 0.002 and abs(dn["formation_sg"] - 1.0414) < 0.002 and dn["delta_sg"] > 0.03 and "base" in dn["tongue"] and 0.005 < dn["gravity_number"] < 0.05
17972
+ and "piston" in dn["regime"] and dn["injected_tds_mgl"] == 120000.0,
17973
+ "snapshots": len(rec) == 8 and rec[-1]["day"] == 240 and [s_["day"] for s_ in cont] == [605, 970] and [s_["day"] for s_ in shut] == [605, 970]
17974
+ and all(rec[i]["in_place_bbl"] < rec[i + 1]["in_place_bbl"] for i in range(7)) and rec[-1]["full_equivalent_ft"] < rec[-1]["half_equivalent_ft"] < rec[-1]["tip_reach_ft"]
17975
+ and abs(rec[-1]["half_equivalent_ft"] - rec[-1]["piston_ft"]) < 1.5 * fr["frame"]["dx_ft"] and cont[-1]["half_equivalent_ft"] > rec[-1]["half_equivalent_ft"] * 1.3
17976
+ and shut[-1]["in_place_bbl"] < rec[-1]["in_place_bbl"] and "interface" in rec[-1] and "interface" in cont[-1] and "interface" not in rec[0],
17977
+ "producer": near["in_grid"] and 480.0 < near["distance_ft"] < 520.0 and near["arrival"]["kind"] == "record" and 30.0 < near["arrival"]["day"] < 110.0
17978
+ and near["arrival"]["day"] < near["tenth"]["day"] < near["half"]["day"] and 0.4 < near["share_now"] < 0.95 and near["share_projected"] > near["share_now"]
17979
+ and abs(near["tds_predicted_now"] - (near["share_now"] * 120000.0 + (1 - near["share_now"]) * 60000.0)) < 60.0 and near["produced_back_bbl"] > 10000.0,
17980
+ "measured": near["n_measured"] == 8 and m_last["measured_tds"] == 81000.0 and abs(m_last["implied_share"] - 0.35) < 1e-6
17981
+ and abs(m_last["predicted_tds"] - (m_last["predicted_share"] * 60000.0 + 60000.0)) < 5.0 and m_last["predicted_share"] > 0.4 and "less of the injected water" in near["reading"]
17982
+ and near["mean_abs_difference_tds"] > 5000.0,
17983
+ "far": not pr[far["id"]]["in_grid"] and "beyond the front's grid" in pr[far["id"]]["note"] and pr[far["id"]]["distance_ft"] > 30000.0,
17984
+ "account": abs(a["closure_bbl"]) <= 5.0 and abs(a["injected_bbl"] - sc["truth"]["cum_bbl"]) < 2.0 and a["produced_back_bbl"] == near["produced_back_bbl"] and abs(a["beyond_edge_bbl"]) < 1.0
17985
+ and a["across_open_faults_bbl"] > 10000.0 and rec[-1]["faults"][0]["name"] == "East fault" and "balance_unaccounted_bbl" in a,
17986
+ "sealing": fr2["faults"][0]["sealing"] and fr2["faults"][0]["faces_sealed"] >= 5 and not fr2["faults"][0]["watched"] and rec2["faults"] == []
17987
+ and fr2["account"]["across_open_faults_bbl"] == 0.0 and abs(fr2["account"]["closure_bbl"]) <= 5.0 and rec2["tip_reach_ft"] != rec[-1]["tip_reach_ft"],
17988
+ "bare": bare["status"] == "OK" and bare["density"]["tongue"] is None and bare["density"]["gravity_number"] is None and "piston" in bare["density"]["regime"]
17989
+ and any("no density" in n_ for n_ in bare["notes"]) and abs(brec["half_equivalent_ft"] - FL.swept_radius_ft(180000.0, 50.0, 0.2)) < 1.5 * bare["frame"]["dx_ft"]
17990
+ and len(bshut) == 1 and bshut[0]["in_place_bbl"] == brec["in_place_bbl"] and bare["producers"] == [],
17991
+ "written": set(wr["files"]) == {"front.json", "front.md"} and "simulation" in txt and "account at" in txt and not [t for t in CR.FORBIDDEN_TERMS if t in txt],
17992
+ "three_d": len(l3) == 2 and not sk3 and all(l_["role"] == "front" and l_["lines"] for l_ in l3) and all(z_top - 0.2 <= z_ <= z_base + 0.2 for v_ in zs.values() for z_ in v_)
17993
+ and tipz and fullz and min(tipz) > max(fullz) and any(l_.get("role") == "front" for l_ in sc3["layers"]) and any(l_.get("role") == "plume" for l_ in sc3["layers"]),
17994
+ "dossier": "results/front.json" in names and "results/plume.json" in names and "reports/front/front.md" in names and "declarations/records/front.json" in names
17995
+ and all(x in audit for x in ("front.settings", "front.report")),
17996
+ }
17997
+ failed2 = [k_ for k_, v in c2.items() if not v]
17998
+ ok(not failed2,
17999
+ "ED2 the workspace: no front until the ledger has an injection well, NOT DECLARED until the formation has its permeability; an even, too-small or too-large grid and "
18000
+ "a projection out of range declined; the injector's front on a 61-cell grid of its own with the producer 500 ft away on it and the one seven miles away beyond it, "
18001
+ "the same page handed back while nothing it was computed from changes; the injected water at 120,000 mg/L and 1.081 against the formation's 1.041 - a tongue along "
18002
+ "the base, the gravity number saying the well's flow shapes it; eight month-end snapshots with the water in place growing and the half contour at the piston "
18003
+ "radius within a cell and a half, two continued and two shut in (the producers drawing the water back); the producer's arrival within the record, then a tenth, "
18004
+ "then half, its share now and the TDS that predicts by the mixing line; its report's eight measured values beside the predicted, the last implying 35% against "
18005
+ "more predicted and read as the water arriving later; the account closing within five barrels with the produced-back and the water across the open east fault "
18006
+ "named; the layer declared sealing closing its faces, nothing across, the front another shape; a front without densities a piston at its radius with the reason "
18007
+ "noted and nothing moving once shut in; the report free of the client-report terms; the interface in 3D between the declared top and base with the tip deeper "
18008
+ "than the full thickness for a denser water, in the workspace's scene beside the plume; the dossier's results/front.json, the report and the settings; the audit"
18009
+ + (f" [failed: {', '.join(failed2)}]" if failed2 else ""))
18010
+ # -- ED3 the routes, the tab, the command, the help, the README and the lesson -----------------------------------------------
18011
+ Users(str(Path(wsp, "users.json"))).add("v", "viewer-pass-1", "viewer"); Users(str(Path(wsp, "users.json"))).add("op", "op-pass-123", "operator")
18012
+ svc = Service(wsp, port=0, scheduler=False).start()
18013
+ base_url = svc.url.rstrip("/")
18014
+
18015
+ def opener(name, pw_):
18016
+ o = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(http.cookiejar.CookieJar()))
18017
+ rq = urllib.request.Request(base_url + "/api/login", method="POST", data=json.dumps({"name": name, "password": pw_}).encode())
18018
+ rq.add_header("Content-Type", "application/json"); rq.add_header("X-GEA-Action", "1"); o.open(rq, timeout=30)
18019
+ return o
18020
+
18021
+ def call(o, method, path, body=None):
18022
+ rq = urllib.request.Request(base_url + path, method=method, data=(json.dumps(body).encode() if body is not None else None))
18023
+ if method == "POST":
18024
+ rq.add_header("Content-Type", "application/json"); rq.add_header("X-GEA-Action", "1")
18025
+ try:
18026
+ with o.open(rq, timeout=180) as rr_:
18027
+ return rr_.status, json.loads(rr_.read())
18028
+ except urllib.error.HTTPError as e:
18029
+ return e.code, json.loads(e.read())
18030
+ try:
18031
+ V, O = opener("v", "viewer-pass-1"), opener("op", "op-pass-123")
18032
+ s_vg, vg = call(V, "GET", "/api/front")
18033
+ s_vw, vw = call(V, "GET", "/api/front?well=" + inj["id"])
18034
+ s_vn, vn = call(V, "GET", "/api/front?well=nowhere")
18035
+ s_vs, _ = call(V, "POST", "/api/front/settings", {"cells": 41})
18036
+ s_os, os_ = call(O, "POST", "/api/front/settings", {"cells": "41", "projection_days": "365"})
18037
+ s_bs, _ = call(O, "POST", "/api/front/settings", {"cells": "40"})
18038
+ s_g2, g2 = call(V, "GET", "/api/front")
18039
+ s_ow, ow = call(O, "POST", "/api/front/write", {})
18040
+ s_vx, _ = call(V, "POST", "/api/front/write", {})
18041
+ s_3d, sc3b = call(V, "GET", "/api/3d/scene/workspace")
18042
+ finally:
18043
+ svc.stop()
18044
+ cli_s = _sp.run([sys.executable, "-m", "gea", "front"], capture_output=True, text=True, cwd=str(pkg.parent))
18045
+ cli_w = _sp.run([sys.executable, "-m", "gea", "front", "--workspace", wsp], capture_output=True, text=True, cwd=str(pkg.parent))
18046
+ cli_j = _sp.run([sys.executable, "-m", "gea", "front", "--workspace", wsp, "--well", inj["id"], "--json"], capture_output=True, text=True, cwd=str(pkg.parent))
18047
+ cli_t = _sp.run([sys.executable, "-m", "gea", "front", "--workspace", wsp, "--cells", "41", "--projection-days", "365"], capture_output=True, text=True, cwd=str(pkg.parent))
18048
+ cli_b = _sp.run([sys.executable, "-m", "gea", "front", "--workspace", wsp, "--cells", "40"], capture_output=True, text=True, cwd=str(pkg.parent))
18049
+ cli_r = _sp.run([sys.executable, "-m", "gea", "front", "--workspace", wsp, "--write"], capture_output=True, text=True, cwd=str(pkg.parent))
18050
+ page_src = (pkg / "web" / "app.html").read_text(encoding="utf-8")
18051
+ readme = (pkg.parent / "README.md").read_text(encoding="utf-8") if (pkg.parent / "README.md").is_file() else ""
18052
+ lesson = (pkg / "help" / "tutorial" / "14-production-pages.md").read_text(encoding="utf-8")
18053
+ c3 = {
18054
+ "api": s_vg == 200 and vg["status"] == "OK" and vg["label"] == "SIMULATION" and s_vw == 200 and len(vw["fronts"]) == 1 and s_vn == 200 and vn["status"] == "EMPTY" and s_vs == 403
18055
+ and s_os == 200 and os_["cells"] == 41 and os_["projection_days"] == 365 and s_bs == 400 and s_g2 == 200 and g2["fronts"][0]["frame"]["cells"] == 41
18056
+ and g2["fronts"][0]["projection_days"] == 365 and s_ow == 200 and "front.json" in ow["files"] and s_vx == 403
18057
+ and s_3d == 200 and any(l_.get("role") == "front" for l_ in sc3b.get("layers", [])),
18058
+ "cli": cli_s.returncode == 0 and "OK - SIMULATION" in cli_s.stdout and cli_w.returncode == 0 and "snapshots" in cli_w.stdout and "shut-in" in cli_w.stdout and "Account at" in cli_w.stdout
18059
+ and cli_j.returncode == 0 and json.loads(cli_j.stdout)["fronts"][0]["well"] == inj["id"] and cli_t.returncode == 0 and "cells 41" in cli_t.stdout
18060
+ and cli_b.returncode != 0 and "odd number" in cli_b.stderr and cli_r.returncode == 0 and "front.md" in cli_r.stdout,
18061
+ "page": all(x in page_src for x in ("VIEWS.front", "['#/front', 'Fluid front']", "/api/front/settings", "ffPlan", "ffSection", "help('front')")),
18062
+ "help": not H.check("front") and H.VIEW_TOPIC.get("front") == "front" and any(t == "front" for t, _, _ in H.INDEX)
18063
+ and all(x in (H.page("front") or "") for x in ("van Leer", "0.433", "SIMULATION", "gea front --workspace C:\\site", "pi phi h d^2 / (3 q)")),
18064
+ "readme_lesson": (not readme or ("### Fluid front" in readme and "`gea front`" in readme)) and "Fluid front" in lesson and "front" in lesson.split("Help:")[-1],
18065
+ }
18066
+ failed3 = [k_ for k_, v in c3.items() if not v]
18067
+ ok(not failed3,
18068
+ "ED3 on the API (anyone reads the fronts, one well's or all; only an operator keeps settings or writes; an even grid is 400; the 3D scene carries the interface), the "
18069
+ "command (the self-test, the snapshots and the account, one well as JSON, settings kept and an even grid stopped, the report), the tab with its plan and its "
18070
+ "section, the help page, the README and lesson 14" + (f" [failed: {', '.join(failed3)}]" if failed3 else ""))
18071
+
18072
+
17842
18073
  def main() -> int:
17843
18074
  print("GEA-Program - ACCEPTANCE SUITE (the product gate)")
17844
18075
  # a handle a job subprocess still holds at the end must not turn a finished gate into a traceback on Windows:
@@ -17975,6 +18206,7 @@ def main() -> int:
17975
18206
  section_ea_vpn_client(tmp)
17976
18207
  section_eb_fluid(tmp)
17977
18208
  section_ec_plume(tmp)
18209
+ section_ed_front(tmp)
17978
18210
  if _FAILS:
17979
18211
  print(f"[ACCEPTANCE] {len(_FAILS)} FAILURES ({_PASS} passed):")
17980
18212
  for f in _FAILS:
@@ -269,6 +269,7 @@ def _gather(ws, well_id: Optional[str]) -> Dict[str, List[tuple]]:
269
269
  files_in(rep, 'reports')
270
270
  files_in(os.path.join(rep, 'fluid'), 'reports/fluid') # the fluid ledger and the material balance
271
271
  files_in(os.path.join(rep, 'plume'), 'reports/plume') # the pressure plume (SIMULATION)
272
+ files_in(os.path.join(rep, 'front'), 'reports/front') # the fluid front (SIMULATION)
272
273
  for w in wells:
273
274
  files_in(os.path.join(rep, 'wells', w['id']), f"reports/wells/{w['id']}")
274
275
  out_list = out['declaration']
@@ -286,7 +287,7 @@ def _gather(ws, well_id: Optional[str]) -> Dict[str, List[tuple]]:
286
287
  ('drillstring', 'casing.json'), ('wellpath', 'collision.json'), ('wellpath', 'survey_program.json'),
287
288
  ('completion', 'frac', 'stages.json'), ('completion', 'frac', 'settings.json'), ('geomech', 'pore_pressure.json'),
288
289
  ('drillstring', 'torque_drag.json'), ('economics', 'production', 'production.json'), ('drillstring', 'hydraulics.json'),
289
- ('drillstring', 'casing_design.json'), ('records', 'fluid.json'), ('records', 'plume.json')):
290
+ ('drillstring', 'casing_design.json'), ('records', 'fluid.json'), ('records', 'plume.json'), ('records', 'front.json')):
290
291
  p = os.path.join(ws.path, *rel)
291
292
  if os.path.isfile(p):
292
293
  out_list.append((p, 'declarations/' + '/'.join(rel)))
@@ -424,6 +425,11 @@ def _results(ws, well_id: Optional[str]) -> List[tuple]:
424
425
  if pp['plumes']:
425
426
  slim = [{**pl, 'snapshots': [{k: v for k, v in s_.items() if k != 'contours'} for s_ in pl.get('snapshots', [])]} for pl in pp['plumes']]
426
427
  out.append(('results/plume.json', json.dumps({**pp, 'plumes': slim}, indent=1, sort_keys=True, default=str).encode('utf-8')))
428
+ from . import front as FRd
429
+ fr = FRd.page(ws)
430
+ if fr['fronts']:
431
+ slim = [{**f_, 'snapshots': [{k: v for k, v in s_.items() if k not in ('contours', 'interface')} for s_ in f_.get('snapshots', [])]} for f_ in fr['fronts']]
432
+ out.append(('results/front.json', json.dumps({**fr, 'fronts': slim}, indent=1, sort_keys=True, default=str).encode('utf-8')))
427
433
  except Exception as e:
428
434
  out.append(('results/fluid_not_run.txt', f'the fluid balance and the plume did not run: {type(e).__name__}: {e}\n'.encode('utf-8')))
429
435
  return out