diff --git a/.integrated_tests.yaml b/.integrated_tests.yaml
index 2cb02daa192..622c1da3d1b 100644
--- a/.integrated_tests.yaml
+++ b/.integrated_tests.yaml
@@ -1,6 +1,7 @@
baselines:
bucket: geosx
- baseline: integratedTests/baseline_integratedTests-pr3228-9676-61994fe
+ baseline: integratedTests/baseline_integratedTests-pr3416-9790-5bdb1fa
+
allow_fail:
all: ''
streak: ''
diff --git a/BASELINE_NOTES.md b/BASELINE_NOTES.md
index ea19f4ac5cd..4304e1b9671 100644
--- a/BASELINE_NOTES.md
+++ b/BASELINE_NOTES.md
@@ -6,6 +6,14 @@ This file is designed to track changes to the integrated test baselines.
Any developer who updates the baseline ID in the .integrated_tests.yaml file is expected to create an entry in this file with the pull request number, date, and their justification for rebaselining.
These notes should be in reverse-chronological order, and use the following time format: (YYYY-MM-DD).
+PR #3416 (2024-01-21)
+=====================
+Refactoring of induced seismicity EQ solvers to add coupling.
+
+PR #3310 (2024-01-21)
+======================
+Scalable rock toughness required new field.
+
PR #3228 (2024-01-15)
=====================
deltaVolume added in multiphase.
diff --git a/examples/pygeosxExamples/modifyBoundaryCondition/pkn_example.xml b/examples/pygeosxExamples/modifyBoundaryCondition/pkn_example.xml
index 94db4f07eb6..23aed51fc40 100644
--- a/examples/pygeosxExamples/modifyBoundaryCondition/pkn_example.xml
+++ b/examples/pygeosxExamples/modifyBoundaryCondition/pkn_example.xml
@@ -62,7 +62,7 @@
diff --git a/inputFiles/hydraulicFracturing/Sneddon_hydroFrac_base.xml b/inputFiles/hydraulicFracturing/Sneddon_hydroFrac_base.xml
index df05297ad3d..e23f6d8b315 100644
--- a/inputFiles/hydraulicFracturing/Sneddon_hydroFrac_base.xml
+++ b/inputFiles/hydraulicFracturing/Sneddon_hydroFrac_base.xml
@@ -37,7 +37,7 @@
name="SurfaceGen"
targetRegions="{ Domain }"
nodeBasedSIF="1"
- rockToughness="10.0e6"
+ initialRockToughness="10.0e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/hydraulicFracturing/heterogeneousInSitu_base.xml b/inputFiles/hydraulicFracturing/heterogeneousInSitu_base.xml
index c8d741170ae..d4547ebc54f 100644
--- a/inputFiles/hydraulicFracturing/heterogeneousInSitu_base.xml
+++ b/inputFiles/hydraulicFracturing/heterogeneousInSitu_base.xml
@@ -53,7 +53,7 @@
diff --git a/inputFiles/hydraulicFracturing/heterogeneousInSitu_smoke.xml b/inputFiles/hydraulicFracturing/heterogeneousInSitu_smoke.xml
index eb7b96bf286..3fc20c5c95a 100644
--- a/inputFiles/hydraulicFracturing/heterogeneousInSitu_smoke.xml
+++ b/inputFiles/hydraulicFracturing/heterogeneousInSitu_smoke.xml
@@ -71,7 +71,7 @@
diff --git a/inputFiles/hydraulicFracturing/hydrofractureSinglePhase2d.xml b/inputFiles/hydraulicFracturing/hydrofractureSinglePhase2d.xml
index 7ac70ce7a6f..9fe4afed5b4 100644
--- a/inputFiles/hydraulicFracturing/hydrofractureSinglePhase2d.xml
+++ b/inputFiles/hydraulicFracturing/hydrofractureSinglePhase2d.xml
@@ -34,7 +34,7 @@
+ initialRockToughness="1.0e6"/>
diff --git a/inputFiles/hydraulicFracturing/kgdEdgeBased_C3D6_base.xml b/inputFiles/hydraulicFracturing/kgdEdgeBased_C3D6_base.xml
index cc461b52ba3..0120cd3f6dd 100644
--- a/inputFiles/hydraulicFracturing/kgdEdgeBased_C3D6_base.xml
+++ b/inputFiles/hydraulicFracturing/kgdEdgeBased_C3D6_base.xml
@@ -49,7 +49,7 @@
diff --git a/inputFiles/hydraulicFracturing/kgdNodeBased_C3D6_base.xml b/inputFiles/hydraulicFracturing/kgdNodeBased_C3D6_base.xml
index d7fbbd5d077..f9d7ac88c37 100644
--- a/inputFiles/hydraulicFracturing/kgdNodeBased_C3D6_base.xml
+++ b/inputFiles/hydraulicFracturing/kgdNodeBased_C3D6_base.xml
@@ -39,7 +39,7 @@
diff --git a/inputFiles/hydraulicFracturing/kgdToughnessDominated_base.xml b/inputFiles/hydraulicFracturing/kgdToughnessDominated_base.xml
index 96d400a8390..74b8003e223 100644
--- a/inputFiles/hydraulicFracturing/kgdToughnessDominated_base.xml
+++ b/inputFiles/hydraulicFracturing/kgdToughnessDominated_base.xml
@@ -45,7 +45,7 @@
name="SurfaceGen"
targetRegions="{ Domain }"
nodeBasedSIF="1"
- rockToughness="1e6"
+ initialRockToughness="1e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/hydraulicFracturing/kgdToughnessDominated_poroelastic_base.xml b/inputFiles/hydraulicFracturing/kgdToughnessDominated_poroelastic_base.xml
index 8f4284dd838..ad91b77dfaf 100644
--- a/inputFiles/hydraulicFracturing/kgdToughnessDominated_poroelastic_base.xml
+++ b/inputFiles/hydraulicFracturing/kgdToughnessDominated_poroelastic_base.xml
@@ -38,7 +38,7 @@
name="SurfaceGen"
targetRegions="{ Domain }"
nodeBasedSIF="1"
- rockToughness="1e6"
+ initialRockToughness="1e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/hydraulicFracturing/kgdValidation_base.xml b/inputFiles/hydraulicFracturing/kgdValidation_base.xml
index e2d16b6d247..a902e5f5fab 100644
--- a/inputFiles/hydraulicFracturing/kgdValidation_base.xml
+++ b/inputFiles/hydraulicFracturing/kgdValidation_base.xml
@@ -44,7 +44,7 @@
logLevel="1"
targetRegions="{ Domain }"
nodeBasedSIF="0"
- rockToughness="1.2e6"
+ initialRockToughness="1.2e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/hydraulicFracturing/kgdViscosityDominated_base.xml b/inputFiles/hydraulicFracturing/kgdViscosityDominated_base.xml
index e9b55058b17..5138b7c1eca 100644
--- a/inputFiles/hydraulicFracturing/kgdViscosityDominated_base.xml
+++ b/inputFiles/hydraulicFracturing/kgdViscosityDominated_base.xml
@@ -45,7 +45,7 @@
name="SurfaceGen"
targetRegions="{ Domain }"
nodeBasedSIF="1"
- rockToughness="1e4"
+ initialRockToughness="1e4"
mpiCommOrder="1"/>
diff --git a/inputFiles/hydraulicFracturing/kgdViscosityDominated_poroelastic_base.xml b/inputFiles/hydraulicFracturing/kgdViscosityDominated_poroelastic_base.xml
index 15a381c8365..32f2f25e7eb 100644
--- a/inputFiles/hydraulicFracturing/kgdViscosityDominated_poroelastic_base.xml
+++ b/inputFiles/hydraulicFracturing/kgdViscosityDominated_poroelastic_base.xml
@@ -38,7 +38,7 @@
name="SurfaceGen"
targetRegions="{ Domain }"
nodeBasedSIF="1"
- rockToughness="1e4"
+ initialRockToughness="1e4"
mpiCommOrder="1"
isPoroelastic="1"/>
diff --git a/inputFiles/hydraulicFracturing/pennyShapedAnisotropicScaledToughness_benchmark.xml b/inputFiles/hydraulicFracturing/pennyShapedAnisotropicScaledToughness_benchmark.xml
new file mode 100644
index 00000000000..6d05d924d31
--- /dev/null
+++ b/inputFiles/hydraulicFracturing/pennyShapedAnisotropicScaledToughness_benchmark.xml
@@ -0,0 +1,182 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/inputFiles/hydraulicFracturing/pennyShapedAnisotropicToughness_base.xml b/inputFiles/hydraulicFracturing/pennyShapedAnisotropicToughness_base.xml
new file mode 100644
index 00000000000..63c2c6fb575
--- /dev/null
+++ b/inputFiles/hydraulicFracturing/pennyShapedAnisotropicToughness_base.xml
@@ -0,0 +1,228 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/inputFiles/hydraulicFracturing/pennyShapedAnisotropicToughness_benchmark.xml b/inputFiles/hydraulicFracturing/pennyShapedAnisotropicToughness_benchmark.xml
new file mode 100644
index 00000000000..6affb33bc1b
--- /dev/null
+++ b/inputFiles/hydraulicFracturing/pennyShapedAnisotropicToughness_benchmark.xml
@@ -0,0 +1,180 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/inputFiles/hydraulicFracturing/pennyShapedAnisotropicToughness_smoke.xml b/inputFiles/hydraulicFracturing/pennyShapedAnisotropicToughness_smoke.xml
new file mode 100644
index 00000000000..a566f9c4c42
--- /dev/null
+++ b/inputFiles/hydraulicFracturing/pennyShapedAnisotropicToughness_smoke.xml
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/inputFiles/hydraulicFracturing/pennyShapedToughnessDominated_benchmark.xml b/inputFiles/hydraulicFracturing/pennyShapedToughnessDominated_benchmark.xml
index 59abb35871a..eb9183bcf82 100644
--- a/inputFiles/hydraulicFracturing/pennyShapedToughnessDominated_benchmark.xml
+++ b/inputFiles/hydraulicFracturing/pennyShapedToughnessDominated_benchmark.xml
@@ -67,7 +67,7 @@
name="SurfaceGen"
targetRegions="{ Domain }"
nodeBasedSIF="1"
- rockToughness="3.0e6"
+ initialRockToughness="3.0e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/hydraulicFracturing/pennyShapedToughnessDominated_poroelastic_benchmark.xml b/inputFiles/hydraulicFracturing/pennyShapedToughnessDominated_poroelastic_benchmark.xml
index e830a52c5fd..b20f9c443af 100644
--- a/inputFiles/hydraulicFracturing/pennyShapedToughnessDominated_poroelastic_benchmark.xml
+++ b/inputFiles/hydraulicFracturing/pennyShapedToughnessDominated_poroelastic_benchmark.xml
@@ -68,7 +68,7 @@
name="SurfaceGen"
targetRegions="{ Domain }"
nodeBasedSIF="1"
- rockToughness="3.0e6"
+ initialRockToughness="3.0e6"
mpiCommOrder="1"
isPoroelastic="1"/>
diff --git a/inputFiles/hydraulicFracturing/pennyShapedToughnessDominated_poroelastic_smoke.xml b/inputFiles/hydraulicFracturing/pennyShapedToughnessDominated_poroelastic_smoke.xml
index a1c1c302b8d..8d074c2ea9e 100644
--- a/inputFiles/hydraulicFracturing/pennyShapedToughnessDominated_poroelastic_smoke.xml
+++ b/inputFiles/hydraulicFracturing/pennyShapedToughnessDominated_poroelastic_smoke.xml
@@ -44,7 +44,7 @@
name="SurfaceGen"
targetRegions="{ Domain }"
nodeBasedSIF="1"
- rockToughness="3.0e6"
+ initialRockToughness="3.0e6"
mpiCommOrder="1"
isPoroelastic="1"/>
diff --git a/inputFiles/hydraulicFracturing/pennyShapedToughnessDominated_smoke.xml b/inputFiles/hydraulicFracturing/pennyShapedToughnessDominated_smoke.xml
index f433335ab6e..acf8e93e6b7 100644
--- a/inputFiles/hydraulicFracturing/pennyShapedToughnessDominated_smoke.xml
+++ b/inputFiles/hydraulicFracturing/pennyShapedToughnessDominated_smoke.xml
@@ -43,7 +43,7 @@
name="SurfaceGen"
targetRegions="{ Domain }"
nodeBasedSIF="1"
- rockToughness="3.0e6"
+ initialRockToughness="3.0e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/hydraulicFracturing/pennyShapedViscosityDominated_benchmark.xml b/inputFiles/hydraulicFracturing/pennyShapedViscosityDominated_benchmark.xml
index a8f78adf606..eef546604d1 100644
--- a/inputFiles/hydraulicFracturing/pennyShapedViscosityDominated_benchmark.xml
+++ b/inputFiles/hydraulicFracturing/pennyShapedViscosityDominated_benchmark.xml
@@ -68,7 +68,7 @@
name="SurfaceGen"
targetRegions="{ Domain }"
nodeBasedSIF="1"
- rockToughness="0.3e6"
+ initialRockToughness="0.3e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/hydraulicFracturing/pennyShapedViscosityDominated_poroelastic_benchmark.xml b/inputFiles/hydraulicFracturing/pennyShapedViscosityDominated_poroelastic_benchmark.xml
index 0d1b9485772..eb476baf5fe 100644
--- a/inputFiles/hydraulicFracturing/pennyShapedViscosityDominated_poroelastic_benchmark.xml
+++ b/inputFiles/hydraulicFracturing/pennyShapedViscosityDominated_poroelastic_benchmark.xml
@@ -69,7 +69,7 @@
name="SurfaceGen"
targetRegions="{ Domain }"
nodeBasedSIF="1"
- rockToughness="0.3e6"
+ initialRockToughness="0.3e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/hydraulicFracturing/pennyShapedViscosityDominated_poroelastic_smoke.xml b/inputFiles/hydraulicFracturing/pennyShapedViscosityDominated_poroelastic_smoke.xml
index b3a8341224e..5cb156cd184 100644
--- a/inputFiles/hydraulicFracturing/pennyShapedViscosityDominated_poroelastic_smoke.xml
+++ b/inputFiles/hydraulicFracturing/pennyShapedViscosityDominated_poroelastic_smoke.xml
@@ -44,7 +44,7 @@
name="SurfaceGen"
targetRegions="{ Domain }"
nodeBasedSIF="1"
- rockToughness="0.3e6"
+ initialRockToughness="0.3e6"
mpiCommOrder="1"
isPoroelastic="1"/>
diff --git a/inputFiles/hydraulicFracturing/pennyShapedViscosityDominated_smoke.xml b/inputFiles/hydraulicFracturing/pennyShapedViscosityDominated_smoke.xml
index 4b20bae5125..c84b65ef8f5 100644
--- a/inputFiles/hydraulicFracturing/pennyShapedViscosityDominated_smoke.xml
+++ b/inputFiles/hydraulicFracturing/pennyShapedViscosityDominated_smoke.xml
@@ -43,7 +43,7 @@
name="SurfaceGen"
targetRegions="{ Domain }"
nodeBasedSIF="1"
- rockToughness="0.3e6"
+ initialRockToughness="0.3e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/hydraulicFracturing/pknViscosityDominated_benchmark.xml b/inputFiles/hydraulicFracturing/pknViscosityDominated_benchmark.xml
index 2b8dce7a719..4943e0f6d78 100644
--- a/inputFiles/hydraulicFracturing/pknViscosityDominated_benchmark.xml
+++ b/inputFiles/hydraulicFracturing/pknViscosityDominated_benchmark.xml
@@ -66,7 +66,7 @@
name="SurfaceGen"
targetRegions="{ Domain }"
nodeBasedSIF="1"
- rockToughness="0.1e6"
+ initialRockToughness="0.1e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/hydraulicFracturing/pknViscosityDominated_poroelastic_benchmark.xml b/inputFiles/hydraulicFracturing/pknViscosityDominated_poroelastic_benchmark.xml
index 72b1be2f4d8..e73a06ddcc4 100644
--- a/inputFiles/hydraulicFracturing/pknViscosityDominated_poroelastic_benchmark.xml
+++ b/inputFiles/hydraulicFracturing/pknViscosityDominated_poroelastic_benchmark.xml
@@ -66,7 +66,7 @@
name="SurfaceGen"
targetRegions="{ Domain }"
nodeBasedSIF="1"
- rockToughness="0.1e6"
+ initialRockToughness="0.1e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/hydraulicFracturing/pknViscosityDominated_poroelastic_smoke.xml b/inputFiles/hydraulicFracturing/pknViscosityDominated_poroelastic_smoke.xml
index 7e8e3463e18..f6e44b9bc91 100644
--- a/inputFiles/hydraulicFracturing/pknViscosityDominated_poroelastic_smoke.xml
+++ b/inputFiles/hydraulicFracturing/pknViscosityDominated_poroelastic_smoke.xml
@@ -44,7 +44,7 @@
name="SurfaceGen"
targetRegions="{ Domain }"
nodeBasedSIF="1"
- rockToughness="0.1e6"
+ initialRockToughness="0.1e6"
mpiCommOrder="1"
isPoroelastic="1"/>
diff --git a/inputFiles/hydraulicFracturing/pknViscosityDominated_smoke.xml b/inputFiles/hydraulicFracturing/pknViscosityDominated_smoke.xml
index 0545171c3bc..87e732e3f37 100644
--- a/inputFiles/hydraulicFracturing/pknViscosityDominated_smoke.xml
+++ b/inputFiles/hydraulicFracturing/pknViscosityDominated_smoke.xml
@@ -43,7 +43,7 @@
name="SurfaceGen"
targetRegions="{ Domain }"
nodeBasedSIF="1"
- rockToughness="1e4"
+ initialRockToughness="1e4"
mpiCommOrder="1"/>
diff --git a/inputFiles/hydraulicFracturing/scripts/hydrofractureFigure.py b/inputFiles/hydraulicFracturing/scripts/hydrofractureFigure.py
index c8cb897201d..81dde7f93f7 100644
--- a/inputFiles/hydraulicFracturing/scripts/hydrofractureFigure.py
+++ b/inputFiles/hydraulicFracturing/scripts/hydrofractureFigure.py
@@ -36,7 +36,7 @@ def getParametersFromXML( geosDir, xmlFilePrefix):
poissonRatio = float(elasticParam.get('defaultPoissonRatio'))
injectionRate = -2.0 * float(tree.find('FieldSpecifications/SourceFlux').get('scale')) / fluidDensity
tree = ElementTree.parse(prefix + xmlFilePrefix + "_base.xml")
- toughness = float(tree.find('Solvers/SurfaceGenerator').get('rockToughness'))
+ toughness = float(tree.find('Solvers/SurfaceGenerator').get('initialRockToughness'))
elif xmlFilePrefix == 'pennyShapedToughnessDominated' or xmlFilePrefix == 'pennyShapedViscosityDominated':
K = float(elasticParam.get('defaultBulkModulus'))
@@ -45,7 +45,7 @@ def getParametersFromXML( geosDir, xmlFilePrefix):
poissonRatio = youngModulus / (2.0 * G) - 1.0
injectionRate = -4.0 * float(tree.find('FieldSpecifications/SourceFlux').get('scale')) / fluidDensity
tree = ElementTree.parse(prefix + xmlFilePrefix + "_benchmark.xml")
- toughness = float(tree.find('Solvers/SurfaceGenerator').get('rockToughness'))
+ toughness = float(tree.find('Solvers/SurfaceGenerator').get('initialRockToughness'))
elif xmlFilePrefix == 'pknViscosityDominated':
K = float(elasticParam.get('defaultBulkModulus'))
@@ -54,7 +54,7 @@ def getParametersFromXML( geosDir, xmlFilePrefix):
poissonRatio = youngModulus / (2.0 * G) - 1.0
injectionRate = -4.0 * float(tree.find('FieldSpecifications/SourceFlux').get('scale')) / fluidDensity
tree = ElementTree.parse(prefix + xmlFilePrefix + "_benchmark.xml")
- toughness = float(tree.find('Solvers/SurfaceGenerator').get('rockToughness'))
+ toughness = float(tree.find('Solvers/SurfaceGenerator').get('initialRockToughness'))
found_core = False
for elem in param:
if elem.get("name") == "core":
diff --git a/inputFiles/hydraulicFracturing/walshQuarterNoChombo_benchmark.xml b/inputFiles/hydraulicFracturing/walshQuarterNoChombo_benchmark.xml
index 957b63bd278..a14bdc856f1 100644
--- a/inputFiles/hydraulicFracturing/walshQuarterNoChombo_benchmark.xml
+++ b/inputFiles/hydraulicFracturing/walshQuarterNoChombo_benchmark.xml
@@ -79,7 +79,7 @@
fractureRegion="Fracture"
targetRegions="{Domain, void}"
nodeBasedSIF="1"
- rockToughness="3.0e6">
+ initialRockToughness="3.0e6">
diff --git a/inputFiles/hydraulicFracturing/walshQuarterNoChombo_smoke.xml b/inputFiles/hydraulicFracturing/walshQuarterNoChombo_smoke.xml
index 9990dd5c291..1a9a5a0ae73 100644
--- a/inputFiles/hydraulicFracturing/walshQuarterNoChombo_smoke.xml
+++ b/inputFiles/hydraulicFracturing/walshQuarterNoChombo_smoke.xml
@@ -64,7 +64,7 @@
fractureRegion="Fracture"
targetRegions="{Domain, void}"
nodeBasedSIF="1"
- rockToughness="3.0e6"
+ initialRockToughness="3.0e6"
mpiCommOrder="1">
diff --git a/inputFiles/inducedSeismicity/SCEC_BP6_QD_S_base.xml b/inputFiles/inducedSeismicity/SCEC_BP6_QD_S_base.xml
new file mode 100644
index 00000000000..1257f1ae3ec
--- /dev/null
+++ b/inputFiles/inducedSeismicity/SCEC_BP6_QD_S_base.xml
@@ -0,0 +1,217 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/inputFiles/inducedSeismicity/SCEC_BP6_QD_S_explicit.xml b/inputFiles/inducedSeismicity/SCEC_BP6_QD_S_explicit.xml
new file mode 100644
index 00000000000..fbbfccd5b38
--- /dev/null
+++ b/inputFiles/inducedSeismicity/SCEC_BP6_QD_S_explicit.xml
@@ -0,0 +1,139 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/inputFiles/inducedSeismicity/SCEC_BP6_QD_S_implicit.xml b/inputFiles/inducedSeismicity/SCEC_BP6_QD_S_implicit.xml
new file mode 100644
index 00000000000..1b74521b1ad
--- /dev/null
+++ b/inputFiles/inducedSeismicity/SCEC_BP6_QD_S_implicit.xml
@@ -0,0 +1,140 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/inputFiles/inducedSeismicity/SCEC_BP7_QD_base.xml b/inputFiles/inducedSeismicity/SCEC_BP7_QD_base.xml
new file mode 100644
index 00000000000..08fc7cb9930
--- /dev/null
+++ b/inputFiles/inducedSeismicity/SCEC_BP7_QD_base.xml
@@ -0,0 +1,251 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/inputFiles/inducedSeismicity/SpringSliderExplicit_base.xml b/inputFiles/inducedSeismicity/SpringSliderExplicit_base.xml
deleted file mode 100644
index a0c0381fb23..00000000000
--- a/inputFiles/inducedSeismicity/SpringSliderExplicit_base.xml
+++ /dev/null
@@ -1,167 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/inputFiles/inducedSeismicity/SpringSliderExplicit_smoke.xml b/inputFiles/inducedSeismicity/SpringSliderExplicit_smoke.xml
index 2de09b79a03..a1a67094f7c 100644
--- a/inputFiles/inducedSeismicity/SpringSliderExplicit_smoke.xml
+++ b/inputFiles/inducedSeismicity/SpringSliderExplicit_smoke.xml
@@ -2,8 +2,19 @@
+ name="./SpringSlider_base.xml"/>
+
+
+
+
+
@@ -23,6 +34,32 @@
maxEventDt="1e4"
target="/Solvers/SpringSlider"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/inputFiles/inducedSeismicity/SpringSlider_base.xml b/inputFiles/inducedSeismicity/SpringSlider_base.xml
index 5f6aefc94ad..876457fa2dd 100644
--- a/inputFiles/inducedSeismicity/SpringSlider_base.xml
+++ b/inputFiles/inducedSeismicity/SpringSlider_base.xml
@@ -1,19 +1,10 @@
-
-
-
@@ -80,27 +71,26 @@
-
+
diff --git a/inputFiles/inducedSeismicity/SpringSlider_smoke.xml b/inputFiles/inducedSeismicity/SpringSlider_smoke.xml
deleted file mode 100644
index b10580131d8..00000000000
--- a/inputFiles/inducedSeismicity/SpringSlider_smoke.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/inputFiles/inducedSeismicity/inducedSeismicity.ats b/inputFiles/inducedSeismicity/inducedSeismicity.ats
index 813bdf08b8b..56aea6b5820 100644
--- a/inputFiles/inducedSeismicity/inducedSeismicity.ats
+++ b/inputFiles/inducedSeismicity/inducedSeismicity.ats
@@ -23,7 +23,7 @@ decks = [
check_step=100,
curvecheck_params=CurveCheckParameters(**curvecheck_params)),
TestDeck(
- name="SpringSlider_smoke",
+ name="SpringSliderImplicit_smoke",
description="Spring slider 0D system",
partitions=((1, 1, 1), ),
restart_step=0,
@@ -34,7 +34,7 @@ decks = [
description="Spring slider 0D system",
partitions=((1, 1, 1), ),
restart_step=0,
- check_step=532,
+ check_step=343,
restartcheck_params=RestartcheckParameters(atol=1e-4, rtol=1e-3))
]
generate_geos_tests(decks)
diff --git a/inputFiles/inducedSeismicity/scripts/plotBP6_results.py b/inputFiles/inducedSeismicity/scripts/plotBP6_results.py
new file mode 100644
index 00000000000..e869c3d5b5a
--- /dev/null
+++ b/inputFiles/inducedSeismicity/scripts/plotBP6_results.py
@@ -0,0 +1,78 @@
+import argparse
+import numpy as np
+from geos.hdf5_wrapper import hdf5_wrapper
+import matplotlib.pyplot as plt
+import os
+
+def remove_padding(data):
+ """Removes trailing zeros from a NumPy array."""
+ nonzero_indices = np.nonzero(data)[0]
+ if nonzero_indices.size == 0: # If all elements are zero
+ return np.array([]), np.array([])
+ last_nonzero = nonzero_indices[-1]
+ return data[:last_nonzero + 1]
+
+def getDataFromHDF5( hdf5FilePath, var_name ):
+ # Read HDF5
+ data = hdf5_wrapper(f'{hdf5FilePath}').get_copy()
+ var = data[f'{var_name} source']
+ var = np.asarray(var)
+ time = data[f'{var_name} Time']
+
+ # Remove padding
+ var = remove_padding(var)
+ time = time[:len(var)] # Match the length of the time array to the variable
+ return time, var
+
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser()
+ parser.add_argument('-d', '--dir', type=str, help='Path to hdf5 file')
+ args = parser.parse_args()
+
+ normalized_dir = os.path.abspath(args.dir)
+ if not os.path.isdir(normalized_dir):
+ print(f"Error: {normalized_dir} is not a valid directory.")
+ exit(1)
+
+ filePath = f"{normalized_dir}/BP6_DQ_S.hdf5"
+ if not os.path.exists(filePath):
+ print(f"Error: {filePath} not found.")
+ exit(1)
+
+ time, pressure = getDataFromHDF5( filePath, "pressure" )
+ time, slipRate = getDataFromHDF5( filePath, "slipRate" )
+
+ # Convert time to years
+ time_in_years = time / (365 * 24 * 3600) # Assuming time is in seconds
+
+ # Plotting
+ fig, ax1 = plt.subplots()
+
+ print(len(time_in_years))
+ print(len(pressure))
+
+ # Plot pressure on the left y-axis
+ ax1.set_xlabel('Time (years)')
+ ax1.set_ylabel('Pressure (Pa)', color='tab:blue')
+ ax1.plot(time_in_years, pressure, label="Pressure", color='tab:blue')
+ ax1.tick_params(axis='y', labelcolor='tab:blue')
+
+
+ # Plot slipRate on the right y-axis (log scale)
+ ax2 = ax1.twinx()
+ ax2.set_ylabel('Slip Rate (m/s)', color='tab:red')
+ ax2.plot(time_in_years, slipRate, label="Slip Rate", color='tab:red')
+ ax2.set_yscale('log')
+ ax2.tick_params(axis='y', labelcolor='tab:red')
+
+ # Set x-axis limits to 0 to 2 years
+ ax1.set_xlim(0, np.max(time_in_years))
+
+
+ # Add grid and title
+ plt.title("Pressure and Slip Rate vs Time")
+ plt.grid()
+
+ # Show plot
+ plt.show()
\ No newline at end of file
diff --git a/inputFiles/inducedSeismicity/scripts/plot_springSlider_results.py b/inputFiles/inducedSeismicity/scripts/plot_springSlider_results.py
new file mode 100644
index 00000000000..ac56838015b
--- /dev/null
+++ b/inputFiles/inducedSeismicity/scripts/plot_springSlider_results.py
@@ -0,0 +1,74 @@
+import argparse
+import numpy as np
+from geos.hdf5_wrapper import hdf5_wrapper
+import matplotlib.pyplot as plt
+import os
+
+def remove_padding(data):
+ """Removes trailing zeros from a NumPy array."""
+ nonzero_indices = np.nonzero(data)[0]
+ if nonzero_indices.size == 0: # If all elements are zero
+ return np.array([]), np.array([])
+ last_nonzero = nonzero_indices[-1]
+ return data[:last_nonzero + 1]
+
+def getDataFromHDF5( hdf5FilePath, var_name ):
+ # Read HDF5
+ data = hdf5_wrapper(f'{hdf5FilePath}').get_copy()
+ var = data[f'{var_name}']
+ var = np.asarray(var)
+ time = data[f'{var_name} Time']
+
+ # Remove padding
+ var = remove_padding(var)
+ time = time[:len(var)] # Match the length of the time array to the variable
+ return time, var
+
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser()
+ parser.add_argument('-d', '--dir', type=str, help='Path to hdf5 file')
+ args = parser.parse_args()
+
+ normalized_dir = os.path.abspath(args.dir)
+ if not os.path.isdir(normalized_dir):
+ print(f"Error: {normalized_dir} is not a valid directory.")
+ exit(1)
+
+ filePath = f"{normalized_dir}/springSlider.hdf5"
+ if not os.path.exists(filePath):
+ print(f"Error: {filePath} not found.")
+ exit(1)
+
+ time, slipRate = getDataFromHDF5( filePath, "slipRate" )
+ time, stateVariable = getDataFromHDF5( filePath, "stateVariable" )
+
+ # Convert time to years
+ time_in_years = time / (365 * 24 * 3600) # Assuming time is in seconds
+
+ # Plotting
+ fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(8, 8), sharex=True)
+
+ # Plot pressure on the left y-axis
+ ax1.set_xlabel('Time (years)')
+ ax1.set_ylabel('slip rate (Pa)', color='tab:blue')
+ ax1.plot(time_in_years, slipRate, label="slip rate", color='tab:blue')
+ ax1.set_yscale('log')
+ ax1.tick_params(axis='y', labelcolor='tab:blue')
+
+ # Set x-axis limits to 0 to 2 years
+ ax1.set_xlim(0, np.max(time_in_years))
+
+ # Plot stateVariable on the right y-axis (log scale)
+ ax2.set_ylabel('state variable', color='tab:red')
+ ax2.plot(time_in_years, stateVariable, label="state variable", color='tab:red')
+ ax2.tick_params(axis='y', labelcolor='tab:red')
+ ax2.set_xlim(0, np.max(time_in_years))
+
+ # Add grid and title
+ fig.suptitle('Spring slider solution', fontsize=16)
+ plt.tight_layout()
+ plt.grid()
+
+ # Show plot
+ plt.show()
\ No newline at end of file
diff --git a/inputFiles/lagrangianContactMechanics/LagrangeContactBubbleStab_FixedSlip_smoke.xml b/inputFiles/lagrangianContactMechanics/LagrangeContactBubbleStab_FixedSlip_smoke.xml
index 8258d2cc4a3..5da14675d94 100644
--- a/inputFiles/lagrangianContactMechanics/LagrangeContactBubbleStab_FixedSlip_smoke.xml
+++ b/inputFiles/lagrangianContactMechanics/LagrangeContactBubbleStab_FixedSlip_smoke.xml
@@ -30,7 +30,7 @@
diff --git a/inputFiles/lagrangianContactMechanics/LagrangeContactBubbleStab_singleFracCompression_base.xml b/inputFiles/lagrangianContactMechanics/LagrangeContactBubbleStab_singleFracCompression_base.xml
index 854136ed032..3be52a9bcdc 100644
--- a/inputFiles/lagrangianContactMechanics/LagrangeContactBubbleStab_singleFracCompression_base.xml
+++ b/inputFiles/lagrangianContactMechanics/LagrangeContactBubbleStab_singleFracCompression_base.xml
@@ -30,7 +30,7 @@
logLevel="0"
fractureRegion="Fracture"
targetRegions="{ Region }"
- rockToughness="1.0e6"
+ initialRockToughness="1.0e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/lagrangianContactMechanics/PassingCrack_base.xml b/inputFiles/lagrangianContactMechanics/PassingCrack_base.xml
index 1f38c231aa9..603fcf59ed7 100644
--- a/inputFiles/lagrangianContactMechanics/PassingCrack_base.xml
+++ b/inputFiles/lagrangianContactMechanics/PassingCrack_base.xml
@@ -7,7 +7,7 @@
diff --git a/inputFiles/lagrangianContactMechanics/SimpleCubes_base.xml b/inputFiles/lagrangianContactMechanics/SimpleCubes_base.xml
index 32e64f498de..ce7f07de63b 100644
--- a/inputFiles/lagrangianContactMechanics/SimpleCubes_base.xml
+++ b/inputFiles/lagrangianContactMechanics/SimpleCubes_base.xml
@@ -6,7 +6,7 @@
@@ -134,7 +134,7 @@
-
diff --git a/inputFiles/lagrangianContactMechanics/SingleFracCompression_base.xml b/inputFiles/lagrangianContactMechanics/SingleFracCompression_base.xml
index d9da50caf95..c3f39da2632 100644
--- a/inputFiles/lagrangianContactMechanics/SingleFracCompression_base.xml
+++ b/inputFiles/lagrangianContactMechanics/SingleFracCompression_base.xml
@@ -9,7 +9,7 @@
logLevel="0"
fractureRegion="Fracture"
targetRegions="{ Region }"
- rockToughness="1.0e6"
+ initialRockToughness="1.0e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/lagrangianContactMechanics/SlippingFault_base.xml b/inputFiles/lagrangianContactMechanics/SlippingFault_base.xml
index 5299794fe0f..d9f4997f3c7 100644
--- a/inputFiles/lagrangianContactMechanics/SlippingFault_base.xml
+++ b/inputFiles/lagrangianContactMechanics/SlippingFault_base.xml
@@ -9,7 +9,7 @@
logLevel="0"
fractureRegion="Fracture"
targetRegions="{ Region }"
- rockToughness="1.0e6"
+ initialRockToughness="1.0e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/lagrangianContactMechanics/Sneddon_benchmark.xml b/inputFiles/lagrangianContactMechanics/Sneddon_benchmark.xml
index 7750053d6fa..d45bc7ded1f 100644
--- a/inputFiles/lagrangianContactMechanics/Sneddon_benchmark.xml
+++ b/inputFiles/lagrangianContactMechanics/Sneddon_benchmark.xml
@@ -13,7 +13,7 @@
logLevel="0"
fractureRegion="Fracture"
targetRegions="{ Region }"
- rockToughness="1.0e6"
+ initialRockToughness="1.0e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/lagrangianContactMechanics/Sneddon_smoke.xml b/inputFiles/lagrangianContactMechanics/Sneddon_smoke.xml
index 5e64b204ad1..5794ed344e5 100644
--- a/inputFiles/lagrangianContactMechanics/Sneddon_smoke.xml
+++ b/inputFiles/lagrangianContactMechanics/Sneddon_smoke.xml
@@ -13,7 +13,7 @@
logLevel="0"
fractureRegion="Fracture"
targetRegions="{ Region }"
- rockToughness="1.0e6"
+ initialRockToughness="1.0e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/lagrangianContactMechanics/TFrac_benchmark.xml b/inputFiles/lagrangianContactMechanics/TFrac_benchmark.xml
index 60f1a1f537a..5a6d6b5a8b7 100644
--- a/inputFiles/lagrangianContactMechanics/TFrac_benchmark.xml
+++ b/inputFiles/lagrangianContactMechanics/TFrac_benchmark.xml
@@ -13,7 +13,7 @@
logLevel="0"
fractureRegion="Fracture"
targetRegions="{ Region }"
- rockToughness="1.0e6"
+ initialRockToughness="1.0e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/lagrangianContactMechanics/TFrac_smoke.xml b/inputFiles/lagrangianContactMechanics/TFrac_smoke.xml
index 5ab56b69af9..cd3543f0806 100644
--- a/inputFiles/lagrangianContactMechanics/TFrac_smoke.xml
+++ b/inputFiles/lagrangianContactMechanics/TFrac_smoke.xml
@@ -12,7 +12,7 @@
logLevel="0"
fractureRegion="Fracture"
targetRegions="{ Region }"
- rockToughness="1.0e6"
+ initialRockToughness="1.0e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/lagrangianContactMechanics/UnstructuredCrack_base.xml b/inputFiles/lagrangianContactMechanics/UnstructuredCrack_base.xml
index 628fd884589..81cddb50913 100644
--- a/inputFiles/lagrangianContactMechanics/UnstructuredCrack_base.xml
+++ b/inputFiles/lagrangianContactMechanics/UnstructuredCrack_base.xml
@@ -6,7 +6,7 @@
diff --git a/inputFiles/lagrangianContactMechanics/scripts/generateTables.py b/inputFiles/lagrangianContactMechanics/scripts/generateTables.py
new file mode 100644
index 00000000000..9c83614b2f4
--- /dev/null
+++ b/inputFiles/lagrangianContactMechanics/scripts/generateTables.py
@@ -0,0 +1,179 @@
+import numpy as np
+import os
+import sys
+import xml.etree.ElementTree as ElementTree
+import matplotlib
+import matplotlib.pyplot as plt
+
+class SingularCrackSlip:
+
+ def __init__(self, mechanicalParameters, length ):
+ K = mechanicalParameters["bulkModulus"]
+ G = mechanicalParameters["shearModulus"]
+ poisson_ratio= (3 * K - 2 * G) / (2 * (3 * K + G))
+
+ mu_star = G /( 1 - poisson_ratio)
+ self.tau_0 = 0.0
+ self.tau_r = -1.0
+
+ self.scaling = 2*(self.tau_0 - self.tau_r)/mu_star
+ self.halfLength = length
+
+ def computeSlip(self, x):
+ return self.scaling * np.sqrt(self.halfLength**2 - x**2)
+
+ def computeTraction(self, x):
+ if x < -self.halfLength or x > self.halfLength:
+ return self.tau_0 + (self.tau_0-self.tau_r) * ( np.abs(x)/np.sqrt(x**2 - self.halfLength**2) - 1 )
+ else:
+ return self.tau_r
+class GaussianSlip:
+
+ def __init__(self, peakStrength, length ):
+ self.scaling = peakStrength
+ self.halfLength = length
+
+ def computeSlip(self, x):
+ denom = 1 / (self.halfLength/2)
+ return self.scaling*np.exp(-0.5*((x)/denom)**2)
+
+def getMechanicalParametersFromXML(xmlFilePath):
+ tree = ElementTree.parse(xmlFilePath)
+
+ param = tree.find('Constitutive/ElasticIsotropic')
+
+ mechanicalParameters = dict.fromkeys(["bulkModulus", "shearModulus"])
+ mechanicalParameters["bulkModulus"] = float(param.get("defaultBulkModulus"))
+ mechanicalParameters["shearModulus"] = float(param.get("defaultShearModulus"))
+ return mechanicalParameters
+
+def getFractureLengthFromXML(xmlFilePath):
+ tree = ElementTree.parse(xmlFilePath)
+
+ rectangle = tree.find('Geometry/Box')
+ xmin = rectangle.get("xMin")
+ xmax = rectangle.get("xMax")
+ xmin = [float(i) for i in xmin[1:-1].split(",")]
+ xmax = [float(i) for i in xmax[1:-1].split(",")]
+ length = ( xmax[0] - xmin[0] ) / 2
+ origin = 0.0
+
+ return length, origin
+
+def plot_traction_solution():
+ # Read HDF5
+ import hdf5_wrapper
+ hdf5File1Path = "Output/traction.hdf5"
+
+ # Read HDF5
+ data = hdf5_wrapper.hdf5_wrapper(hdf5File1Path).get_copy()
+ traction = data['traction']
+ traction = np.asarray(traction)
+ traction_geos = traction[0, :, 1]
+ x = data['traction elementCenter']
+ x_geos = x[0, :, 0]
+
+ #-------- Extract info from XML
+ xmlFilePath = "/Users/cusini1/geosx/GEOSX/inputFiles/lagrangianContactMechanics/LagrangeContactBubbleStab_FixedSlip_base.xml"
+
+ mechanicalParameters = getMechanicalParametersFromXML(xmlFilePath)
+
+ # Get length of the fracture
+ xmlFilePath = "/Users/cusini1/geosx/GEOSX/inputFiles/lagrangianContactMechanics/LagrangeContactBubbleStab_FixedSlip_smoke.xml"
+ totalHalfLength, originShift = getFractureLengthFromXML(xmlFilePath)
+ halfLength = 2.0
+
+ singularCrackSlipSolution = SingularCrackSlip(mechanicalParameters, halfLength)
+ x = np.linspace(-totalHalfLength, totalHalfLength, 10000, endpoint=True)
+ traction_analytical = np.zeros(len(x))
+ i = 0
+ for xCell in x:
+ traction_analytical[i] = singularCrackSlipSolution.computeTraction(xCell)
+ i += 1
+
+ fsize = 30
+ msize = 15
+ lw = 2
+ fig, ax = plt.subplots(1, figsize=(16, 12))
+ cmap = plt.get_cmap("tab10")
+
+ # Plot analytical (continuous line) and numerical (markers) aperture solution
+ ax.plot(x, traction_analytical, color='r', label='Traction analytical', lw=lw)
+ ax.plot(x_geos, traction_geos, color='k', label='geos', marker="o", lw=lw)
+
+ ax.set_xlabel('Fault coordinate [m]', size=fsize, weight="bold")
+ ax.set_ylabel('Shear traction', size=fsize, weight="bold")
+ ax.legend(bbox_to_anchor=(0.75, 0.9), loc='center', borderaxespad=0., fontsize=fsize)
+ ax.xaxis.set_tick_params(labelsize=fsize)
+ ax.yaxis.set_tick_params(labelsize=fsize)
+ plt.savefig("traction.png")
+
+def output_tables(x, slip, name):
+ # Save x to x.csv with one value per row
+ np.savetxt('x.csv', x, fmt='%f')
+
+ # Save aperture_analytical to jump.csv with one value per row
+ np.savetxt(f'{name}.csv', slip, fmt='%f')
+
+
+def debug():
+ #-------- Extract info from XML
+ xmlFilePath = "/Users/cusini1/geosx/GEOSX/inputFiles/lagrangianContactMechanics/LagrangeContactBubbleStab_FixedSlip_base.xml"
+
+ mechanicalParameters = getMechanicalParametersFromXML(xmlFilePath)
+ appliedPressure = 1.0
+
+ # Get length of the fracture
+ xmlFilePath = "/Users/cusini1/geosx/GEOSX/inputFiles/lagrangianContactMechanics/LagrangeContactBubbleStab_FixedSlip_smoke.xml"
+ totalHalfLength, originShift = getFractureLengthFromXML(xmlFilePath)
+ halfLength = 2.0
+
+ # Initialize Sneddon's analytical solution
+ singularCrackSlipSolution = SingularCrackSlip(mechanicalParameters, halfLength )
+ peakStrength = 3.0
+ gaussianSlipSolution = GaussianSlip( peakStrength, halfLength)
+
+ # Plot analytical (continuous line) and numerical (markers) aperture solution
+ x = np.linspace(-totalHalfLength, totalHalfLength, 100000, endpoint=True)
+ singularCrackSlip = np.zeros(len(x))
+ gaussianSlip = np.zeros(len(x))
+ i = 0
+ for xCell in x:
+ if xCell > -halfLength and xCell < halfLength:
+ singularCrackSlip[i] = singularCrackSlipSolution.computeSlip(xCell)
+ gaussianSlip[i] = gaussianSlipSolution.computeSlip(xCell)
+ i += 1
+
+ fsize = 24
+ msize = 15
+ lw = 6
+ fig, ax = plt.subplots(1, figsize=(16, 12))
+ cmap = plt.get_cmap("tab10")
+
+ ax.plot(x, singularCrackSlip , color='k', label='Analytical Solution', lw=lw)
+ ax.grid()
+ ax.set_xlabel('Fault coordinate [m]', size=fsize, weight="bold")
+ ax.set_ylabel('slip [m]', size=fsize, weight="bold")
+ ax.legend(bbox_to_anchor=(0.7, 1), loc='center', borderaxespad=0., fontsize=fsize)
+ ax.xaxis.set_tick_params(labelsize=fsize)
+ ax.yaxis.set_tick_params(labelsize=fsize)
+ plt.savefig("singularCrackSlip.png")
+
+ fig, ax = plt.subplots(1, figsize=(16, 12))
+ cmap = plt.get_cmap("tab10")
+
+ ax.plot(x, gaussianSlip , color='k', label='Analytical Solution', lw=lw)
+ ax.grid()
+ ax.set_xlabel('Fault coordinate [m]', size=fsize, weight="bold")
+ ax.set_ylabel('slip [m]', size=fsize, weight="bold")
+ ax.legend(bbox_to_anchor=(0.75, 0.9), loc='center', borderaxespad=0., fontsize=fsize)
+ ax.xaxis.set_tick_params(labelsize=fsize)
+ ax.yaxis.set_tick_params(labelsize=fsize)
+ plt.savefig("gaussianSlip.png")
+
+ output_tables(x, singularCrackSlip, "singularCrackSlip")
+ output_tables(x, gaussianSlip, "gaussianSlip")
+
+if __name__ == "__main__":
+ debug()
+ plot_traction_solution()
diff --git a/inputFiles/phaseField/PhaseFieldFracture_Nucleation_base.xml b/inputFiles/phaseField/PhaseFieldFracture_Nucleation_base.xml
index e339684d116..c69b54535cc 100644
--- a/inputFiles/phaseField/PhaseFieldFracture_Nucleation_base.xml
+++ b/inputFiles/phaseField/PhaseFieldFracture_Nucleation_base.xml
@@ -52,7 +52,7 @@
diff --git a/inputFiles/poromechanicsFractures/ExponentialDecayPermeability_conformingFracture_base.xml b/inputFiles/poromechanicsFractures/ExponentialDecayPermeability_conformingFracture_base.xml
index d21f7f7fb80..d47a5af1807 100644
--- a/inputFiles/poromechanicsFractures/ExponentialDecayPermeability_conformingFracture_base.xml
+++ b/inputFiles/poromechanicsFractures/ExponentialDecayPermeability_conformingFracture_base.xml
@@ -44,7 +44,7 @@
name="SurfaceGen"
targetRegions="{ Domain }"
fractureRegion="Fracture"
- rockToughness="1e6"
+ initialRockToughness="1e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/poromechanicsFractures/PoroElastic_conformingFracture_2d_faultSlip_sequential_solvers.xml b/inputFiles/poromechanicsFractures/PoroElastic_conformingFracture_2d_faultSlip_sequential_solvers.xml
index 845f3151232..a5e47f2cc74 100755
--- a/inputFiles/poromechanicsFractures/PoroElastic_conformingFracture_2d_faultSlip_sequential_solvers.xml
+++ b/inputFiles/poromechanicsFractures/PoroElastic_conformingFracture_2d_faultSlip_sequential_solvers.xml
@@ -53,7 +53,7 @@
name="SurfaceGen"
targetRegions="{ Domain }"
fractureRegion="Fracture"
- rockToughness="1e6"
+ initialRockToughness="1e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/poromechanicsFractures/PoroElastic_conformingFracture_2d_faultSlip_solvers.xml b/inputFiles/poromechanicsFractures/PoroElastic_conformingFracture_2d_faultSlip_solvers.xml
index 2c8d9f8936b..73f5391756c 100755
--- a/inputFiles/poromechanicsFractures/PoroElastic_conformingFracture_2d_faultSlip_solvers.xml
+++ b/inputFiles/poromechanicsFractures/PoroElastic_conformingFracture_2d_faultSlip_solvers.xml
@@ -45,7 +45,7 @@
name="SurfaceGen"
targetRegions="{ Domain }"
fractureRegion="Fracture"
- rockToughness="1e6"
+ initialRockToughness="1e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/poromechanicsFractures/PoroElastic_conformingFracture_2d_openingFrac_sequential_solvers.xml b/inputFiles/poromechanicsFractures/PoroElastic_conformingFracture_2d_openingFrac_sequential_solvers.xml
index 4112be144f1..d11f90503d8 100755
--- a/inputFiles/poromechanicsFractures/PoroElastic_conformingFracture_2d_openingFrac_sequential_solvers.xml
+++ b/inputFiles/poromechanicsFractures/PoroElastic_conformingFracture_2d_openingFrac_sequential_solvers.xml
@@ -52,7 +52,7 @@
name="SurfaceGen"
targetRegions="{ Domain }"
fractureRegion="Fracture"
- rockToughness="1e6"
+ initialRockToughness="1e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/poromechanicsFractures/PoroElastic_conformingFracture_2d_openingFrac_solvers.xml b/inputFiles/poromechanicsFractures/PoroElastic_conformingFracture_2d_openingFrac_solvers.xml
index cc365b429c6..d2c9d1fd433 100755
--- a/inputFiles/poromechanicsFractures/PoroElastic_conformingFracture_2d_openingFrac_solvers.xml
+++ b/inputFiles/poromechanicsFractures/PoroElastic_conformingFracture_2d_openingFrac_solvers.xml
@@ -44,7 +44,7 @@
name="SurfaceGen"
targetRegions="{ Domain }"
fractureRegion="Fracture"
- rockToughness="1e6"
+ initialRockToughness="1e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/proppant/FlowProppantBedTransport2d_base.xml b/inputFiles/proppant/FlowProppantBedTransport2d_base.xml
index 177a83e6c00..d8bc681d588 100644
--- a/inputFiles/proppant/FlowProppantBedTransport2d_base.xml
+++ b/inputFiles/proppant/FlowProppantBedTransport2d_base.xml
@@ -50,7 +50,7 @@
diff --git a/inputFiles/proppant/FlowProppantTransport2d_base.xml b/inputFiles/proppant/FlowProppantTransport2d_base.xml
index ab806c51cf2..8f4608a6577 100644
--- a/inputFiles/proppant/FlowProppantTransport2d_base.xml
+++ b/inputFiles/proppant/FlowProppantTransport2d_base.xml
@@ -53,7 +53,7 @@
diff --git a/inputFiles/proppant/ProppantGelTransport_base.xml b/inputFiles/proppant/ProppantGelTransport_base.xml
index b4e7e74b4d6..425b5bdb5da 100644
--- a/inputFiles/proppant/ProppantGelTransport_base.xml
+++ b/inputFiles/proppant/ProppantGelTransport_base.xml
@@ -53,7 +53,7 @@
+ initialRockToughness="1e6"/>
diff --git a/inputFiles/proppant/ProppantSlotTest_benchmark.xml b/inputFiles/proppant/ProppantSlotTest_benchmark.xml
index 4c123fc1fc6..73025434ce8 100755
--- a/inputFiles/proppant/ProppantSlotTest_benchmark.xml
+++ b/inputFiles/proppant/ProppantSlotTest_benchmark.xml
@@ -92,7 +92,7 @@
diff --git a/inputFiles/proppant/ProppantSlotTest_smoke.xml b/inputFiles/proppant/ProppantSlotTest_smoke.xml
index 0576291d3b3..757e67d5f0d 100755
--- a/inputFiles/proppant/ProppantSlotTest_smoke.xml
+++ b/inputFiles/proppant/ProppantSlotTest_smoke.xml
@@ -102,7 +102,7 @@
diff --git a/inputFiles/singlePhaseFlowFractures/fractureFlowWithGravity_conforming_2d_smoke.xml b/inputFiles/singlePhaseFlowFractures/fractureFlowWithGravity_conforming_2d_smoke.xml
index 9dbce69a6a6..9045289c402 100644
--- a/inputFiles/singlePhaseFlowFractures/fractureFlowWithGravity_conforming_2d_smoke.xml
+++ b/inputFiles/singlePhaseFlowFractures/fractureFlowWithGravity_conforming_2d_smoke.xml
@@ -18,7 +18,7 @@
diff --git a/inputFiles/singlePhaseFlowFractures/fractureFlow_conforming_2d.xml b/inputFiles/singlePhaseFlowFractures/fractureFlow_conforming_2d.xml
index 3e5ebf1c94f..93eba8a2ebd 100644
--- a/inputFiles/singlePhaseFlowFractures/fractureFlow_conforming_2d.xml
+++ b/inputFiles/singlePhaseFlowFractures/fractureFlow_conforming_2d.xml
@@ -17,7 +17,7 @@
diff --git a/inputFiles/singlePhaseFlowFractures/fractureJunctionFlow_conforming_2d.xml b/inputFiles/singlePhaseFlowFractures/fractureJunctionFlow_conforming_2d.xml
index e1902e65f51..a85f2e3b715 100644
--- a/inputFiles/singlePhaseFlowFractures/fractureJunctionFlow_conforming_2d.xml
+++ b/inputFiles/singlePhaseFlowFractures/fractureJunctionFlow_conforming_2d.xml
@@ -17,7 +17,7 @@
diff --git a/inputFiles/singlePhaseFlowFractures/fractureMatrixFlowWithGravity_conforming_2d_smoke.xml b/inputFiles/singlePhaseFlowFractures/fractureMatrixFlowWithGravity_conforming_2d_smoke.xml
index 8f7226b2f85..2250f3b5fe5 100644
--- a/inputFiles/singlePhaseFlowFractures/fractureMatrixFlowWithGravity_conforming_2d_smoke.xml
+++ b/inputFiles/singlePhaseFlowFractures/fractureMatrixFlowWithGravity_conforming_2d_smoke.xml
@@ -18,7 +18,7 @@
diff --git a/inputFiles/singlePhaseFlowFractures/fractureMatrixFlow_conforming_2d.xml b/inputFiles/singlePhaseFlowFractures/fractureMatrixFlow_conforming_2d.xml
index 6d9f7f2692e..7f475b928ab 100644
--- a/inputFiles/singlePhaseFlowFractures/fractureMatrixFlow_conforming_2d.xml
+++ b/inputFiles/singlePhaseFlowFractures/fractureMatrixFlow_conforming_2d.xml
@@ -18,7 +18,7 @@
diff --git a/inputFiles/singlePhaseFlowFractures/impermeableFault_conforming_base.xml b/inputFiles/singlePhaseFlowFractures/impermeableFault_conforming_base.xml
index c05815fe353..13ed96f0b8c 100644
--- a/inputFiles/singlePhaseFlowFractures/impermeableFault_conforming_base.xml
+++ b/inputFiles/singlePhaseFlowFractures/impermeableFault_conforming_base.xml
@@ -18,7 +18,7 @@
diff --git a/inputFiles/surfaceGeneration/DryFrac_StaticPenny_PrismElem.xml b/inputFiles/surfaceGeneration/DryFrac_StaticPenny_PrismElem.xml
index f398d7beb79..ada8953f37b 100644
--- a/inputFiles/surfaceGeneration/DryFrac_StaticPenny_PrismElem.xml
+++ b/inputFiles/surfaceGeneration/DryFrac_StaticPenny_PrismElem.xml
@@ -20,7 +20,7 @@
@@ -190,5 +190,5 @@
name="restartOutput"/>
-
+
diff --git a/inputFiles/surfaceGeneration/cube_8.xml b/inputFiles/surfaceGeneration/cube_8.xml
index 2f002bb34b9..b5920ca47fa 100644
--- a/inputFiles/surfaceGeneration/cube_8.xml
+++ b/inputFiles/surfaceGeneration/cube_8.xml
@@ -21,7 +21,7 @@
name="SurfaceGen"
logLevel="1"
targetRegions="{ Region2 }"
- rockToughness="1e60"
+ initialRockToughness="1e60"
mpiCommOrder="1" />
@@ -231,5 +231,5 @@
name="restartOutput"/>
-
+
diff --git a/inputFiles/thermalSinglePhaseFlowFractures/fractureMatrixThermalFlow_conforming_base.xml b/inputFiles/thermalSinglePhaseFlowFractures/fractureMatrixThermalFlow_conforming_base.xml
index 57cfd350256..9c903ebf0e4 100644
--- a/inputFiles/thermalSinglePhaseFlowFractures/fractureMatrixThermalFlow_conforming_base.xml
+++ b/inputFiles/thermalSinglePhaseFlowFractures/fractureMatrixThermalFlow_conforming_base.xml
@@ -25,7 +25,7 @@
diff --git a/inputFiles/thermoPoromechanicsFractures/ThermoPoroElastic_conforming_base.xml b/inputFiles/thermoPoromechanicsFractures/ThermoPoroElastic_conforming_base.xml
index e32a27879d0..69ebbdcaaba 100644
--- a/inputFiles/thermoPoromechanicsFractures/ThermoPoroElastic_conforming_base.xml
+++ b/inputFiles/thermoPoromechanicsFractures/ThermoPoroElastic_conforming_base.xml
@@ -47,7 +47,7 @@
name="SurfaceGenerator"
targetRegions="{ RockMatrix }"
fractureRegion="Fracture"
- rockToughness="1e6"
+ initialRockToughness="1e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/wellbore/CasedElasticWellbore_ImperfectInterfaces_base.xml b/inputFiles/wellbore/CasedElasticWellbore_ImperfectInterfaces_base.xml
index 0f782918ec9..fb52fd5f479 100644
--- a/inputFiles/wellbore/CasedElasticWellbore_ImperfectInterfaces_base.xml
+++ b/inputFiles/wellbore/CasedElasticWellbore_ImperfectInterfaces_base.xml
@@ -22,7 +22,7 @@
name="SurfaceGen"
fractureRegion="Fracture"
targetRegions="{ casing, cement, rock }"
- rockToughness="1.0e6"
+ initialRockToughness="1.0e6"
mpiCommOrder="1"/>
diff --git a/inputFiles/wellbore/CasedThermoElasticWellbore_ImperfectInterfaces_base.xml b/inputFiles/wellbore/CasedThermoElasticWellbore_ImperfectInterfaces_base.xml
index ae8b6baea35..ab4ccf65952 100644
--- a/inputFiles/wellbore/CasedThermoElasticWellbore_ImperfectInterfaces_base.xml
+++ b/inputFiles/wellbore/CasedThermoElasticWellbore_ImperfectInterfaces_base.xml
@@ -53,7 +53,7 @@
name="SurfaceGen"
fractureRegion="Fracture"
targetRegions="{ casing, cement, rock }"
- rockToughness="1.0e6"
+ initialRockToughness="1.0e6"
mpiCommOrder="1"/>
diff --git a/scripts/ci_build_and_test_in_container.sh b/scripts/ci_build_and_test_in_container.sh
index 6e6ed6e1609..348fe6ad229 100755
--- a/scripts/ci_build_and_test_in_container.sh
+++ b/scripts/ci_build_and_test_in_container.sh
@@ -337,11 +337,13 @@ fi
# Cleaning the build directory.
or_die cmake --build . --target clean
-
# Clean the repository
or_die cd ${GEOS_SRC_DIR}/inputFiles
find . -name *.pyc | xargs rm -f
+# Clean the rst files
+echo "Cleaning the rst files..."
+or_die rm -rf ${GEOS_SRC_DIR}/src/docs/sphinx/datastructure
# If we're here, either everything went OK or we have to deal with the integrated tests manually.
if [[ ! -z "${INTEGRATED_TEST_EXIT_STATUS+x}" ]]; then
diff --git a/src/coreComponents/common/MpiWrapper.hpp b/src/coreComponents/common/MpiWrapper.hpp
index 22def51e1e8..4d017ef8393 100644
--- a/src/coreComponents/common/MpiWrapper.hpp
+++ b/src/coreComponents/common/MpiWrapper.hpp
@@ -315,7 +315,7 @@ struct MpiWrapper
int sendcount,
T_RECV * recvbuf,
int recvcount,
- MPI_Comm comm );
+ MPI_Comm comm = MPI_COMM_GEOS );
/**
* @brief Strongly typed wrapper around MPI_Allgatherv.
@@ -335,7 +335,7 @@ struct MpiWrapper
T_RECV * recvbuf,
int * recvcounts,
int * displacements,
- MPI_Comm comm );
+ MPI_Comm comm = MPI_COMM_GEOS );
/**
* @brief Convenience function for MPI_Allgather.
@@ -422,10 +422,10 @@ struct MpiWrapper
template< typename T >
- static int scan( T const * sendbuf, T * recvbuf, int count, MPI_Op op, MPI_Comm comm );
+ static int scan( T const * sendbuf, T * recvbuf, int count, MPI_Op op, MPI_Comm comm = MPI_COMM_GEOS );
template< typename T >
- static int exscan( T const * sendbuf, T * recvbuf, int count, MPI_Op op, MPI_Comm comm );
+ static int exscan( T const * sendbuf, T * recvbuf, int count, MPI_Op op, MPI_Comm comm = MPI_COMM_GEOS );
/**
* @brief Strongly typed wrapper around MPI_Bcast.
@@ -436,7 +436,7 @@ struct MpiWrapper
* @return The return value of the underlying call to MPI_Bcast().
*/
template< typename T >
- static int bcast( T * buffer, int count, int root, MPI_Comm comm );
+ static int bcast( T * buffer, int count, int root, MPI_Comm comm = MPI_COMM_GEOS );
/**
@@ -466,7 +466,28 @@ struct MpiWrapper
TR * const recvbuf,
int recvcount,
int root,
- MPI_Comm comm );
+ MPI_Comm comm = MPI_COMM_GEOS );
+
+ /**
+ * @brief Strongly typed wrapper around MPI_Gather().
+ * @tparam TS The pointer type for \p sendbuf
+ * @tparam TR The pointer type for \p recvbuf
+ * @param[in] sendbuf The pointer to the sending buffer.
+ * @param[out] recvbuf The pointer to the receive buffer.
+ * @param[in] recvcount The number of values to receive.
+ * @param[in] root The rank recieving the data.
+ * @param[in] comm The MPI_Comm over which the gather operates.
+ * @return
+ */
+ template< typename T, typename DST_CONTAINER,
+ typename = std::enable_if_t<
+ std::is_trivially_copyable_v< T > &&
+ std::is_same_v< decltype(std::declval< DST_CONTAINER >().size()), std::size_t > &&
+ std::is_same_v< decltype(std::declval< DST_CONTAINER >().data()), T * > > >
+ static int gather( T const & value,
+ DST_CONTAINER & destValuesBuffer,
+ int root,
+ MPI_Comm comm = MPI_COMM_GEOS );
/**
* @brief Strongly typed wrapper around MPI_Gatherv.
@@ -489,7 +510,7 @@ struct MpiWrapper
const int * recvcounts,
const int * displs,
int root,
- MPI_Comm comm );
+ MPI_Comm comm = MPI_COMM_GEOS );
/**
* @brief Returns an MPI_Op associated with our strongly typed Reduction enum.
@@ -900,6 +921,25 @@ int MpiWrapper::gather( TS const * const sendbuf,
#endif
}
+template< typename T, typename DST_CONTAINER, typename >
+int MpiWrapper::gather( T const & value,
+ DST_CONTAINER & destValuesBuffer,
+ int root,
+ MPI_Comm MPI_PARAM( comm ) )
+{
+ if( commRank() == 0 )
+ GEOS_ERROR_IF_LT_MSG( destValuesBuffer.size(), size_t( commSize() ),
+ "Receive buffer is not large enough to contain the values to receive." );
+#ifdef GEOS_USE_MPI
+ return MPI_Gather( &value, sizeof( T ), internal::getMpiType< uint8_t >(),
+ destValuesBuffer.data(), sizeof( T ), internal::getMpiType< uint8_t >(),
+ root, comm );
+#else
+ memcpy( destValuesBuffer.data(), &value, sendBufferSize );
+ return 0;
+#endif
+}
+
template< typename TS, typename TR >
int MpiWrapper::gatherv( TS const * const sendbuf,
int sendcount,
diff --git a/src/coreComponents/common/format/table/TableData.cpp b/src/coreComponents/common/format/table/TableData.cpp
index 5153bf58752..517613fcf50 100644
--- a/src/coreComponents/common/format/table/TableData.cpp
+++ b/src/coreComponents/common/format/table/TableData.cpp
@@ -18,39 +18,38 @@
*/
#include "TableData.hpp"
+#include "common/logger/Logger.hpp"
namespace geos
{
-void TableData::addRow( std::vector< string > const & row )
+void TableData::addRow( std::vector< TableData::CellData > const & row )
{
- if( m_rows.size() != 0 && row.size() != m_rows[m_rows.size() - 1].size() )
+ m_rows.push_back( row );
+}
+
+void TableData::addSeparator()
+{
+ if( m_rows.empty())
{
- string msg = "Remarks : some cells may be missing";
- if( std::find( m_errorsMsg.begin(), m_errorsMsg.end(), msg ) == m_errorsMsg.end())
- {
- m_errorsMsg.push_back( msg );
- }
+ GEOS_ERROR( "Bad use of a Tabledata::addSeparator(). Make sure you have added values in TableData" );
}
- m_rows.push_back( row );
+
+ integer rowSize = m_rows[0].size();
+ m_rows.emplace_back( std::vector< TableData::CellData >( rowSize, { CellType::Separator, "-" } ));
+
}
void TableData::clear()
{
m_rows.clear();
- m_errorsMsg.clear();
}
-std::vector< std::vector< string > > const & TableData::getTableDataRows() const
+std::vector< std::vector< TableData::CellData > > const & TableData::getTableDataRows() const
{
return m_rows;
}
-std::vector< string > const & TableData::getErrorMsgs() const
-{
- return m_errorsMsg;
-}
-
void TableData2D::collectTableValues( arraySlice1d< real64 const > rowAxisValues,
arraySlice1d< real64 const > columnAxisValues,
arrayView1d< real64 const > values )
@@ -75,7 +74,6 @@ TableData2D::TableDataHolder TableData2D::convertTable2D( arrayView1d< real64 co
{
string const rowFmt = GEOS_FMT( "{} = {{}}", rowAxisDescription );
string const columnFmt = GEOS_FMT( "{} = {{}}", columnAxisDescription );
-
collectTableValues( coordinates[0], coordinates[1], values );
return buildTableData( string( units::getDescription( valueUnit )),
rowFmt,
@@ -87,7 +85,6 @@ TableData2D::TableDataHolder TableData2D::buildTableData( string_view targetUnit
string_view columnFmt ) const
{
TableData2D::TableDataHolder tableData1D;
- std::vector< size_t > rowsLength;
tableData1D.headerNames.push_back( string( targetUnit ) );
@@ -99,9 +96,9 @@ TableData2D::TableDataHolder TableData2D::buildTableData( string_view targetUnit
// insert row value and row cell values
for( auto const & [rowValue, rowMap] : m_data )
{
- std::vector< string > currentRowValues;
+ std::vector< TableData::CellData > currentRowValues;
currentRowValues.reserve( rowMap.size() );
- currentRowValues.push_back( GEOS_FMT( rowFmt, rowValue ) );
+ currentRowValues.push_back( {CellType::Value, GEOS_FMT( rowFmt, rowValue )} );
std::set< real64 >::const_iterator columnIt = m_columnValues.begin();
for( auto const & [columnValue, cellValue] : rowMap )
@@ -109,13 +106,12 @@ TableData2D::TableDataHolder TableData2D::buildTableData( string_view targetUnit
// if a column value(s) is/are missing, insert empty entry(ies)
while( columnValue > *( columnIt++ ) && columnIt != m_columnValues.end() )
{
- currentRowValues.push_back( "" );
+ currentRowValues.push_back( {CellType::Value, ""} );
}
- currentRowValues.push_back( GEOS_FMT( "{}", cellValue ) );
+ currentRowValues.push_back( {CellType::Value, GEOS_FMT( "{}", cellValue )} );
}
- tableData1D.tableData.addRow( std::move( currentRowValues ) );
- rowsLength.push_back( currentRowValues.size() );
+ tableData1D.tableData.addRow( currentRowValues );
}
return tableData1D;
diff --git a/src/coreComponents/common/format/table/TableData.hpp b/src/coreComponents/common/format/table/TableData.hpp
index 0842c3a4fbe..04d524c5f6e 100644
--- a/src/coreComponents/common/format/table/TableData.hpp
+++ b/src/coreComponents/common/format/table/TableData.hpp
@@ -23,6 +23,7 @@
#include "common/Units.hpp"
#include "common/DataTypes.hpp"
#include "common/format/Format.hpp"
+#include "TableTypes.hpp"
namespace geos
{
@@ -33,10 +34,22 @@ namespace geos
class TableData
{
public:
+
+ /**
+ * @brief Representing a data in TableData
+ */
+ struct CellData
+ {
+ /// The cell type
+ CellType type;
+ /// The cell value
+ string value = "";
+ };
+
/**
* @brief Add a row to the table.
* The values passed to addRow (can be any type).
- * @param args Cell values to be added to the row.
+ * @param args CellData values to be added to the row.
*/
template< typename ... Args >
void addRow( Args const & ... args );
@@ -45,7 +58,13 @@ class TableData
* @brief Add a row to the table
* @param row A vector of string representing a row
*/
- void addRow( std::vector< string > const & row );
+ void addRow( std::vector< CellData > const & row );
+
+ /**
+ * @brief Add a line separator to the table
+ * You must have filled values in TableData before using it
+ */
+ void addSeparator();
/**
* @brief Reset data in the table
@@ -55,7 +74,7 @@ class TableData
/**
* @return The rows of the table
*/
- std::vector< std::vector< string > > const & getTableDataRows() const;
+ std::vector< std::vector< CellData > > const & getTableDataRows() const;
/**
* @brief Get all error messages
@@ -66,10 +85,7 @@ class TableData
private:
/// vector containing all rows with cell values
- std::vector< std::vector< string > > m_rows;
-
- /// store error if there are any inconsistencies related to the table
- std::vector< string > m_errorsMsg;
+ std::vector< std::vector< CellData > > m_rows;
};
@@ -98,7 +114,7 @@ class TableData2D
/**
* @brief Add a cell to the table. If necessary, create automatically the containing column & row.
* @tparam T The value passed to addCell (can be any type).
- * @param value Cell value to be added.
+ * @param value CellData value to be added.
* @param rowValue The value of the row containing the cell.
* @param columnValue The value of the column containing the cell.
*/
@@ -149,17 +165,35 @@ class TableData2D
std::set< real64 > m_columnValues;
};
+/**
+ * @brief Trait to check is the args is a special type of cell
+ * @tparam T The type of a cell
+ */
+template< typename T >
+constexpr bool isCellType = std::is_same_v< T, CellType >;
+
template< typename ... Args >
void TableData::addRow( Args const &... args )
{
- std::vector< string > m_cellsValue;
+ std::vector< CellData > cells;
( [&] {
- static_assert( has_formatter_v< decltype(args) >, "Argument passed in addRow cannot be converted to string" );
- string const cellValue = GEOS_FMT( "{}", args );
- m_cellsValue.push_back( cellValue );
+ static_assert( has_formatter_v< decltype(args) > || isCellType< std::decay_t< decltype(args) > >, "Argument passed in addRow cannot be converted to string nor a CellType" );
+ if constexpr (std::is_same_v< Args, CellType >) {
+ if( args == CellType::Separator )
+ {
+ cells.push_back( {CellType::Separator} );
+ }
+ else
+ {
+ cells.push_back( {CellType::MergeNext} );
+ }
+ }
+ else
+ {
+ cells.push_back( {CellType::Value, GEOS_FMT( "{}", args )} );
+ }
} (), ...);
-
- addRow( m_cellsValue );
+ addRow( cells );
}
template< typename T >
diff --git a/src/coreComponents/common/format/table/TableFormatter.cpp b/src/coreComponents/common/format/table/TableFormatter.cpp
index 7392834e060..4305fcc8a98 100644
--- a/src/coreComponents/common/format/table/TableFormatter.cpp
+++ b/src/coreComponents/common/format/table/TableFormatter.cpp
@@ -13,6 +13,7 @@
* ------------------------------------------------------------------------------------------------------------
*/
+
/**
* @file TableFormatter.cpp
*/
@@ -20,7 +21,9 @@
#include "TableFormatter.hpp"
#include
#include "common/format/StringUtilities.hpp"
+#include "common/logger/Logger.hpp"
#include "TableFormatter.hpp"
+
namespace geos
{
@@ -38,34 +41,78 @@ TableCSVFormatter::TableCSVFormatter( TableLayout const & tableLayout ):
m_tableLayout = tableLayout;
}
+static constexpr string_view separator = ",";
string TableCSVFormatter::headerToString() const
{
- std::stringstream oss;
- static constexpr string_view separator = ",";
+ string result;
+
+ size_t total_size = 0;
+ for( const auto & column : m_tableLayout.getColumns())
+ {
+ for( const auto & str : column.m_header.m_lines )
+ {
+ total_size += str.size();
+ }
+ total_size += separator.size();
+ }
+ result.reserve( total_size );
for( std::size_t idxColumn = 0; idxColumn < m_tableLayout.getColumns().size(); ++idxColumn )
{
- oss << m_tableLayout.getColumns()[idxColumn].m_parameter.columnName;
+ std::ostringstream strValue;
+ for( auto const & str : m_tableLayout.getColumns()[idxColumn].m_header.m_lines )
+ {
+ result.append( str );
+ }
+
if( idxColumn < m_tableLayout.getColumns().size() - 1 )
{
- oss << separator;
+ result.append( separator );
}
}
- oss << "\n";
- return oss.str();
+ result.append( "\n" );
+ return result;
}
string TableCSVFormatter::dataToString( TableData const & tableData ) const
{
- std::vector< std::vector< string > > const rowsValues = tableData.getTableDataRows();
- std::ostringstream oss;
+ RowsCellInput const rowsValues( tableData.getTableDataRows() );
+ string result;
+ size_t total_size = 0;
for( const auto & row : rowsValues )
{
- oss << stringutilities::join( row.cbegin(), row.cend(), "," ) << "\n";
+ for( const auto & item : row )
+ {
+ total_size += item.value.size();
+ }
+ total_size += row.size();
}
- return oss.str();
+ result.reserve( total_size );
+
+ for( const auto & row : rowsValues )
+ {
+ std::vector< string > rowConverted;
+ for( const auto & item : row )
+ {
+ std::istringstream strStream( item.value );
+ string line;
+ bool detectNewLine = false;
+ while( getline( strStream, line, '\n' ))
+ {
+ rowConverted.push_back( line );
+ detectNewLine = true;
+ }
+
+ if( !detectNewLine )
+ rowConverted.push_back( item.value );
+ }
+ result.append( stringutilities::join( rowConverted.cbegin(), rowConverted.cend(), separator ));
+ result.append( "\n" );
+ }
+
+ return result;
}
template<>
@@ -79,15 +126,15 @@ string TableCSVFormatter::toString< TableData >( TableData const & tableData ) c
///////////////////////////////////////////////////////////////////////
/**
- * @brief Build cell given an alignment, a value and spaces
- * @param alignment The aligment of cell value
+ * @brief Build cell given an m_alignment, a value and spaces
+ * @param m_alignment The aligment of cell value
* @param value The cell value
* @param spaces The number of spaces in the cell
* @return A formated cell
*/
-string buildCell( TableLayout::Alignment const alignment, string_view value, integer const spaces )
+string buildCell( TableLayout::Alignment const m_alignment, string_view value, size_t const spaces )
{
- switch( alignment )
+ switch( m_alignment )
{
case TableLayout::right: return GEOS_FMT( "{:>{}}", value, spaces );
case TableLayout::left: return GEOS_FMT( "{:<{}}", value, spaces );
@@ -96,315 +143,549 @@ string buildCell( TableLayout::Alignment const alignment, string_view value, int
}
}
-/**
- * @brief Detect columns who are not displayed from TableLayout and therefore modify columns / tableDataRows vectors
- * @param columns Vector built in TableLayout containing all columns with their parameters
- * @param tableDataRows Vector built in TableData containing all rows values
- */
-void formatColumnsFromLayout( std::vector< TableLayout::Column > & columns,
- std::vector< std::vector< string > > & tableDataRows )
-{
- integer idxColumn = 0;
- for( auto iterColumn = columns.begin(); iterColumn!=columns.end(); )
- {
- if( !iterColumn->m_parameter.enabled )
- {
- iterColumn = columns.erase( iterColumn );
- for( auto & row : tableDataRows )
- {
- row.erase( row.begin() + idxColumn );
- }
- }
- else
- {
- ++iterColumn;
- ++idxColumn;
- }
- }
-}
-
TableTextFormatter::TableTextFormatter( TableLayout const & tableLayout ):
TableFormatter( tableLayout )
{}
-void TableTextFormatter::fillTableColumnsFromRows( std::vector< TableLayout::Column > & columns,
- std::vector< std::vector< string > > & rows ) const
+string TableTextFormatter::toString() const
{
- for( size_t idxRow = 0; idxRow < rows.size(); idxRow++ )
- {
- if( rows[idxRow].size() < columns.size() )
- {
- rows[idxRow].resize( columns.size(), " " );
- }
-
- for( size_t idxColumn = 0; idxColumn < columns.size(); idxColumn++ )
- {
- if( m_tableLayout.getColumns()[idxColumn].m_parameter.enabled )
- {
- columns[idxColumn].m_columnValues.push_back( rows[idxRow][idxColumn] );
- }
- }
- }
+ TableData tableData;
+ return toString( tableData );
}
-string TableTextFormatter::layoutToString() const
+template<>
+string TableTextFormatter::toString< TableData >( TableData const & tableData ) const
{
std::ostringstream tableOutput;
- string sectionSeparatingLine;
- std::vector< TableLayout::Column > columns = m_tableLayout.getColumns();
-
- outputLayout( tableOutput, columns, {}, sectionSeparatingLine );
+ CellLayoutRows cellsHeaderLayout;
+ CellLayoutRows cellsDataLayout;
+ string separatorLine;
+
+ TableLayout tableLayout = m_tableLayout;
+ size_t nbEnabledColumn = 0;
+
+ initalizeTableLayout( tableLayout, tableData,
+ cellsHeaderLayout, cellsDataLayout,
+ separatorLine,
+ nbEnabledColumn );
+ outputTable( tableLayout, tableOutput,
+ cellsHeaderLayout, cellsDataLayout,
+ separatorLine,
+ nbEnabledColumn );
return tableOutput.str();
}
-template<>
-string TableTextFormatter::toString< TableData >( TableData const & tableData ) const
+void TableTextFormatter::initalizeTableLayout( TableLayout & tableLayout,
+ TableData const & tableData,
+ CellLayoutRows & cellsHeaderLayout,
+ CellLayoutRows & cellsDataLayout,
+ string & separatorLine,
+ size_t & nbEnabledColumn ) const
{
- std::ostringstream tableOutput;
- string sectionSeparatingLine;
- std::vector< TableLayout::Column > columns = m_tableLayout.getColumns();
- std::vector< std::vector< string > > tableDataRows = tableData.getTableDataRows();
- std::vector< string > const & msgTableError = tableData.getErrorMsgs();
- integer const nbValuesRows = tableDataRows.size();
+ setLinks( tableLayout.getColumns() );
- formatColumnsFromLayout( columns, tableDataRows );
- fillTableColumnsFromRows( columns, tableDataRows );
+ populateHeaderCellsLayout( tableLayout, cellsHeaderLayout );
- outputLayout( tableOutput, columns, msgTableError, sectionSeparatingLine );
- outputSectionRows( columns, sectionSeparatingLine, tableOutput, nbValuesRows, TableLayout::Section::values );
- tableOutput << '\n';
+ RowsCellInput inputDataValues( tableData.getTableDataRows());
+ if( inputDataValues.size() > 0 )
+ {
+ populateDataCellsLayout( tableLayout, cellsDataLayout, inputDataValues );
+ }
- return tableOutput.str();
+ updateColumnMaxLength( tableLayout, cellsHeaderLayout, cellsDataLayout );
+
+ adjustTableWidth( tableLayout, cellsHeaderLayout, cellsDataLayout, separatorLine, nbEnabledColumn );
}
-void TableTextFormatter::outputLayout( std::ostringstream & tableOutput,
- std::vector< TableLayout::Column > & columns,
- std::vector< string > const & msgTableError,
- string & sectionSeparatingLine ) const
+void TableTextFormatter::outputTable( TableLayout & tableLayout,
+ std::ostringstream & tableOutput,
+ CellLayoutRows const & cellsHeader,
+ CellLayoutRows const & cellsData,
+ string_view separatorLine,
+ size_t & nbEnabledColumn ) const
{
- string topSeparator;
- size_t nbHeaderRows = 0;
- std::vector< std::vector< string > > splitHeaders;
- string const tableTitle = string( m_tableLayout.getTitle());
-
- splitAndSetColumnNames( columns, nbHeaderRows, splitHeaders );
- findAndSetMaxStringSize( columns );
+ if( tableLayout.isLineBreakEnabled())
+ {
+ tableOutput << '\n';
+ }
+ outputTitleRow( tableLayout, tableOutput, separatorLine );
+ tableOutput << GEOS_FMT( "{}\n", separatorLine );
+ outputLines( tableLayout, cellsHeader, tableOutput, tableLayout.getSublineInHeaderCounts(),
+ CellType::Header, separatorLine, nbEnabledColumn );
+ outputLines( tableLayout, cellsData, tableOutput, tableLayout.getNbSubDataLines(),
+ CellType::Value, separatorLine, nbEnabledColumn );
+ if( tableLayout.isLineBreakEnabled())
+ {
+ tableOutput << '\n';
+ }
+}
- computeTableWidth( columns, msgTableError );
- buildTableSeparators( columns, topSeparator, sectionSeparatingLine );
+void TableTextFormatter::setLinks( std::vector< TableLayout::Column > & columns ) const
+{
+ for( size_t idxColumn = 0; idxColumn < columns.size(); ++idxColumn )
+ {
+ if( idxColumn < columns.size() - 1 )
+ {
+ columns[idxColumn].setNextCell( &columns[idxColumn + 1] );
+ }
- tableOutput << '\n';
- outputTopRows( tableOutput, {tableTitle}, topSeparator, TableLayout::Alignment::center );
- outputTopRows( tableOutput, msgTableError, topSeparator, TableLayout::Alignment::left );
- tableOutput << GEOS_FMT( "{}\n", sectionSeparatingLine );
+ if( !columns[idxColumn].m_subColumn.empty())
+ {
+ for( auto & subCol : columns[idxColumn].m_subColumn )
+ {
+ subCol.setParent( &columns[idxColumn] );
+ }
- outputSectionRows( columns, sectionSeparatingLine, tableOutput, nbHeaderRows, TableLayout::Section::header );
+ setLinks( columns[idxColumn].m_subColumn );
+ }
+ }
}
-void TableTextFormatter::splitAndSetColumnNames( std::vector< TableLayout::Column > & columns,
- size_t & nbHeaderRows,
- std::vector< std::vector< string > > & splitHeaders ) const
+void TableTextFormatter::populateHeaderCellsLayout( TableLayout & tableLayout,
+ CellLayoutRows & cellsHeaderLayout ) const
{
+ cellsHeaderLayout.resize( tableLayout.getMaxDepth() );
+ size_t const headerLayersCount = tableLayout.getMaxDepth();
+ std::vector< size_t > & sublineHeaderCounts = tableLayout.getSublineInHeaderCounts();
+ sublineHeaderCounts.resize( headerLayersCount, 1 );
- splitHeaders.reserve( columns.size() );
- for( auto const & column : columns )
+ for( auto it = tableLayout.beginDeepFirst(); it != tableLayout.endDeepFirst(); ++it )
{
- std::vector< string > splitHeaderParts;
- std::istringstream ss( column.m_parameter.columnName );
- string subColumnNames;
+ size_t const currentLayer = it.getCurrentLayer();
+ TableLayout::CellLayout currentCell = it->m_header;
- while( getline( ss, subColumnNames, '\n' ))
+ if( !it->hasChild() && headerLayersCount - 1 != currentLayer )
{
- splitHeaderParts.push_back( subColumnNames );
+ for( size_t idxRow = currentLayer; idxRow < headerLayersCount - 1; idxRow++ )
+ {
+ TableLayout::CellLayout emptyCell{CellType::Header, "", TableLayout::Alignment::center};
+ emptyCell.m_cellWidth = it->m_header.m_cellWidth;
+ cellsHeaderLayout[idxRow + 1].push_back( emptyCell );
+ }
}
+ currentCell.m_cellWidth = it->m_header.m_cellWidth;
- splitHeaders.push_back( std::move( splitHeaderParts ) );
- }
+ if( it->hasParent() )
+ {
+ if( it->getNumberCellMerge() == 0 )
+ {
+ it->getParent()->incrementMergeHeaderCount( 1 );
+ }
+ else
+ {
+ it->getParent()->incrementMergeHeaderCount( it->getNumberCellMerge() );
+ }
+ }
- nbHeaderRows = std::max_element( splitHeaders.begin(), splitHeaders.end(),
- []( auto const & v1, auto const & v2 ) { return v1.size() < v2.size(); } )->size();
+ if( it->getNumberCellMerge() > 1 )
+ {
+ it->decrementMergeHeaderCount();
+ }
- for( auto & headerParts : splitHeaders )
- {
- if( headerParts.size() < nbHeaderRows )
+ sublineHeaderCounts[currentLayer] = std::max( sublineHeaderCounts[currentLayer],
+ currentCell.m_lines.size() );
+
+ for( size_t idxColumn = 0; idxColumn < it->getNumberCellMerge(); idxColumn++ )
{
- headerParts.resize( nbHeaderRows, " " );
+ TableLayout::CellLayout mergingCell{ CellType::MergeNext, "", TableLayout::Alignment::center };
+ cellsHeaderLayout[currentLayer].push_back( mergingCell );
}
- columns[&headerParts - &splitHeaders[0]].m_parameter.splitColumnNameLines = headerParts;
- }
-}
+ cellsHeaderLayout[currentLayer].push_back( currentCell );
+ }
-void TableTextFormatter::findAndSetMaxStringSize( std::vector< TableLayout::Column > & columns ) const
-{
- for( auto & column : columns )
+ size_t idxLayer = 0;
+ for( auto & lines: cellsHeaderLayout )
{
- auto const maxStringSizeHeader = *std::max_element( column.m_parameter.splitColumnNameLines.begin(),
- column.m_parameter.splitColumnNameLines.end(),
- []( const auto & a, const auto & b ) {return a.size() < b.size();} );
- column.m_maxStringSize = maxStringSizeHeader;
+ size_t const nbLinesInLayer = sublineHeaderCounts[idxLayer];
- for( auto const & cell : column.m_columnValues )
+ if( nbLinesInLayer != 1 )
{
- if( column.m_maxStringSize.length() < cell.length())
+ for( auto & cell : lines )
{
- column.m_maxStringSize = cell;
+ cell.m_lines.resize( nbLinesInLayer, "" );
}
}
+ idxLayer++;
}
}
-void TableTextFormatter::increaseColumnsSize( std::vector< TableLayout::Column > & columns,
- integer const extraCharacters ) const
+void TableTextFormatter::populateDataCellsLayout( TableLayout & tableLayout,
+ CellLayoutRows & cellsDataLayout,
+ RowsCellInput & inputDataValues ) const
{
- integer const extraCharactersPerColumn = std::ceil( extraCharacters / columns.size() );
- for( std::size_t idxColumn = 0; idxColumn < columns.size(); ++idxColumn )
+ cellsDataLayout = {
+ inputDataValues.size(),
+ std::vector< TableLayout::CellLayout >( inputDataValues[0].size(), TableLayout::CellLayout())
+ };
+
+ std::vector< size_t > & subDataLineCounts = tableLayout.getNbSubDataLines();
+ for( size_t idxRow = 0; idxRow < inputDataValues.size(); ++idxRow )
{
- integer newMaxStringSize = extraCharactersPerColumn + columns[idxColumn].m_maxStringSize.size();
- if( idxColumn == columns.size() - 1 )
+ size_t maxLinesPerRow = 0;
+ size_t idxColumn = 0;
+ for( auto it = tableLayout.beginDeepFirst(); it != tableLayout.endDeepFirst(); ++it )
{
- newMaxStringSize += m_tableLayout.getColumnMargin();
+ if( !it->hasChild())
+ {
+ TableData::CellData & cell = inputDataValues[idxRow][idxColumn];
+ TableLayout::ColumnAlignement const cellAlignement = it->m_alignment;
+ TableLayout::Alignment const alignement = cell.type == CellType::Header ?
+ cellAlignement.headerAlignment :
+ cellAlignement.valueAlignment;
+
+ if( it->m_header.m_cellType == CellType::Hidden )
+ {
+ cell.type = it->m_header.m_cellType;
+ }
+ if( it->m_header.m_cellType == CellType::Separator )
+ {
+ cell.value = m_horizontalLine;
+ }
+
+ cellsDataLayout[idxRow][idxColumn] = TableLayout::CellLayout( cell.type, cell.value, alignement );
+ maxLinesPerRow = std::max( maxLinesPerRow, cellsDataLayout[idxRow][idxColumn].m_lines.size() );
+ idxColumn++;
+ }
}
+ subDataLineCounts.push_back( { maxLinesPerRow } );
+ }
- columns[idxColumn].m_maxStringSize = GEOS_FMT( "{:>{}}",
- columns[idxColumn].m_maxStringSize,
- newMaxStringSize );
+ size_t idxLayer = 0;
+ for( auto & lines: cellsDataLayout )
+ {
+ size_t nbLinesInLayer = subDataLineCounts[idxLayer];
+ if( nbLinesInLayer != 1 )
+ {
+ for( auto & cell : lines )
+ {
+ cell.m_lines.resize( nbLinesInLayer, "" );
+ }
+ }
+ idxLayer++;
}
}
-void computeTableErrorLength( std::vector< string > const & msgTableError, string::size_type & msgTableErrorLength )
+void TableTextFormatter::updateColumnMaxLength( TableLayout & tableLayout,
+ CellLayoutRows & cellsHeaderLayout,
+ CellLayoutRows & cellsDataLayout ) const
{
- if( !msgTableError.empty() )
+ auto getMaxLineLength = []( std::vector< std::string > const & lines ) -> size_t
{
- auto maxStringSize = *(std::max_element( msgTableError.begin(), msgTableError.end(),
- []( const auto & a, const auto & b ) {
- return a.size() < b.size();
- } ));
+ auto maxLineLength = std::max_element( lines.begin(), lines.end(),
+ []( std::string const & a, std::string const & b ) {
+ return a.length() < b.length();
+ } );
+ return (maxLineLength != lines.end()) ? maxLineLength->length() : 0;
+ };
+
+ auto updateCellMaxLength = [&tableLayout]( TableLayout::CellLayout & cell, size_t maxColumnSize,
+ TableLayout::CellLayout * previousCell = nullptr )
+ {
+ if( previousCell && previousCell->m_cellType == CellType::MergeNext )
+ {
+ size_t const previousCellMaxLength = previousCell->m_cellWidth;
+ size_t const additionalMargin = tableLayout.getColumnMargin();
+ cell.m_cellWidth = maxColumnSize + previousCellMaxLength + additionalMargin;
+ previousCell->m_cellWidth = 0;
+ }
+ else
+ {
+ cell.m_cellWidth = maxColumnSize;
+ }
+ };
- msgTableErrorLength += maxStringSize.size() + 1; // max string size + line return at the end
- }
-}
+ size_t const numColumns = cellsHeaderLayout[0].size();
+ //each idx per row
+ std::vector< size_t > accMaxStringColumn( cellsDataLayout.size(), 0 );
+ for( size_t idxColumn = 0; idxColumn < numColumns; ++idxColumn )
+ {
+ size_t maxColumnSize = 1;
-void computeTableSectionLength( std::vector< TableLayout::Column > & columns, string::size_type & sectionlineLength )
-{
- sectionlineLength += std::accumulate( columns.begin(), columns.end(), 0,
- []( auto sum, const auto & column )
- { return sum + column.m_maxStringSize.length();} );
-}
+ // init header column max length
+ for( size_t rowIdx = 0; rowIdx < cellsDataLayout.size(); ++rowIdx )
+ {
+ size_t const cellDataLength = getMaxLineLength( cellsDataLayout[rowIdx][idxColumn].m_lines );
+ if( idxColumn == 0 ||
+ (idxColumn > 0 && cellsDataLayout[rowIdx][idxColumn - 1].m_cellType != CellType::MergeNext))
+ {
+ maxColumnSize = std::max( maxColumnSize, cellDataLength );
+ }
+ }
-void TableTextFormatter::computeTableWidth( std::vector< TableLayout::Column > & columns,
- std::vector< string > const & msgTableError ) const
-{
- integer const columnMargin = m_tableLayout.getColumnMargin();
- integer const borderMargin = m_tableLayout.getBorderMargin();
- string const tableTitle = string( m_tableLayout.getTitle() );
+ for( size_t rowIdx = 0; rowIdx < cellsHeaderLayout.size(); ++rowIdx )
+ {
+ size_t const cellHeaderLength = getMaxLineLength( cellsHeaderLayout[rowIdx][idxColumn].m_lines );
+ maxColumnSize = std::max( {maxColumnSize, cellHeaderLength} );
+ cellsHeaderLayout[rowIdx][idxColumn].m_cellWidth = maxColumnSize;
+ }
- string::size_type sectionLengthWithSpacing = ( ( columns.size() - 1 ) * columnMargin ) + (borderMargin * 2);
- string::size_type sectionlineLength = sectionLengthWithSpacing;
- string::size_type maxTopLineLength = tableTitle.length();
- string::size_type msgTableErrorLength = borderMargin;
+ // update maxColumnSize for data cell
+ for( size_t rowIdx = 0; rowIdx < cellsDataLayout.size(); ++rowIdx )
+ {
+ TableLayout::CellLayout & dataCell = cellsDataLayout[rowIdx][idxColumn];
+ TableLayout::CellLayout * previousDataCell = (idxColumn > 0) ?
+ &cellsDataLayout[rowIdx][idxColumn - 1] :
+ nullptr;
- computeTableErrorLength( msgTableError, msgTableErrorLength );
- computeTableSectionLength( columns, sectionlineLength );
+ if( dataCell.m_cellType == CellType::MergeNext )
+ {
+ accMaxStringColumn[rowIdx] += cellsHeaderLayout[0][idxColumn].m_cellWidth + tableLayout.getColumnMargin();
+ }
- maxTopLineLength = std::max( maxTopLineLength, msgTableErrorLength );
- if( sectionlineLength < maxTopLineLength )
- {
- integer const extraCharacters = maxTopLineLength - sectionlineLength;
- increaseColumnsSize( columns, extraCharacters );
+ if( idxColumn > 0 &&
+ previousDataCell->m_cellType == CellType::MergeNext && dataCell.m_cellType != CellType::MergeNext )
+ {
+ // root header cells know the maximum string size in the column
+ size_t const sumOfMergingCell = accMaxStringColumn[rowIdx] + cellsHeaderLayout[0][idxColumn].m_cellWidth;
+ if( sumOfMergingCell < dataCell.m_cellWidth )
+ {
+ maxColumnSize -= dataCell.m_cellWidth - sumOfMergingCell;
+ for( size_t rowIdx2 = 0; rowIdx2 < rowIdx; rowIdx2++ )
+ {
+ updateCellMaxLength( cellsDataLayout[rowIdx2][idxColumn], maxColumnSize );
+ if( cellsDataLayout[rowIdx2][idxColumn].m_cellType == CellType::Separator )
+ {
+ size_t const additionnalMargin = (idxColumn == numColumns - 1) ?
+ tableLayout.getBorderMargin() * 2 + 2 :
+ tableLayout.getColumnMargin();
+ cellsDataLayout[rowIdx2][idxColumn].m_lines[0] = std::string( maxColumnSize + additionnalMargin, '-' );
+ }
+ }
+ }
+
+ accMaxStringColumn[rowIdx] = 0;
+ }
+ else
+ {
+ size_t const cellDataLength = getMaxLineLength( cellsDataLayout[rowIdx][idxColumn].m_lines );
+ maxColumnSize = std::max( {maxColumnSize, cellDataLength} );
+ }
+
+ updateCellMaxLength( dataCell, maxColumnSize, previousDataCell );
+
+ if( dataCell.m_cellType == CellType::Separator )
+ {
+ size_t separatorLength = dataCell.m_cellWidth;
+ separatorLength += (idxColumn == numColumns - 1) ?
+ tableLayout.getBorderMargin() * 2 + 2 :
+ tableLayout.getColumnMargin();
+
+ dataCell.m_lines[0] = std::string( separatorLength, '-' );
+ }
+ }
+
+ // last pass for updating cells header
+ for( size_t rowIdx = 0; rowIdx < cellsHeaderLayout.size(); ++rowIdx )
+ {
+ TableLayout::CellLayout & headerCell = cellsHeaderLayout[rowIdx][idxColumn];
+ TableLayout::CellLayout * previousHeaderCell = (idxColumn > 0) ?
+ &cellsHeaderLayout[rowIdx][idxColumn - 1]:
+ nullptr;
+
+ updateCellMaxLength( headerCell, maxColumnSize, previousHeaderCell );
+ }
}
}
-
-void TableTextFormatter::buildTableSeparators( std::vector< TableLayout::Column > const & columns,
- string & topSeparator,
- string & sectionSeparatingLine ) const
+void TableTextFormatter::adjustTableWidth( TableLayout & tableLayout,
+ CellLayoutRows & cellsHeaderLayout,
+ CellLayoutRows & cellsDataLayout,
+ string & separatorLine,
+ size_t & nbEnabledColumn ) const
{
- { // section separator line
- integer const columnMargin = m_tableLayout.getColumnMargin();
- integer const borderMargin = m_tableLayout.getBorderMargin();
+ std::string const tableTitle = std::string( tableLayout.getTitle() );
+ size_t const margins = (size_t) tableLayout.getBorderMargin() * 2;
+ size_t const horizontalBar = 2;
+
+ size_t sectionlineLength = 0;
+ size_t nbHiddenColumns = 0;
+ size_t headerColumnCount = 0;
- std::vector< string > maxStringPerColumn;
- for( auto const & column : columns )
+ for( auto const & column : cellsHeaderLayout[0] )
+ {
+ if( column.m_cellType == CellType::Hidden )
+ {
+ nbHiddenColumns++;
+ }
+ if( column.m_cellType != CellType::Hidden )
+ {
+ nbEnabledColumn++;
+ }
+ if( column.m_cellType == CellType::Value || column.m_cellType == CellType::Header )
{
- maxStringPerColumn.push_back( string( column.m_maxStringSize.length(), m_horizontalLine ) );
+ sectionlineLength += column.m_cellWidth;
+ headerColumnCount++;
}
+ }
- string const patternBetweenColumns = GEOS_FMT( "{:-^{}}", m_horizontalLine, columnMargin );
- std::string const leftBorder = GEOS_FMT( "{}{:-<{}}", m_horizontalLine, "", borderMargin );
- std::string const rightBorder = GEOS_FMT( "{}{:-<{}}", m_horizontalLine, "", borderMargin );
- std::string const columnJoin = stringutilities::join( maxStringPerColumn, patternBetweenColumns );
+ size_t const spacingBetweenColumns = headerColumnCount == 0 ? (size_t) tableLayout.getColumnMargin():
+ (headerColumnCount - 1) * (size_t) tableLayout.getColumnMargin();
- std::ostringstream oss;
- oss << leftBorder << columnJoin << rightBorder;
- sectionSeparatingLine = oss.str();
- }
+ sectionlineLength += spacingBetweenColumns + margins + horizontalBar;
- { // top line separator
- // -2 because we can have '+' to the extremity of top separator
- integer const topSeparatorLength = sectionSeparatingLine.size() - 2;
- topSeparator = GEOS_FMT( "{}{:-<{}}{}", m_horizontalLine, "", topSeparatorLength, m_horizontalLine );
+ size_t const titleRowLength = tableTitle.length() + margins + horizontalBar;
+ size_t const maxLength = std::max( {titleRowLength, sectionlineLength} );
+ if( sectionlineLength < maxLength )
+ {
+ size_t const paddingCharacters = maxLength - sectionlineLength;
+ adjustColumnWidth( cellsHeaderLayout, nbHiddenColumns, paddingCharacters );
+ adjustColumnWidth( cellsDataLayout, nbHiddenColumns, paddingCharacters );
+ sectionlineLength = maxLength;
}
+
+ separatorLine = GEOS_FMT( "{:-^{}}", m_horizontalLine, sectionlineLength );
}
-void TableTextFormatter::outputTopRows( std::ostringstream & tableOutput,
- std::vector< string > const & msg,
- string_view topSeparator,
- TableLayout::Alignment alignment ) const
+void TableTextFormatter::adjustColumnWidth( CellLayoutRows & cells,
+ size_t const nbHiddenColumns,
+ size_t const paddingCharacters ) const
{
- if( msg.size() != 0 && msg[0] != "" )
+ size_t const numRows = cells.size();
+ size_t const nbColumns = cells[0].size();
+ size_t const remainingPaddingForLastColumn = paddingCharacters % (nbColumns - nbHiddenColumns);
+ size_t const paddingPerColumn = paddingCharacters / (nbColumns - nbHiddenColumns);
+ for( size_t idxRow = 0; idxRow < numRows; ++idxRow )
{
- tableOutput << GEOS_FMT( "{}\n", topSeparator );
- for( std::string const & str : msg )
+ for( size_t idxColumn = 0; idxColumn < nbColumns; ++idxColumn )
{
- tableOutput << m_verticalLine << string( m_tableLayout.getBorderMargin(), ' ' );
- tableOutput << buildCell( alignment, str, (topSeparator.length() - 6));
- tableOutput << string( m_tableLayout.getBorderMargin(), ' ' ) << "|\n";
+ auto & currentCell = cells[idxRow][idxColumn];
+
+ if( currentCell.m_cellType != CellType::Hidden )
+ {
+ size_t nextIdxColumn = idxColumn + 1;
+ while( nextIdxColumn < nbColumns &&
+ cells[idxRow][nextIdxColumn].m_cellType == CellType::Hidden )
+ {
+ nextIdxColumn++;
+ }
+ bool isLastVisibleColumn = nextIdxColumn == nbColumns;
+
+ if( idxColumn > 0 && cells[idxRow][idxColumn - 1].m_cellType == CellType::MergeNext )
+ {
+ auto * previousCell = &cells[idxRow][idxColumn - 1];
+ currentCell.m_cellWidth += previousCell->m_cellWidth;
+ previousCell->m_cellWidth = 0;
+ }
+
+ size_t const additionalPadding = (isLastVisibleColumn || idxColumn == nbColumns - 1) ?
+ remainingPaddingForLastColumn :
+ 0;
+
+ currentCell.m_cellWidth += paddingPerColumn + additionalPadding;
+ }
}
}
+
}
-void TableTextFormatter::outputSectionRows( std::vector< TableLayout::Column > const & columns,
- string_view sectionSeparatingLine,
- std::ostringstream & tableOutput,
- integer const nbRows,
- TableLayout::Section const section ) const
+void TableTextFormatter::outputTitleRow( TableLayout & tableLayout,
+ std::ostringstream & tableOutput,
+ string_view separatorLine ) const
{
- integer const columnMargin = m_tableLayout.getColumnMargin();
- integer const borderMargin = m_tableLayout.getBorderMargin();
-
- for( integer idxRow = 0; idxRow< nbRows; ++idxRow )
+ string const tableTitle = string( tableLayout.getTitle());
+ if( !tableTitle.empty() )
{
- // Append the left border
- tableOutput << GEOS_FMT( "{:<{}}", m_verticalLine, 1 + borderMargin );
- for( std::size_t idxColumn = 0; idxColumn < columns.size(); ++idxColumn )
- {
- TableLayout::Column const currentColumn = columns[idxColumn];
- auto const & columnContent = section == TableLayout::Section::header ?
- columns[idxColumn].m_parameter.splitColumnNameLines :
- columns[idxColumn].m_columnValues;
- string cell = columnContent.at( idxRow );
- integer const cellSize = currentColumn.m_maxStringSize.length();
+ tableOutput << GEOS_FMT( "{}\n", separatorLine );
+ tableOutput << GEOS_FMT( "{:<{}}", m_verticalLine, tableLayout.getBorderMargin() + 1 );
+ tableOutput << buildCell( TableLayout::Alignment::center,
+ tableTitle,
+ separatorLine.length() - (tableLayout.getBorderMargin() * 2) - 2 );
+ tableOutput << GEOS_FMT( "{:>{}}\n", m_verticalLine, tableLayout.getBorderMargin() + 1 );
+ }
+}
- tableOutput << buildCell( currentColumn.m_parameter.alignment, cell, cellSize );
+void TableTextFormatter::formatCell( TableLayout & tableLayout,
+ std::ostringstream & tableOutput,
+ TableLayout::CellLayout const & cell,
+ size_t idxLine ) const
+{
+ GEOS_UNUSED_VAR( tableLayout );
+ tableOutput << buildCell( cell.m_alignment,
+ cell.m_lines[idxLine],
+ cell.m_cellWidth );
+}
- // Add space between column
- if( idxColumn < columns.size() - 1 )
+void TableTextFormatter::outputLines( TableLayout & tableLayout,
+ CellLayoutRows const & cellsLayout,
+ std::ostringstream & tableOutput,
+ std::vector< size_t > const & nbLinesRow,
+ CellType sectionType,
+ string_view separatorLine,
+ size_t & nbEnabledColumn ) const
+{
+ size_t idxLine = 0;
+ for( auto const & row : cellsLayout )
+ {
+ for( size_t idxSubLine = 0; idxSubLine < nbLinesRow[idxLine]; idxSubLine++ )
+ {
+ size_t idxColumn = 0;
+ size_t nbEnabledColumnTemp = nbEnabledColumn;
+ while( nbEnabledColumnTemp > 0 )
{
- tableOutput << GEOS_FMT( "{:^{}}", m_verticalLine, columnMargin );
+ auto & cell = row[idxColumn];
+ switch( cell.m_cellType )
+ {
+ case CellType::Value:
+ case CellType::Header:
+ if( &cell == &(row.front()) )
+ {
+ tableOutput << GEOS_FMT( "{:<{}}", m_verticalLine, tableLayout.getBorderMargin() + 1 );
+ }
+
+ formatCell( tableLayout, tableOutput, cell, idxSubLine );
+
+ if( &cell == &(row.back()) || nbEnabledColumnTemp == 1 )
+ {
+ tableOutput << GEOS_FMT( "{:>{}}", m_verticalLine, tableLayout.getBorderMargin() + 1 );
+ }
+ else
+ {
+ tableOutput << GEOS_FMT( "{:^{}}", m_verticalLine, tableLayout.getColumnMargin());
+ }
+ nbEnabledColumnTemp--;
+ break;
+ case CellType::MergeNext:
+ if( &cell == &(row.front()) )
+ {
+ tableOutput << GEOS_FMT( "{:<{}}", m_verticalLine, tableLayout.getBorderMargin() + 1 );
+ }
+ if( &cell == &(row.back()) )
+ {
+ formatCell( tableLayout, tableOutput, cell, idxSubLine );
+ tableOutput << GEOS_FMT( "{:>{}}", m_verticalLine, tableLayout.getBorderMargin() + 1 );
+ }
+ nbEnabledColumnTemp--;
+ break;
+ case CellType::Separator:
+ formatCell( tableLayout, tableOutput, cell, idxSubLine );
+ nbEnabledColumnTemp--;
+ break;
+ case CellType::Hidden:
+ if( &cell == &(row.back()) )
+ {
+ tableOutput << GEOS_FMT( "{:>{}}", m_verticalLine, tableLayout.getBorderMargin() + 1 );
+ }
+ default:
+ break;
+ }
+ idxColumn++;
}
+ tableOutput <{}}\n", m_verticalLine, borderMargin + 1 );
}
-
- if( nbRows != 0 )
+ if( sectionType == CellType::Value && !cellsLayout.empty())
{
- tableOutput << GEOS_FMT( "{}\n", sectionSeparatingLine );
+ tableOutput << separatorLine;
}
}
-
}
diff --git a/src/coreComponents/common/format/table/TableFormatter.hpp b/src/coreComponents/common/format/table/TableFormatter.hpp
index 26dd2b16ba4..04392b7691d 100644
--- a/src/coreComponents/common/format/table/TableFormatter.hpp
+++ b/src/coreComponents/common/format/table/TableFormatter.hpp
@@ -22,6 +22,7 @@
#include "TableData.hpp"
#include "TableLayout.hpp"
+#include "TableTypes.hpp"
namespace geos
{
@@ -32,6 +33,13 @@ namespace geos
class TableFormatter
{
+public:
+ /// Represent the TableData values
+ using RowsCellInput = std::vector< std::vector< TableData::CellData > >;
+ /// Represent the Table (header or values) structured
+ using CellLayoutRows = std::vector< std::vector< TableLayout::CellLayout > >;
+
+
protected:
/// Layout for a table
@@ -41,14 +49,9 @@ class TableFormatter
/**
* @brief Construct a new Table Formatter from a tableLayout
- * @param tableLayout Contain all column names and optionnaly the table title
+ * @param tableLayout Contain all tableColumnData names and optionnaly the table title
*/
TableFormatter( TableLayout const & tableLayout );
-
- /**
- * @brief Destroy the Table Formatter object
- */
- virtual ~TableFormatter() = default;
};
/**
@@ -67,23 +70,18 @@ class TableCSVFormatter : public TableFormatter
/**
* @brief Construct a new Table Formatter from a tableLayout
- * @param tableLayout Contain all column names and optionnaly the table title
+ * @param tableLayout Contain all tableColumnData names and optionnaly the table title
*/
TableCSVFormatter( TableLayout const & tableLayout );
/**
- * @brief Destroy the TableCSVFormatter object
- */
- virtual ~TableCSVFormatter() = default;
-
- /**
- * @return The string with all column names.
+ * @return The string with all tableColumnData names.
*/
string headerToString() const;
/**
- * @brief Convert the table data to a CSV string.
- * @param tableData The 1D table data.
+ * @brief Convert the table data to a CSV string..
+ * @param tableData The table data
* @return The CSV string representation of the table data.
*/
string dataToString( TableData const & tableData ) const;
@@ -115,7 +113,6 @@ class TableTextFormatter : public TableFormatter
{
public:
-
/**
* @brief Construct a new TableFormatter
*/
@@ -125,20 +122,15 @@ class TableTextFormatter : public TableFormatter
/**
* @brief Construct a new TableFormatter from a tableLayout
- * @param tableLayout Contain all column names and optionnaly the table title
+ * @param tableLayout Contain all tableColumnData names and optionnaly the table title
*/
TableTextFormatter( TableLayout const & tableLayout );
-
- /**
- * @brief Destroy the Table Text Formatter object
- */
- virtual ~TableTextFormatter() = default;
-
/**
- * @return A TableLayout converted into a formatted representation.
+ * @return A TableLayout string representation,
+ * The TableTextFormatter receives hasn't receive any data, so only the header part is returned.
*/
- string layoutToString() const;
+ string toString() const;
/**
* @brief Convert a data source to a table string.
@@ -152,99 +144,139 @@ class TableTextFormatter : public TableFormatter
/// symbol for separator construction
static constexpr char m_verticalLine = '|';
- /// for the extremity of a row
+ /// for the extremity of a row
static constexpr char m_horizontalLine = '-';
- /**
- * @brief Fill the vector (m_column) in tableData with values from rows stored in tableData.
- * @param columns Vector of columns to be filled.
- * @param tableData Vector containing all rows filled with values
- */
- void fillTableColumnsFromRows( std::vector< TableLayout::Column > & columns,
- std::vector< std::vector< string > > & tableData ) const;
+
+/**
+ * @brief Initializes the table layout with the given table data and prepares necessary layouts for headers and data cells.
+ * @param tableLayout A reference to the `TableLayout` object.
+ * @param tableData A constant reference to the `TableData` object, which contains the actual data for the table.
+ * @param cellsHeaderLayout A reference to a `CellLayoutRows` where the header cells will be populated.
+ * @param cellsDataLayout A reference to a `CellLayoutRows` where the data cells will be populated.
+ * @param separatorLine A string that will be used as the table separator line
+ */
+ void initalizeTableLayout( TableLayout & tableLayout,
+ TableData const & tableData,
+ CellLayoutRows & cellsDataLayout,
+ CellLayoutRows & cellsHeaderLayout,
+ string & separatorLine,
+ size_t & nbEnabledColumn ) const;
+/**
+ * @brief Outputs the formatted table to the provided output stream.
+ * @param tableLayout The layout of the table
+ * @param tableOutput A reference to an `std::ostringstream` where the formatted table will be written.
+ * @param cellsHeader The layout of the header rows
+ * @param cellsData The layout of the data rows
+ * @param separatorLine The string to be used as the table separator line
+ */
+ void outputTable( TableLayout & tableLayout,
+ std::ostringstream & tableOutput,
+ CellLayoutRows const & cellsHeader,
+ CellLayoutRows const & cellsData,
+ string_view separatorLine,
+ size_t & nbEnabledColumn ) const;
/**
- * @brief Converts a TableLayout into a formatted representation.
- * @param tableOutput The output stream
- * @param columns The vector containing all table columns
- * @param msgTableError A vector containg all error related to the table
- * @param sectionSeparatingLine An empty string for building the section separator
+ * @brief Sets parent-child relationships between columns and sub-columns.
+ * @param columns A reference to a vector of `TableLayout::Column` objects.
*/
- void outputLayout( std::ostringstream & tableOutput,
- std::vector< TableLayout::Column > & columns,
- std::vector< string > const & msgTableError,
- string & sectionSeparatingLine ) const;
+ void setLinks( std::vector< TableLayout::Column > & columns ) const;
/**
- * @brief Split all header names by detecting the newline \\n character. and
- * set the same vector size for each split header and merge it into columns
- * @param columns The vector containg all columns
- * @param largestHeaderVectorSize The largest split header vector size
- * @param splitHeaders A empty vector who will contain all split header names
+ * @brief Adjusts the header layout by ensuring all header layers have consistent row sizes and formats.
+ * @param tableLayout The layout of the table, containing information about columns, headers, and their layers.
+ * @param cellsHeaderLayout A reference to the collection of header cells that will be updated with the gridified layout.
*/
- void splitAndSetColumnNames( std::vector< TableLayout::Column > & columns,
- size_t & largestHeaderVectorSize,
- std::vector< std::vector< string > > & splitHeaders ) const;
+ void populateHeaderCellsLayout( TableLayout & tableLayout,
+ CellLayoutRows & cellsDataLayout ) const;
+
+/**
+ * @brief Populates the data cells layout based on input data values.
+ * @param tableLayout The layout of the table,
+ * @param cellsDataLayout A reference to the layout for the data cells that will be populated.
+ * @param inputDataValues A 2D vector containing the actual input data values.
+ */
+ void populateDataCellsLayout( TableLayout & tableLayout,
+ CellLayoutRows & cellsDataLayout,
+ RowsCellInput & inputDataValues ) const;
/**
- * @brief For each column find and set the column's longest string
- * @param columns The vector containg all columns
+ * @brief Finds and sets the longest string for each column in the table.
+ * @param tableLayout The layout of the table,
+ * @param cellHeaderLength A reference to the collection of data cells.
+ * The function updates the maximum string
+ * length for each cell based on the longest string found in the column.
+ * @param cellsDataLayout A reference to the collection of data cells.
+ * The function updates the maximum string
+ * length for each cell based on the longest string found in the column.
*/
- void findAndSetMaxStringSize( std::vector< TableLayout::Column > & columns ) const;
+ void updateColumnMaxLength( TableLayout & tableLayout,
+ CellLayoutRows & cellHeaderLength,
+ CellLayoutRows & cellsDataLayout ) const;
/**
- * @brief recalculate the largest string size for each columns
- * @param columns Vector containing all table columns
- * @param extraCharacters Extra characters to be added to \p m_maxStringSize of each columns
+ * @brief Computes and constructs the separator lines for the table.
+ * Adjust columns if the title is the largest row
+ * @param tableLayout The layout of the table,
+ * @param cellsHeaderLayout A reference to the collection of header cells that can be affected by column resizing.
+ * @param cellsDataLayout A reference to the collection of data cells that can be affected by column resizing.
+ * @param separatorLine A string reference where the table separator line will be created
*/
- void increaseColumnsSize( std::vector< TableLayout::Column > & columns,
- integer const extraCharacters ) const;
+ void adjustTableWidth( TableLayout & tableLayout,
+ CellLayoutRows & cellsHeaderLayout,
+ CellLayoutRows & cellsDataLayout,
+ string & separatorLine,
+ size_t & nbEnabledColumn ) const;
/**
- * @brief Compute the max table line length, taking into account the length of : title, error, columns header and content
- * Increase the size of the columns if necessary
- * @param columns Vector of column containing containing the largest string for each column
- * @param msgTableError Vector containing all error messages
+ * @brief Increases the size of columns to accommodate extra characters.
+ * @param cells A reference to the collection of data/header cells
+ * @param nbHiddenColumns The total number of hidden columns in the table.
+ * @param extraCharacters The total number of extra characters to be distributed across the columns.
*/
- void computeTableWidth( std::vector< TableLayout::Column > & columns,
- std::vector< string > const & msgTableError ) const;
+ void adjustColumnWidth( CellLayoutRows & cells,
+ size_t nbHiddenColumns,
+ size_t const paddingCharacters ) const;
/**
- * @brief Build all separators needed from content length contained in the columns vector
- * @param columns Vector containing all table columns
- * @param topSeparator Top separator to be built
- * @param sectionSeparatingLine Line section separator to be built
+ * @brief Output the title row in the table
+ * @param tableLayout The layout of the table
+ * @param tableOutput The output stream
+ * @param separatorLine The table separator line string
*/
- void buildTableSeparators( std::vector< TableLayout::Column > const & columns,
- string & topSeparator,
- string & sectionSeparatingLine ) const;
+ void outputTitleRow( TableLayout & tableLayout,
+ std::ostringstream & tableOutput,
+ string_view separatorLine ) const;
/**
- * @brief Add a row on top of the table
+ * @brief Formats a table cell and appends it to the table output.
+ * @param tableLayout The layout of the table
* @param tableOutput The output stream
- * @param msg Vector of string(s) to display
- * @param topSeparator The top table separator
- * @param alignment The aligment for a row
+ * @param cell The cell to format
+ * @param idxLine The current line index used to access the specific content for the cell.
*/
- void outputTopRows( std::ostringstream & tableOutput,
- std::vector< string > const & msg,
- string_view topSeparator,
- TableLayout::Alignment alignment ) const;
+ void formatCell( TableLayout & tableLayout,
+ std::ostringstream & tableOutput,
+ TableLayout::CellLayout const & cell,
+ size_t idxLine ) const;
/**
- * @brief Output a section by specifying it's type ( header or section )
- * @param columns Vector containing all table columns
- * @param sectionSeparatingLine Line separator between sections
- * @param rows A section row
- * @param nbRows Indicates the number of lines in a section
- * @param section The section to be built
- * @note Add the ending line if there are one or more rows
+ * @brief Outputs the formatted table lines to the output stream.
+ * @param tableLayout The layout of the table
+ * @param cellsLayout A collection of rows, each containing a layout of cells to be processed and formatted.
+ * @param tableOutput The output stream
+ * @param nbLinesRow A vector containing the number of sub-lines for each row.
+ * @param sectionType The type of the section being processed (Header, Value, etc.).
+ * @param separatorLine The table separator line string
*/
- void outputSectionRows( std::vector< TableLayout::Column > const & columns,
- string_view sectionSeparatingLine,
- std::ostringstream & rows,
- integer const nbRows,
- TableLayout::Section const section ) const;
+ void outputLines( TableLayout & tableLayout,
+ CellLayoutRows const & cellsLayout,
+ std::ostringstream & tableOutput,
+ std::vector< size_t > const & nbLinesRow,
+ CellType sectionType,
+ string_view separatorLine,
+ size_t & nbEnabledColumn ) const;
};
/**
diff --git a/src/coreComponents/common/format/table/TableLayout.cpp b/src/coreComponents/common/format/table/TableLayout.cpp
index 7e6b134d606..10350ac4a6c 100644
--- a/src/coreComponents/common/format/table/TableLayout.cpp
+++ b/src/coreComponents/common/format/table/TableLayout.cpp
@@ -16,64 +16,234 @@
/**
* @file TableData.hpp
*/
-
#include "TableLayout.hpp"
+#include
namespace geos
{
-TableLayout::TableLayout( std::vector< string > const & columnNames, string const & title ):
- m_tableTitle( title )
+void TableLayout::addToColumns( std::vector< string > const & columnNames )
{
- setMargin( MarginValue::medium );
- m_columns.reserve( columnNames.size() );
- for( auto const & name : columnNames )
+ for( auto const & m_header : columnNames )
{
- m_columns.push_back( {TableLayout::ColumnParam{{name}, Alignment::right, true}, {}, ""} );
+ addToColumns( m_header );
}
}
-TableLayout::TableLayout( std::vector< ColumnParam > const & columnParameters, string const & title ):
- m_tableTitle( title )
+void TableLayout::addToColumns( string_view m_header )
{
- setMargin( MarginValue::medium );
- m_columns.reserve( columnParameters.size() );
- for( auto const & param : columnParameters )
- {
- m_columns.push_back( { param, {}, ""} );
- }
+ TableLayout::Column column = TableLayout::Column().setName( m_header );
+ m_tableColumnsData.push_back( column );
+}
+
+void TableLayout::addToColumns( TableLayout::Column const & column )
+{
+ m_tableColumnsData.push_back( column );
+}
+
+TableLayout & TableLayout::setTitle( string_view title )
+{
+ m_tableTitle = title;
+ return *this;
}
-void TableLayout::setMargin( MarginValue marginValue )
+TableLayout & TableLayout::enableLineBreak( bool value )
{
+ m_wrapLine = value;
+ return *this;
+}
+
+TableLayout & TableLayout::setMargin( MarginValue marginValue )
+{
+ m_marginValue = marginValue;
m_borderMargin = marginValue;
m_columnMargin = integer( marginValue ) * 2 + 1;
+
+ return *this;
+}
+
+bool TableLayout::isLineBreakEnabled() const
+{ return m_wrapLine; }
+
+size_t TableLayout::getMaxDepth() const
+{
+ size_t depthMax = 1;
+ size_t currDepth = 1;
+ for( auto const & column : m_tableColumnsData )
+ {
+ currDepth = 1;
+ TableLayout::Column const * currColumn = &column;
+ while( !currColumn->m_subColumn.empty())
+ {
+ currColumn = &currColumn->m_subColumn[0];
+ currDepth++;
+ }
+ depthMax = std::max( currDepth, depthMax );
+ }
+ return depthMax;
+}
+
+void divideCell( std::vector< string > & lines, string const & value )
+{
+ std::istringstream strStream( value );
+ std::string line;
+ lines.clear();
+ while( getline( strStream, line, '\n' ))
+ {
+ lines.push_back( line );
+ }
+
+ if( line.empty())
+ {
+ lines.push_back( "" );
+ }
+}
+
+TableLayout::CellLayout::CellLayout():
+ m_lines( {""} ),
+ m_cellType( CellType::Header ),
+ m_alignment( TableLayout::Alignment::center ),
+ m_cellWidth( 0 )
+{}
+
+TableLayout::CellLayout::CellLayout( CellType type, string const & cellValue, TableLayout::Alignment alignment ):
+ m_cellType( type ),
+ m_alignment( alignment )
+{
+ divideCell( m_lines, cellValue );
+ if( !m_lines.empty())
+ {
+ m_cellWidth = std::max_element( m_lines.begin(), m_lines.end(), []( const auto & a, const auto & b )
+ {
+ return a.length() < b.length();
+ } )->length();
+ }
+ else
+ {
+ m_cellWidth = 0;
+ }
+}
+
+TableLayout::Column::Column():
+ m_parent( nullptr ), m_next( nullptr )
+{
+ m_header.m_lines = {};
+ m_header.m_cellType = CellType::Header;
+ m_header.m_alignment = Alignment::center;
+}
+
+TableLayout::Column::Column( TableLayout::CellLayout cell ):
+ m_parent( nullptr ), m_next( nullptr )
+{ m_header = cell; }
+
+
+TableLayout::Column & TableLayout::Column::setName( string_view name )
+{
+ m_header.m_lines.push_back( std::string( name ) );
+ divideCell( m_header.m_lines, m_header.m_lines[0] );
+ m_header.m_cellType = CellType::Header;
+ return *this;
+}
+
+TableLayout::Column & TableLayout::Column::setVisibility( CellType celltype )
+{
+ m_header.m_cellType = celltype;
+ return *this;
+}
+
+TableLayout::Column & TableLayout::Column::addSubColumns( std::initializer_list< string > subColName )
+{
+ std::vector< TableLayout::Column > subColumns;
+ for( auto const & name : subColName )
+ {
+ TableLayout::CellLayout cell{CellType::Header, name, TableLayout::Alignment::center};
+ TableLayout::Column col{cell};
+ subColumns.emplace_back( col );
+ }
+ m_subColumn = subColumns;
+ return *this;
}
-std::vector< TableLayout::Column > const & TableLayout::getColumns() const
+TableLayout::Column & TableLayout::Column::addSubColumns( std::initializer_list< TableLayout::Column > subCol )
{
- return m_columns;
+ m_subColumn = subCol;
+ return *this;
}
-string_view TableLayout::getTitle() const
+TableLayout::Column & TableLayout::Column::addSubColumns( string const & subColName )
{
- return m_tableTitle;
+ TableLayout::CellLayout cell{CellType::Header, subColName, TableLayout::Alignment::center};
+ TableLayout::Column col{cell};
+ this->m_subColumn.push_back( col );
+ return *this;
}
+TableLayout::Column & TableLayout::Column::setHeaderAlignment( Alignment headerAlignment )
+{
+ m_alignment.headerAlignment = headerAlignment;
+ m_header.m_alignment = headerAlignment;
+ return *this;
+}
-integer const & TableLayout::getBorderMargin() const
+TableLayout::Column & TableLayout::Column::setValuesAlignment( Alignment valueAlignment )
{
- return m_borderMargin;
+ m_alignment.valueAlignment = valueAlignment;
+ return *this;
}
-integer const & TableLayout::getColumnMargin() const
+TableLayout::DeepFirstIterator & TableLayout::DeepFirstIterator::operator++()
{
- return m_columnMargin;
+ if( m_currentColumn->getNextCell() != nullptr )
+ {
+ m_currentColumn = m_currentColumn->getNextCell();
+ while( m_currentColumn->hasChild() )
+ {
+ m_currentLayer++;
+ m_currentColumn = &m_currentColumn->m_subColumn[0];
+ }
+ }
+ else
+ {
+ bool const hasParent = (m_currentColumn->getParent() != nullptr);
+ m_currentLayer -= size_t( hasParent );
+ m_currentColumn = hasParent ? m_currentColumn->getParent() : nullptr;
+ }
+ return *this;
}
-integer const & TableLayout::getMarginTitle() const
+TableLayout::DeepFirstIterator TableLayout::DeepFirstIterator::operator++( int )
{
- return m_titleMargin;
+ TableLayout::DeepFirstIterator temp = *this;
+ ++(*this);
+ return temp;
}
+TableLayout::DeepFirstIterator TableLayout::beginDeepFirst()
+{
+ TableLayout::Column * startColumn = &(*m_tableColumnsData.begin());
+ size_t idxLayer = 0;
+ if( startColumn->hasChild() )
+ {
+ while( startColumn->hasChild() )
+ {
+ idxLayer++;
+ startColumn = &startColumn->m_subColumn[0];
+ }
+ }
+ return DeepFirstIterator( startColumn, idxLayer );
+}
+
+bool TableLayout::DeepFirstIterator::isLastColumn()
+{
+ if( m_currentColumn == nullptr )
+ return true;
+ TableLayout::Column * tempColumn = m_currentColumn;
+ while( tempColumn->getParent() )
+ {
+ tempColumn = tempColumn->getParent();
+ }
+ return tempColumn->getNextCell() == nullptr;
+}
+
+
}
diff --git a/src/coreComponents/common/format/table/TableLayout.hpp b/src/coreComponents/common/format/table/TableLayout.hpp
index e6f96a878eb..ee8f6a02323 100644
--- a/src/coreComponents/common/format/table/TableLayout.hpp
+++ b/src/coreComponents/common/format/table/TableLayout.hpp
@@ -21,6 +21,10 @@
#define GEOS_COMMON_FORMAT_TABLE_TABLELAYOUT_HPP
#include "common/DataTypes.hpp"
+#include "TableTypes.hpp"
+#include
+#include "common/logger/Logger.hpp"
+
namespace geos
{
@@ -51,106 +55,510 @@ class TableLayout
enum Section { header, values };
/**
- * @brief Structure to set up each colum parameters.
+ * @brief Structure to set up values m_alignment for each colum.
*/
- struct ColumnParam
+ struct ColumnAlignement
{
- /// Name for a column
- string columnName;
- /// Alignment for a column. By default aligned to the right side
- Alignment alignment = Alignment::right;
- /// A boolean to display a colummn
- bool enabled = true;
- /// Vector containing substring column name delimited by "\n"
- std::vector< string > splitColumnNameLines;
-
- /**
- * @brief Construct a ColumnParam object with the specified name and alignment.
- * @param name The name of the column
- * @param align The alignment of the column
- */
- ColumnParam( std::string const & name, Alignment align )
- : columnName( name ), alignment( align )
- {}
+ /// Alignment for column name. By default aligned to center
+ Alignment headerAlignment = Alignment::center;
+ /// Alignment for column values. By default aligned to right side
+ Alignment valueAlignment = Alignment::right;
+ };
+
+/**
+ * @struct CellLayout
+ * @brief Structure grouping the cell information to display it in a table (content, type, alignment, ...).
+ */
+ struct CellLayout
+ {
+ /// vector containing each cell content, separated by lines.
+ std::vector< string > m_lines;
+ /// The type of the cell (Header,Value, Merge, ...).
+ CellType m_cellType;
+ /// The alignment of the cell (left, center, right).
+ Alignment m_alignment;
+ /// Maximum length of the data in the cell.
+ size_t m_cellWidth;
/**
- * @brief Construct a ColumnParam object with the specified name, alignment, and display flag.
- * @param name The name of the column
- * @param align The alignment of the column
- * @param display Flag indicating whether the column is enabled
+ * @brief Constructor to initialize a Cell with a default settings.
*/
- ColumnParam( std::string const & name, Alignment align, bool display )
- : columnName( name ), alignment( align ), enabled( display )
- {}
+ CellLayout();
+
+ /**
+ * @brief Constructor to initialize a cell given celltype, value and alignment.
+ * @param cellType The type of the cell.
+ * @param value The value to be assigned to the cell.
+ * @param alignment The alignment of the cell (left, right, or center).
+ */
+ CellLayout( CellType cellType, string const & value, TableLayout::Alignment alignment );
};
/**
- * @brief Struct for a column.
+ * @class Column
+ * @brief Class representing a column in a table layout.
*/
- struct Column
+ class Column
{
- /// Structure who contains parameters for a column
- ColumnParam m_parameter;
- /// A vector containing all column values
- std::vector< string > m_columnValues;
- /// The largest string in the column
- string m_maxStringSize;
+public:
+ /// The header cell layout.
+ CellLayout m_header;
+ /// A vector containing all sub-columns in the column.
+ std::vector< Column > m_subColumn;
+ /// struct containing m_alignment for the column (header and values)
+ ColumnAlignement m_alignment;
+
+ /**
+ * @brief Default constructor.
+ * Initializes a column with default values.
+ */
+ Column();
+
+ /**
+ * @brief Constructor to initialize a column with a specific `CellLayout`.
+ * @param cellLayout The `CellLayout` object to initialize the column.
+ *
+ */
+ Column( TableLayout::CellLayout cellLayout );
+
+ /**
+ * @brief Get the parent column.
+ * @return Pointer to the parent column, or `nullptr` if no parent is set.
+ */
+ Column * getParent()
+ { return m_parent; }
+
+ /**
+ * @brief Set the parent column.
+ * @param parent Pointer to the parent column to set.
+ */
+ void setParent( Column * parent )
+ { m_parent = parent; }
+
+ /**
+ * @brief GGet the next column in the layout.
+ * @return Pointer to the next column or `nullptr` if no next column exists.
+ */
+ Column * getNextCell()
+ { return m_next; }
+
+ /**
+ * @brief Set the next column in the layout.
+ * @param nextCell The next column in the table layout.
+ */
+ void setNextCell( Column * nextCell )
+ { m_next = nextCell; }
+
+ /**
+ * @brief Sets the name of the column.
+ * @param name The name to set for the column.
+ * @return The current column object.
+ */
+ Column & setName( string_view name );
+
+ /**
+ * @brief Set the column visibility.
+ * @param celltype Cell type to apply to hide the colmun
+ * @return The current column .
+ */
+ Column & setVisibility( CellType celltype );
+
+ /**
+ * @brief Adds multiple sub-columns to the column.
+ * @param subCol A list of sub-column names to add.
+ * @return The current column object
+ */
+ TableLayout::Column & addSubColumns( std::initializer_list< TableLayout::Column > subCol );
+
+ /**
+ * @brief Adds multiple sub-columns to the column.
+ * @param subColName A list of sub-column names to add.
+ * @return The current column object
+ */
+ TableLayout::Column & addSubColumns( std::initializer_list< string > subColName );
+
+ /**
+ * @brief Adds a single sub-column to the column.
+ * @param subColName The name of the sub-column to add.
+ * @return The current column object.
+ */
+ TableLayout::Column & addSubColumns( string const & subColName );
+
+ /**
+ * @brief Sets the header alignment for the column.
+ * @param headerAlignment The alignment to set for the column header (left, right, or center).
+ * @return The current column object
+ */
+ TableLayout::Column & setHeaderAlignment( Alignment headerAlignment );
+
+ /**
+ * @brief Sets the values alignment for the column.
+ * @param valueAlignment The alignment to set for the column values (left, right, or center).
+ * @return The current column object
+ */
+ TableLayout::Column & setValuesAlignment( Alignment valueAlignment );
+
+ /**
+ * @return number of times we will divide the current cell
+ */
+ size_t getNumberCellMerge()
+ { return m_headerMergeCount; }
+
+ /**
+ * @brief Increment number of times we will divide the current cell
+ * @param value number of division to add
+ */
+ void incrementMergeHeaderCount( size_t value )
+ { m_headerMergeCount+= value;}
+
+ /**
+ * @brief Decremente number of times we will divide the current cell
+ */
+ void decrementMergeHeaderCount()
+ { m_headerMergeCount--; }
+
+ /**
+ * @brief Checks if the column has any child columns.
+ * @return bool True if the column has child columns, otherwise false.
+ */
+ bool hasChild() const
+ { return !this->m_subColumn.empty(); }
+
+ /**
+ * @brief Checks if the column has a parent column.
+ * @return bool True if the column has a parent, otherwise false.
+ */
+ bool hasParent() const
+ { return this->m_parent != nullptr; }
+
+private:
+ /// Pointer to the parent cell (if any).
+ Column * m_parent;
+ /// Pointer to the next cell (if any).
+ Column * m_next;
+ /// The width of the cell (e.g., for cell containing subColumns).
+ size_t m_headerMergeCount = 0;
};
+ /**
+ * @brief Iterator to loop over all columns, starting by the deepest sub columns,
+ * then to their parents, then to their siblings.
+ */
+ class DeepFirstIterator
+ {
+public:
+ ///alias for column
+ using ColumnType = Column;
+
+ /**
+ * @brief Construct a new Leaf Iterator object
+ * @param columnPtr The first deepest column of vector
+ * @param idxLayer the layer associated with the column
+ */
+ DeepFirstIterator( ColumnType * columnPtr, size_t idxLayer ):
+ m_currentColumn( columnPtr ), m_currentLayer( idxLayer )
+ {}
+
+ /**
+ * @brief Copy assignment operator
+ * @param[in] columnPtr Coulmn to copy
+ * @return Leaf iterator
+ */
+ DeepFirstIterator & operator=( Column * columnPtr )
+ {
+ this->m_currentColumn= columnPtr;
+ return *this;
+ }
+
+ /**
+ * @brief Prefix ++ overload
+ * @return Leaf iterator
+ */
+ DeepFirstIterator & operator++();
+
+ /**
+ * @brief Postfix ++ overload
+ * @return Leaf iterator
+ */
+ DeepFirstIterator operator++( int );
+
+ /**
+ * @brief Dereference operator.
+ * @return Reference to the current Column object pointed to by the iterator.
+ */
+ ColumnType & operator*()
+ { return *m_currentColumn; }
+
+ /**
+ * @brief Arrow operator.
+ * @return Pointer to the current Column object.
+ */
+ ColumnType * operator->()
+ { return m_currentColumn; }
+
+ /**
+ * @brief Equality comparison operator.
+ * @param a The first iterator.
+ * @param b The second iterator.
+ * @return True if both iterators point to the same column; false otherwise.
+ */
+ friend bool operator== ( DeepFirstIterator const & a, DeepFirstIterator const & b )
+ { return a.m_currentColumn == b.m_currentColumn; };
+ /**
+ * @brief Inequality comparison operator.
+ * @param a The first iterator.
+ * @param b The second iterator.
+ * @return True if the iterators point to different columns; false otherwise.
+ */
+ friend bool operator!= ( DeepFirstIterator const & a, DeepFirstIterator const & b )
+ { return a.m_currentColumn != b.m_currentColumn; };
+
+ /**
+ * @brief Gets the current layer (depth) of the iterator.
+ * @return The current layer (depth) of the iterator.
+ */
+ size_t getCurrentLayer() const
+ { return m_currentLayer; }
+
+ /**
+ * @brief Check if the current cell belong the last column
+ * @return true
+ * @return false
+ */
+ bool isLastColumn();
+
+private:
+ /// Pointer to the current column
+ ColumnType * m_currentColumn;
+ /// The current depth of the iterator
+ size_t m_currentLayer;
+ };
+
+ /**
+ * @return Return an itarator pointing on the first leaf of the first columns vector
+ * Example on 2 column with Column A : 2 layer and Column B : 3 layers
+ * A.A -> A-B -> A-C -> A -> B-A-A -> B-A-B -> B-A -> B-B-A -> B-B-B -> B-B -> B
+ */
+ DeepFirstIterator beginDeepFirst();
+
+ /**
+ * @return Return a end itarator
+ * This iterator is initialized with a null pointer
+ * representing a position after the last valid element
+ */
+ DeepFirstIterator endDeepFirst()
+ {
+ return DeepFirstIterator( nullptr, 0 );
+ }
+
+ /// Alias for an initializer list of variants that can contain either a string or a layout column.
+ using TableLayoutArgs = std::initializer_list< std::variant< string_view, TableLayout::Column > >;
+
TableLayout() = default;
/**
- * @brief Construct a new Table object, all values in the table are centered by default
- * @param columnNames The names of the columns
- * @param title The table name
+ * @brief Construct a new Table Layout object
+ * @param title The table title
+ * @param columns A vector containing all column initialized
+ */
+ TableLayout( string_view title,
+ std::vector< TableLayout::Column > const & columns )
+ {
+ setMargin( MarginValue::medium );
+ setTitle( title );
+ for( auto const & column :columns )
+ {
+ addToColumns( column );
+ }
+ }
+
+ /**
+ * @brief Construct a new Table Layout object
+ * @param title The table title
+ * @param args An initializer_list containing string / column
+ */
+ TableLayout( string_view title,
+ TableLayoutArgs args )
+ {
+ setMargin( MarginValue::medium );
+ setTitle( title );
+ processArguments( args );
+ }
+
+ /**
+ * @brief Construct a new Table Layout object
+ * @param args An initializer_list containing string / column
*/
- TableLayout( std::vector< string > const & columnNames, string const & title = "" );
+
+ TableLayout( TableLayoutArgs args )
+ {
+ setMargin( MarginValue::medium );
+ processArguments( args );
+ }
/**
- * @brief Construct a new Table object by specifying value alignment and optionally their displays based to log levels
- * level
- * @param columnParameters List of structures to set up each colum parameters.
- * @param title The table name
+ * @brief Construct a new Table Layout object
+ * @param title The table title
+ * @param args An initializer_list containing string / column
*/
- TableLayout( std::vector< ColumnParam > const & columnParameters, string const & title = "" );
+ TableLayout( string_view title,
+ std::vector< string > const & args )
+ {
+ setMargin( MarginValue::medium );
+ setTitle( title );
+ addToColumns( args );
+ }
+
+ /**
+ * @brief Get the max depth of a column
+ * @return The max column depth
+ */
+ size_t getMaxDepth() const;
/**
* @return The columns vector
*/
- std::vector< Column > const & getColumns() const;
+ std::vector< Column > & getColumns()
+ { return m_tableColumnsData; }
/**
- * @return The table name
+ * @return The columns vector
*/
- string_view getTitle() const;
+ std::vector< Column > const & getColumns() const
+ { return m_tableColumnsData; }
/**
- * @return The border margin, number of spaces at both left and right table sides
+ * @return The table name
*/
- integer const & getBorderMargin() const;
+ string_view getTitle() const
+ { return m_tableTitle; }
/**
- * @return The column margin, numbers of spaces separating both left and right side from each column content
+ * @param title The table title
+ * @return The tableLayout reference
*/
- integer const & getColumnMargin() const;
+ TableLayout & setTitle( string_view title );
/**
- * @return The margin title
+ * @brief Remove the return line at the end & begenning of the table
+ * @param value Value to desactivate or not wrapLine at the end
+ * @return The tableLayout reference
*/
- integer const & getMarginTitle() const;
+ TableLayout & enableLineBreak( bool value );
/**
* @brief Set the minimal margin width between cell content and borders.
* @param marginValue The margin value
+ * @return The tableLayout reference
*/
- void setMargin( MarginValue marginValue );
+ TableLayout & setMargin( MarginValue marginValue );
+
+ /**
+ * @return check if the line break at the end & beginning is activated
+ */
+ bool isLineBreakEnabled() const;
+
+
+ /**
+ * @return The border margin,
+ * number of spaces at both left and right table sides plus vertical character
+ */
+ integer const & getBorderMargin() const
+ { return m_borderMargin; }
+
+ /**
+ * @return The column margin,
+ * numbers of spaces separating both left and right side from a vertical line
+ */
+ integer const & getColumnMargin() const
+ { return m_columnMargin; }
+
+ /**
+ * @return The table margin value
+ */
+ integer const & getMarginValue() const
+ { return m_marginValue; }
+
+ /**
+ * @return The margin title
+ */
+ integer const & getMarginTitle() const
+ { return m_titleMargin; }
+
+/**
+ * @brief Get the Nb Rows object
+ * @return std::vector< integer >&
+ */
+ std::vector< size_t > & getSublineInHeaderCounts()
+ { return m_sublineHeaderCounts; }
+
+/**
+ * @brief Get the Nb Rows object
+ * @return std::vector< integer >&
+ */
+ std::vector< size_t > & getNbSubDataLines()
+ { return m_sublineDataCounts; }
+
+ /**
+ * @brief Create and add a column to the columns vector given a string
+ * @param m_header The column name
+ */
+ void addToColumns( string_view m_header );
private:
- std::vector< Column > m_columns;
+ /**
+ * @brief Add a column to the table given an initializer_list of string & Column
+ * @param args An initializer_list containing string / column
+ */
+ void processArguments( TableLayoutArgs args )
+ {
+ for( auto const & arg : args )
+ {
+ std::visit( [this]( auto const & value ) {
+ addToColumns( value );
+ }, arg );
+ }
+ }
+
+ /**
+ * @brief
+ *
+ * @tparam Ts The remaining arguments
+ * @param args The remaining arguments to be processed
+ */
+ template< typename ... Ts >
+ void processArguments( Ts &... args )
+ {
+ addToColumns( args ... );
+ }
+
+ /**
+ * @brief Create and add columns to the columns vector given a string vector
+ * @param columnNames The columns name
+ */
+ void addToColumns( std::vector< string > const & columnNames );
+
+/**
+ *
+ * @brief Create and add a column to the columns vector given a Column
+ * @param column Vector containing addition information on the column
+ */
+ void addToColumns( TableLayout::Column const & column );
+
+ /// Contains the columns layout
+ std::vector< Column > m_tableColumnsData;
+ /// Contains the subdivision (line) counts for each line in header.
+ std::vector< size_t > m_sublineHeaderCounts;
+ /// Contains the subdivision (line) counts for each line in data.
+ std::vector< size_t > m_sublineDataCounts;
+ bool m_wrapLine = true;
+
string m_tableTitle;
+
integer m_borderMargin;
integer m_columnMargin;
+ integer m_marginValue;
integer m_titleMargin = 2;
};
diff --git a/src/coreComponents/common/format/table/TableTypes.hpp b/src/coreComponents/common/format/table/TableTypes.hpp
new file mode 100644
index 00000000000..56c823ffd28
--- /dev/null
+++ b/src/coreComponents/common/format/table/TableTypes.hpp
@@ -0,0 +1,43 @@
+
+
+/*
+ * ------------------------------------------------------------------------------------------------------------
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
+ * Copyright (c) 2018-2024 TotalEnergies
+ * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
+ * Copyright (c) 2023-2024 Chevron
+ * Copyright (c) 2019- GEOS/GEOSX Contributors
+ * All rights reserved
+ *
+ * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
+ * ------------------------------------------------------------------------------------------------------------
+ */
+
+/**
+ * @file TableData.hpp
+ */
+
+
+#ifndef GEOS_COMMON_FORMAT_TABLETYPES_HPP
+#define GEOS_COMMON_FORMAT_TABLETYPES_HPP
+
+namespace geos
+{
+
+/**
+ * @brief The different type a cell can handle
+ */
+enum class CellType : integer
+{
+ Header,
+ Value,
+ Separator,
+ MergeNext,
+ Hidden
+};
+
+}
+
+#endif /* GEOS_COMMON_FORMAT_TABLETYPES_HPP */
diff --git a/src/coreComponents/common/format/table/unitTests/testTable.cpp b/src/coreComponents/common/format/table/unitTests/testTable.cpp
index 0258385b1a1..8fd6a5fca47 100644
--- a/src/coreComponents/common/format/table/unitTests/testTable.cpp
+++ b/src/coreComponents/common/format/table/unitTests/testTable.cpp
@@ -24,48 +24,77 @@
using namespace geos;
+TEST( testTable, testCSVTable )
+{
+ TableLayout const tableLayout( {
+ TableLayout::Column()
+ .setName( "Cras egestas" ),
+ TableLayout::Column()
+ .setName( "CoordX" ),
+ TableLayout::Column()
+ .setName( "C" ),
+ TableLayout::Column()
+ .setName( "CoordZ" ),
+ TableLayout::Column()
+ .setName( "Prev\nelement" ),
+ TableLayout::Column()
+ .setName( "Next\nelement" )} );
+
+ TableData tableData;
+ tableData.addRow( "value1", "gaz", "3.0", "3.0129877", "2", "1" );
+ tableData.addRow( "val1", "val2", "[3.045,42.02,89.25]", 3.0, 10.0f, 3 );
+
+ TableCSVFormatter const csvOutput( tableLayout );
+
+ EXPECT_EQ( csvOutput.toString( tableData ),
+ "Cras egestas,CoordX,C,CoordZ,Prevelement,Nextelement\n"
+ "value1,gaz,3.0,3.0129877,2,1\n"
+ "val1,val2,[3.045,42.02,89.25],3,10,3\n"
+ );
+}
+
TEST( testTable, tableEmptyRow )
{
//table with empty row
- TableLayout const tableLayout( {"Well\nelement no.\nPV weighted\nbar",
+ TableLayout const tableLayout( "InternalWellGenerator well_injector1",
+ {"Well\nelement no.\nPV weighted\nbar",
"CordX",
"CoordZ",
"Prev\nelement",
- "Next\nelement"},
- "InternalWellGenerator well_injector1"
- );
+ "Next\nelement"} );
TableData tableData;
tableData.addRow( "value1", "[30.21543]", "3.0", 54, 0 );
- tableData.addRow( "", "", "", "", "" );
+ tableData.addRow( "", " ", "", "", "" );
tableData.addRow( "Duis fringilla, ligula sed porta fringilla, ligula wisi commodo felis,ut adipiscing felis dui in enim. Suspendisse malesuada ultrices ante", "[30.21543]", "30.45465142",
787442, 10 );
-
TableTextFormatter const tableText( tableLayout );
+ tableText.toString( tableData );
EXPECT_EQ( tableText.toString(
tableData ),
"\n-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n"
"| InternalWellGenerator well_injector1 |\n"
"-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n"
- "| Well | CordX | CoordZ | Prev | Next |\n"
- "| element no. | | | element | element |\n"
- "| PV weighted | | | | |\n"
- "| bar | | | | |\n"
+ "| Well | CordX | CoordZ | Prev | Next |\n"
+ "| element no. | | | element | element |\n"
+ "| PV weighted | | | | |\n"
+ "| bar | | | | |\n"
"-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n"
"| value1 | [30.21543] | 3.0 | 54 | 0 |\n"
"| | | | | |\n"
"| Duis fringilla, ligula sed porta fringilla, ligula wisi commodo felis,ut adipiscing felis dui in enim. Suspendisse malesuada ultrices ante | [30.21543] | 30.45465142 | 787442 | 10 |\n"
- "-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n\n"
+ "-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n"
);
}
TEST( testTable, tableClassic )
{
- TableLayout const tableLayout( {"Duis fringilla, ligula sed porta fringilla,\nligula wisi commodo felis,ut adipiscing felis dui in enim. Suspendisse malesuada ultrices ante",
+ TableLayout const tableLayout( "InternalWellGenerator well_injector1",
+ {"Duis fringilla, ligula sed porta fringilla,\nligula wisi commodo felis,ut adipiscing felis dui in enim. Suspendisse malesuada ultrices ante",
"CordX",
"CoordZ",
"Prev\nelement",
- "Next\nelement"}, "InternalWellGenerator well_injector1" );
+ "Next\nelement"} );
TableData tableData;
tableData.addRow( "value1", "[30.21543]", "3.0", 54, 0 );
@@ -77,77 +106,100 @@ TEST( testTable, tableClassic )
"\n-----------------------------------------------------------------------------------------------------------------------------------------------------------\n"
"| InternalWellGenerator well_injector1 |\n"
"-----------------------------------------------------------------------------------------------------------------------------------------------------------\n"
- "| Duis fringilla, ligula sed porta fringilla, | CordX | CoordZ | Prev | Next |\n"
+ "| Duis fringilla, ligula sed porta fringilla, | CordX | CoordZ | Prev | Next |\n"
"| ligula wisi commodo felis,ut adipiscing felis dui in enim. Suspendisse malesuada ultrices ante | | | element | element |\n"
"-----------------------------------------------------------------------------------------------------------------------------------------------------------\n"
"| value1 | [30.21543] | 3.0 | 54 | 0 |\n"
"| | | | | |\n"
"| value23 | [30.21543] | 30.45465142 | 787442 | 10 |\n"
- "-----------------------------------------------------------------------------------------------------------------------------------------------------------\n\n"
+ "-----------------------------------------------------------------------------------------------------------------------------------------------------------\n"
);
}
TEST( testTable, tableColumnParamClassic )
{
TableLayout const tableLayout( {
- TableLayout::ColumnParam{{"Cras egestas"}, TableLayout::Alignment::center},
- TableLayout::ColumnParam{{"CoordX"}, TableLayout::Alignment::left},
- TableLayout::ColumnParam{{"C"}, TableLayout::Alignment::left},
- TableLayout::ColumnParam{{"CoordZ"}, TableLayout::Alignment::left},
- TableLayout::ColumnParam{{"Prev\nelement"}, TableLayout::Alignment::right},
- TableLayout::ColumnParam{{"Next\nelement"}, TableLayout::Alignment::right}
- }, "InternalWellGenerator well_injector1" );
+ TableLayout::Column()
+ .setName( "Cras egestas" ),
+ TableLayout::Column()
+ .setName( "CoordX" ),
+ TableLayout::Column()
+ .setName( "C" ),
+ TableLayout::Column()
+ .setName( "CoordZ" ),
+ TableLayout::Column()
+ .setName( "Prev\nelement" ),
+ TableLayout::Column()
+ .setName( "Next\nelement" )} );
TableData tableData;
- tableData.addRow( "value1", " ", "3.0", 3.0129877, 2.0f, 1 );
+ tableData.addRow( "value1", "gaz\nwater", "3.0\n42.0", "3.0129877\n0.0123456", "2\n3", "1\n4" );
tableData.addRow( "val1", "v", "[3.045,42.02,89.25]", 3.0, 10.0f, 3 );
TableTextFormatter const tableText( tableLayout );
EXPECT_EQ( tableText.toString( tableData ),
"\n-------------------------------------------------------------------------------------------\n"
- "| InternalWellGenerator well_injector1 |\n"
- "-------------------------------------------------------------------------------------------\n"
- "| Cras egestas | CoordX | C | CoordZ | Prev | Next |\n"
+ "| Cras egestas | CoordX | C | CoordZ | Prev | Next |\n"
"| | | | | element | element |\n"
"-------------------------------------------------------------------------------------------\n"
- "| value1 | | 3.0 | 3.0129877 | 2 | 1 |\n"
- "| val1 | v | [3.045,42.02,89.25] | 3 | 10 | 3 |\n"
- "-------------------------------------------------------------------------------------------\n\n"
+ "| value1 | gaz | 3.0 | 3.0129877 | 2 | 1 |\n"
+ "| | water | 42.0 | 0.0123456 | 3 | 4 |\n"
+ "| val1 | v | [3.045,42.02,89.25] | 3 | 10 | 3 |\n"
+ "-------------------------------------------------------------------------------------------\n"
);
}
TEST( testTable, tableHiddenColumn )
{
- TableLayout const tableLayout( {
- TableLayout::ColumnParam{{"Cras egestas"}, TableLayout::Alignment::center},
- TableLayout::ColumnParam{{"CoordX"}, TableLayout::Alignment::right},
- TableLayout::ColumnParam{{"C"}, TableLayout::Alignment::center},
- TableLayout::ColumnParam{{"CoordZ"}, TableLayout::Alignment::left},
- TableLayout::ColumnParam{{"Prev\nelement"}, TableLayout::Alignment::left, false},
- TableLayout::ColumnParam{{"Next\nelement"}, TableLayout::Alignment::center, false},
- }, "Cras egestas ipsum a nisl. Vivamus variu dolor utsisicdis parturient montes, nascetur ridiculus mus. Duis" );
+ string const title = "Cras egestas ipsum a nisl. Vivamus variu dolor utsisicdis parturient montes, nascetur ridiculus mus. Duis";
+ TableLayout tableLayout( title,
+ {
+ TableLayout::Column()
+ .setName( "Cras egestas" )
+ .setValuesAlignment( TableLayout::Alignment::left )
+ .setHeaderAlignment( TableLayout::Alignment::center ),
+ TableLayout::Column()
+ .setName( "CoordX" )
+ .setValuesAlignment( TableLayout::Alignment::left )
+ .setHeaderAlignment( TableLayout::Alignment::right )
+ .setVisibility( CellType::Hidden ),
+ TableLayout::Column()
+ .setName( "C" )
+ .setValuesAlignment( TableLayout::Alignment::left )
+ .setHeaderAlignment( TableLayout::Alignment::center ),
+ TableLayout::Column()
+ .setName( "CoordZ" )
+ .setValuesAlignment( TableLayout::Alignment::left )
+ .setHeaderAlignment( TableLayout::Alignment::left ),
+ TableLayout::Column()
+ .setName( "Prev\nelement" )
+ .setVisibility( CellType::Hidden ),
+ TableLayout::Column()
+ .setName( "Next\nelement" )
+ .setVisibility( CellType::Hidden )
+ } );
TableData tableData;
- tableData.addRow( "value1", " ", "3.0", 3.0129877, 2.0f, 1 );
+ tableData.addRow( "value1", "", "3.0", 3.0129877, 2.0f, 1 );
tableData.addRow( "val1", "v", "[3.045,42.02,89.25]", 3.0, 10.0f, 3 );
TableTextFormatter const tableText( tableLayout );
EXPECT_EQ( tableText.toString( tableData ),
- "\n----------------------------------------------------------------------------------------------------------------\n"
- "| Cras egestas ipsum a nisl. Vivamus variu dolor utsisicdis parturient montes, nascetur ridiculus mus. Duis |\n"
- "----------------------------------------------------------------------------------------------------------------\n"
- "| Cras egestas | CoordX | C | CoordZ |\n"
- "----------------------------------------------------------------------------------------------------------------\n"
- "| value1 | | 3.0 | 3.0129877 |\n"
- "| val1 | v | [3.045,42.02,89.25] | 3 |\n"
- "----------------------------------------------------------------------------------------------------------------\n\n" );
+ "\n---------------------------------------------------------------------------------------------------------------\n"
+ "| Cras egestas ipsum a nisl. Vivamus variu dolor utsisicdis parturient montes, nascetur ridiculus mus. Duis |\n"
+ "---------------------------------------------------------------------------------------------------------------\n"
+ "| Cras egestas | C | CoordZ |\n"
+ "| | | |\n"
+ "---------------------------------------------------------------------------------------------------------------\n"
+ "| value1 | 3.0 | 3.0129877 |\n"
+ "| val1 | [3.045,42.02,89.25] | 3 |\n"
+ "---------------------------------------------------------------------------------------------------------------\n" );
}
TEST( testTable, tableUniqueColumn )
{
- TableLayout const tableLayout( {
- TableLayout::ColumnParam{{"Cras egestas"}, TableLayout::Alignment::center},
- }, "Cras egestas ipsu a nisl. Vivamus variu dolor utsisicdis parturient montes, nascetur ridiculus mus. Duis" );
+ string const title = "Cras egestas ipsum a nisl. Vivamus variu dolor utsisicdis parturient montes, nascetur ridiculus mus. Duis";
+ TableLayout const tableLayout( title, {"Cras egestas"} );
TableData tableData;
tableData.addRow( "value1" );
@@ -156,26 +208,34 @@ TEST( testTable, tableUniqueColumn )
TableTextFormatter const tableText( tableLayout );
EXPECT_EQ( tableText.toString( tableData ),
"\n---------------------------------------------------------------------------------------------------------------\n"
- "| Cras egestas ipsu a nisl. Vivamus variu dolor utsisicdis parturient montes, nascetur ridiculus mus. Duis |\n"
+ "| Cras egestas ipsum a nisl. Vivamus variu dolor utsisicdis parturient montes, nascetur ridiculus mus. Duis |\n"
"---------------------------------------------------------------------------------------------------------------\n"
"| Cras egestas |\n"
"---------------------------------------------------------------------------------------------------------------\n"
- "| value1 |\n"
- "| val1 |\n"
- "---------------------------------------------------------------------------------------------------------------\n\n" );
+ "| value1 |\n"
+ "| val1 |\n"
+ "---------------------------------------------------------------------------------------------------------------\n" );
}
TEST( testTable, tableEmptyTitle )
{
TableLayout const tableLayout( {
- TableLayout::ColumnParam{{"Cras egestas"}, TableLayout::Alignment::center},
- TableLayout::ColumnParam{{"CoordX"}, TableLayout::Alignment::right},
- TableLayout::ColumnParam{{"C"}, TableLayout::Alignment::center},
- TableLayout::ColumnParam{{"CoordZ"}, TableLayout::Alignment::left},
- TableLayout::ColumnParam{{"Prev\nelement"}, TableLayout::Alignment::left},
- TableLayout::ColumnParam{{"Next\nelement"}, TableLayout::Alignment::center},
- }
- );
+ TableLayout::Column()
+ .setName( "Cras egestas" )
+ .setHeaderAlignment( TableLayout::Alignment::center ),
+ TableLayout::Column()
+ .setName( "CoordX" )
+ .setHeaderAlignment( TableLayout::Alignment::right ),
+ "C",
+ TableLayout::Column()
+ .setName( "CoordZ" )
+ .setHeaderAlignment( TableLayout::Alignment::left ),
+ TableLayout::Column()
+ .setName( "Prev\nelement" )
+ .setHeaderAlignment( TableLayout::Alignment::left ),
+ TableLayout::Column()
+ .setName( "Next\nelement" )
+ .setHeaderAlignment( TableLayout::Alignment::center )} );
TableData tableData;
tableData.addRow( "value1", " ", "3.0", 3.0129877, 2.0f, 1 );
@@ -187,9 +247,9 @@ TEST( testTable, tableEmptyTitle )
"| Cras egestas | CoordX | C | CoordZ | Prev | Next |\n"
"| | | | | element | element |\n"
"-------------------------------------------------------------------------------------------\n"
- "| value1 | | 3.0 | 3.0129877 | 2 | 1 |\n"
- "| val1 | v | [3.045,42.02,89.25] | 3 | 10 | 3 |\n"
- "-------------------------------------------------------------------------------------------\n\n"
+ "| value1 | | 3.0 | 3.0129877 | 2 | 1 |\n"
+ "| val1 | v | [3.045,42.02,89.25] | 3 | 10 | 3 |\n"
+ "-------------------------------------------------------------------------------------------\n"
);
}
@@ -215,115 +275,222 @@ TEST( testTable, table2DTable )
columnFmt );
//format
- TableLayout const tableLayout( tableconverted.headerNames );
+ TableLayout const tableLayout( "", tableconverted.headerNames );
//log
- TableTextFormatter const tableLog( tableLayout );
- EXPECT_EQ( tableLog.toString( tableconverted.tableData ),
+ TableTextFormatter const tableText( tableLayout );
+ EXPECT_EQ( tableText.toString( tableconverted.tableData ),
"\n---------------------------------------------------------------------\n"
- "| Viscosity kg*s | Pression = 10000 | Pression = 15000 |\n"
+ "| Viscosity kg*s | Pression = 10000 | Pression = 15000 |\n"
"---------------------------------------------------------------------\n"
"| Temperature = 300 | 0.03 | 0.02 |\n"
"| Temperature = 350 | 0.035 | 0.023333333333333334 |\n"
"| Temperature = 400 | 0.04 | 0.02666666666666667 |\n"
- "---------------------------------------------------------------------\n\n"
+ "---------------------------------------------------------------------\n"
+ );
+}
+
+TEST( testTable, layoutTable )
+{
+ string filename = "fluid1_phaseModel1_PhillipsBrineDensity_table";
+ string log = GEOS_FMT( "The {} PVT table exceeding 500 rows.\nTo visualize the tables, go to the generated csv", filename );
+ TableLayout const tableLayoutInfos( filename,
+ {
+ TableLayout::Column()
+ .setName( log )
+ .setHeaderAlignment( TableLayout::Alignment::left )} );
+ TableTextFormatter const tableText( tableLayoutInfos );
+ EXPECT_EQ( tableText.toString(),
+ "\n-------------------------------------------------------------------------------------\n"
+ "| fluid1_phaseModel1_PhillipsBrineDensity_table |\n"
+ "-------------------------------------------------------------------------------------\n"
+ "| The fluid1_phaseModel1_PhillipsBrineDensity_table PVT table exceeding 500 rows. |\n"
+ "| To visualize the tables, go to the generated csv |\n"
+ "-------------------------------------------------------------------------------------\n\n"
);
}
+TEST( testTable, subColumns )
+{
+ {
+ TableLayout const tableLayout( {
+ " ",
+ "Column1",
+ TableLayout::Column()
+ .setName( "Nodes" )
+ .addSubColumns( {"LocalesNodes", "GhostNodes", "ActiveNodes" } ),
+ "Column3",
+ TableLayout::Column()
+ .setName( "Column4" )
+ .addSubColumns( { TableLayout::Column()
+ .setName( "Locales" ).addSubColumns( {"SubLocales1", "SubLocales2"} ),
+ TableLayout::Column()
+ .setName( "Ghost" ).addSubColumns( {"SubGhost1", "SubGhost2"} ),
+ TableLayout::Column()
+ .setName( "Active" ).addSubColumns( {"SubActive1", "SubActive2"} )
+ } ),
+ "Column5"
+ } );
+
+ TableData tableData;
+ tableData.addRow( "3547", "1289", "7534", "6901", "4832", "9281", "1154", "5360", "2739", "9004", "1497", "6", "7" );
+ tableData.addRow( "5142", "8290", "364", "2310", "7011", "1427", "2574", "9043", "5305", "608", "980", "6", "7" );
+ tableData.addRow( "3174", "8259", "6092", "1783", "7435", "2891", "914", "178", "4635", "5839", "8124", "6", "7" );
+ tableData.addRow( "6193", "7481", "1305", "9037", "4306.1", "6157", "1849", "2753", "910", "2369", "9992", "6", "7" );
+ tableData.addRow( "8012", "5729.2112", "6975", "3201.213", "9448", "1820", "4125", "182.12", "7453", "5069", "3912", "6", "7" );
+ tableData.addRow( "4381", "6728", "5204", "8663", "2035", "7804", "6310", "9621", "4158", "789", "2537", "6", "7" );
+ TableTextFormatter tableText( tableLayout );
+ EXPECT_EQ( tableText.toString(
+ tableData ),
+ "\n------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n"
+ "| | Column1 | Nodes | Column3 | Column4 | Column5 |\n"
+ "------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n"
+ "| | | LocalesNodes | GhostNodes | ActiveNodes | | Locales | Ghost | Active | |\n"
+ "------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n"
+ "| | | | | | | SubLocales1 | SubLocales2 | SubGhost1 | SubGhost2 | SubActive1 | SubActive2 | |\n"
+ "------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n"
+ "| 3547 | 1289 | 7534 | 6901 | 4832 | 9281 | 1154 | 5360 | 2739 | 9004 | 1497 | 6 | 7 |\n"
+ "| 5142 | 8290 | 364 | 2310 | 7011 | 1427 | 2574 | 9043 | 5305 | 608 | 980 | 6 | 7 |\n"
+ "| 3174 | 8259 | 6092 | 1783 | 7435 | 2891 | 914 | 178 | 4635 | 5839 | 8124 | 6 | 7 |\n"
+ "| 6193 | 7481 | 1305 | 9037 | 4306.1 | 6157 | 1849 | 2753 | 910 | 2369 | 9992 | 6 | 7 |\n"
+ "| 8012 | 5729.2112 | 6975 | 3201.213 | 9448 | 1820 | 4125 | 182.12 | 7453 | 5069 | 3912 | 6 | 7 |\n"
+ "| 4381 | 6728 | 5204 | 8663 | 2035 | 7804 | 6310 | 9621 | 4158 | 789 | 2537 | 6 | 7 |\n"
+ "------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n"
+ );
+ }
+}
-TEST( testTable, table2DColumnMismatch )
+TEST( testTable, variadicTest )
{
- //test 2D table column mismatch
{
- // collect
- TableData2D tableData;
-
- tableData.addCell( 300, 10000, 0.03 );
- tableData.addCell( 300, 15000, 0.02 );
- tableData.addCell( 350, 10000, 0.035 );
- tableData.addCell( 350, 10000, 0.035 );
- tableData.addCell( 400, 10000, 0.04 );
- tableData.addCell( 400, 15000, 0.02666666666666667 );
-
- //convert
- string const rowFmt = GEOS_FMT( "{} = {{}}", "Temperature" );
- string const columnFmt = GEOS_FMT( "{} = {{}}", "Pression" );
- TableData2D::TableDataHolder tableConverted = tableData.buildTableData( "Viscosity kg*s",
- rowFmt,
- columnFmt );
-
- //format
- TableLayout const tableLayout( tableConverted.headerNames );
-
- //log
- TableTextFormatter const tableLog( tableLayout );
- EXPECT_EQ( tableLog.toString( tableConverted.tableData ),
- "\n--------------------------------------------------------------------\n"
- "| Remarks : some cells may be missing |\n"
- "--------------------------------------------------------------------\n"
- "| Viscosity kg*s | Pression = 10000 | Pression = 15000 |\n"
- "--------------------------------------------------------------------\n"
- "| Temperature = 300 | 0.03 | 0.02 |\n"
- "| Temperature = 350 | 0.035 | |\n"
- "| Temperature = 400 | 0.04 | 0.02666666666666667 |\n"
- "--------------------------------------------------------------------\n\n"
+ TableLayout const layoutTest( "Cras egestas ipsum a nisl. Vivamus variu dolor utsisicdis parturient montes, nascetur ridiculus mus. Duis nascetur ridiculus mus",
+ {
+ "Rank",
+ TableLayout::Column()
+ .setName( "Nodes" )
+ .addSubColumns( {"Locales", "Ghost" } ),
+ "Edge",
+ TableLayout::Column()
+ .setName( "Faces" )
+ .addSubColumns( {"Locales", "Ghost" } ),
+ TableLayout::Column()
+ .setName( "Elems" )
+ .addSubColumns( {"Locales", "Ghost"} ),
+ } );
+ TableData tableData;
+ tableData.addRow( "min(local/total)", 1, 2, 3, 4, 5, 6, 7 );
+ tableData.addRow( "min(local/total)", 1, 2, 3, 4, 5, 6, 7 );
+ TableTextFormatter log( layoutTest );
+ EXPECT_EQ( log.toString( tableData ),
+ "\n--------------------------------------------------------------------------------------------------------------------------------------\n"
+ "| Cras egestas ipsum a nisl. Vivamus variu dolor utsisicdis parturient montes, nascetur ridiculus mus. Duis nascetur ridiculus mus |\n"
+ "--------------------------------------------------------------------------------------------------------------------------------------\n"
+ "| Rank | Nodes | Edge | Faces | Elems |\n"
+ "--------------------------------------------------------------------------------------------------------------------------------------\n"
+ "| | Locales | Ghost | | Locales | Ghost | Locales | Ghost |\n"
+ "--------------------------------------------------------------------------------------------------------------------------------------\n"
+ "| min(local/total) | 1 | 2 | 3 | 4 | 5 | 6 | 7 |\n"
+ "| min(local/total) | 1 | 2 | 3 | 4 | 5 | 6 | 7 |\n"
+ "--------------------------------------------------------------------------------------------------------------------------------------\n"
);
}
}
-TEST( testTable, layoutTable )
+TEST( testTable, testLineBreak )
{
- string filename = "fluid1_phaseModel1_PhillipsBrineDensity_table";
+ TableLayout tableLayout( {"Cras egestas", "CoordX", "C", "CoordZ", "Prev\nelement", "Next\nelement"} );
+ tableLayout.setTitle( "title" ).setMargin( TableLayout::MarginValue::tiny ).enableLineBreak( false );
+
+ TableData tableData;
+ tableData.addRow( "1", "2", "3.0", 3.0129877, 2.0f, 1 );
+ tableData.addRow( "1", "2", "3.0", 3.0129877, 2.0f, 1 );
- string log = GEOS_FMT( "The {} PVT table exceeding 500 rows.\nTo visualize the tables, go to the generated csv \n", filename );
- TableLayout const tableLayoutInfos( {TableLayout::ColumnParam{{log}, TableLayout::Alignment::left}}, filename );
+ TableTextFormatter const tableText( tableLayout );
- TableTextFormatter const tableLog( tableLayoutInfos );
- EXPECT_EQ( tableLog.layoutToString(),
- "\n-------------------------------------------------------------------------------------\n"
- "| fluid1_phaseModel1_PhillipsBrineDensity_table |\n"
- "-------------------------------------------------------------------------------------\n"
- "| The fluid1_phaseModel1_PhillipsBrineDensity_table PVT table exceeding 500 rows. |\n"
- "| To visualize the tables, go to the generated csv |\n"
- "-------------------------------------------------------------------------------------\n"
+ EXPECT_EQ( tableText.toString( tableData ),
+ "---------------------------------------------------\n"
+ "| title |\n"
+ "---------------------------------------------------\n"
+ "|Cras egestas|CoordX| C | CoordZ | Prev | Next |\n"
+ "| | | | |element|element|\n"
+ "---------------------------------------------------\n"
+ "| 1| 2|3.0|3.0129877| 2| 1|\n"
+ "| 1| 2|3.0|3.0129877| 2| 1|\n"
+ "---------------------------------------------------"
);
}
-TEST( testTable, tableSetMargin )
+TEST( testTable, testCellMerging )
{
- ////////////
- //////// If setMargin used elsewhere make it public and remove comments for this test
- ////////////
- //test with tiny margin
- // {
- // TableLayout tableLayout( {
- // TableLayout::ColumnParam{{"Colonne 1"}, TableLayout::Alignment::center},
- // TableLayout::ColumnParam{{"Colonne 2"}, TableLayout::Alignment::center},
- // TableLayout::ColumnParam{{"Colonne 3"}, TableLayout::Alignment::right},
- // TableLayout::ColumnParam{{"Colonne 4"}, TableLayout::Alignment::right},
- // TableLayout::ColumnParam{{"Prev\nelement"}, TableLayout::Alignment::right},
- // TableLayout::ColumnParam{{"Next\nelement"}, TableLayout::Alignment::right},
- // }, "InternalWellGenerator well_injector1" );
-
- // //tableLayout.setMargin( TableLayout::MarginValue::tiny );
-
- // TableData tableData;
- // tableData.addRow( "value 1", "long value 1", "3.0034", 3.0129877, "" , 1 );
- // tableData.addRow( "value 1", "long value 2", "100.45", 4.0129877, 1 , 2 );
-
- // TableTextFormatter const tableText( tableLayout );
- // EXPECT_EQ( tableText.toString( tableData ),
-// "\n------------------------------------------------------------\n"
-// "| InternalWellGenerator well_injector1 |\n"
-// "------------------------------------------------------------\n"
-// "|Colonne 1| Colonne 2 |Colonne 3|Colonne 4| Prev| Next|\n"
-// "| | | | |element|element|\n"
-// "------------------------------------------------------------\n"
-// "| value 1 |long value 1| 3.0034|3.0129877| | 1|\n"
-// "| value 1 |long value 2| 100.45|4.0129877| 1| 2|\n"
-// "------------------------------------------------------------\n\n"
-// );
-// }
+ TableLayout const tableLayout( {
+ TableLayout::Column()
+ .setName( "Cras egestas" ),
+ TableLayout::Column()
+ .setName( "CoordX" ),
+ "C",
+ TableLayout::Column()
+ .setName( "CoordZ" ),
+ TableLayout::Column()
+ .setName( "Prev\nelement" ),
+ TableLayout::Column()
+ .setName( "Next\nelement" )} );
+
+ TableData tableData;
+ tableData.addRow( "ProductA", 1234, 40, "ProductName", 5678, 60 );
+ tableData.addRow( "ProductA", 54, 4564575, "long size value", 5454554512, 60 );
+ tableData.addSeparator();
+ tableData.addRow( "ProductA", 54, 4564575, "long size value", 5454554512, 60 );
+ tableData.addRow( 3.14f, 2.718f, CellType::MergeNext, 1.618f, 0.577f, CellType::MergeNext );
+ tableData.addRow( "P1\nP2\nP3", "2002\n2003\n2004", CellType::MergeNext, "1212121245452145454545", 4004, CellType::MergeNext );
+ tableData.addRow( "Long product size", 54, 4564575, "long size value", 5454554512, 60 );
+ tableData.addRow( "ProductAfdggfd", 5445, 4565, "PrName", 5454512, 64650 );
+ tableData.addRow( 3.14f, 2.718f, CellType::MergeNext, 1.618f, 0.577f, CellType::MergeNext );
+ tableData.addSeparator();
+ tableData.addRow( "CellType::MergeNext", CellType::MergeNext, CellType::MergeNext, CellType::MergeNext, CellType::MergeNext, "Item2" );
+ tableData.addSeparator();
+ tableData.addRow( 1500, 2500, CellType::MergeNext, CellType::MergeNext, CellType::MergeNext, CellType::MergeNext );
+ tableData.addSeparator();
+ tableData.addRow( 1.23f, 4.56f, CellType::MergeNext, "764654665465465654654646", 0.12f, 40 );
+ tableData.addRow( "Long product size", 54, 4564575, "long size value", 5454554512, 60 );
+ tableData.addRow( "ProductA", 54, 4564575, "long size value", 5454554512, 60 );
+ tableData.addSeparator();
+ tableData.addRow( "P1", "2002", CellType::MergeNext, CellType::MergeNext, CellType::MergeNext, "121212465465465666656461245452145454545" );
+ tableData.addSeparator();
+ tableData.addRow( "Alpha", 1001, 8, "Beta\nwater", "2002\n1.0", CellType::MergeNext );
+
+ TableTextFormatter const tableText( tableLayout );
+ std::cout << tableText.toString( tableData ) << std::endl;
+ EXPECT_EQ( tableText.toString( tableData ),
+ "\n-----------------------------------------------------------------------------------------------\n"
+ "| Cras egestas | CoordX | C | CoordZ | Prev | Next |\n"
+ "| | | | | element | element |\n"
+ "-----------------------------------------------------------------------------------------------\n"
+ "| ProductA | 1234 | 40 | ProductName | 5678 | 60 |\n"
+ "| ProductA | 54 | 4564575 | long size value | 5454554512 | 60 |\n"
+ "-----------------------------------------------------------------------------------------------\n"
+ "| ProductA | 54 | 4564575 | long size value | 5454554512 | 60 |\n"
+ "| 3.14 | 2.718 | 1.618 | 0.577 | |\n"
+ "| P1 | 2002 | 1212121245452145454545 | 4004 | |\n"
+ "| P2 | 2003 | | | |\n"
+ "| P3 | 2004 | | | |\n"
+ "| Long product size | 54 | 4564575 | long size value | 5454554512 | 60 |\n"
+ "| ProductAfdggfd | 5445 | 4565 | PrName | 5454512 | 64650 |\n"
+ "| 3.14 | 2.718 | 1.618 | 0.577 | |\n"
+ "-----------------------------------------------------------------------------------------------\n"
+ "| CellType::MergeNext | Item2 |\n"
+ "-----------------------------------------------------------------------------------------------\n"
+ "| 1500 | 2500 | |\n"
+ "-----------------------------------------------------------------------------------------------\n"
+ "| 1.23 | 4.56 | 764654665465465654654646 | 0.12 | 40 |\n"
+ "| Long product size | 54 | 4564575 | long size value | 5454554512 | 60 |\n"
+ "| ProductA | 54 | 4564575 | long size value | 5454554512 | 60 |\n"
+ "-----------------------------------------------------------------------------------------------\n"
+ "| P1 | 2002 | 121212465465465666656461245452145454545 |\n"
+ "-----------------------------------------------------------------------------------------------\n"
+ "| Alpha | 1001 | 8 | Beta | 2002 | |\n"
+ "| | | | water | 1.0 | |\n"
+ "-----------------------------------------------------------------------------------------------\n"
+ );
}
int main( int argc, char * * argv )
diff --git a/src/coreComponents/common/initializeEnvironment.cpp b/src/coreComponents/common/initializeEnvironment.cpp
index 179f7ca4279..832f4fa542f 100644
--- a/src/coreComponents/common/initializeEnvironment.cpp
+++ b/src/coreComponents/common/initializeEnvironment.cpp
@@ -345,11 +345,11 @@ static void addUmpireHighWaterMarks()
pushStatsIntoAdiak( allocatorName + " rank max", mark );
}
- TableLayout const memoryStatLayout ( {"Umpire Memory Pool\n(reserved / % over total)",
- "Min over ranks",
- "Max over ranks",
- "Avg over ranks",
- "Sum over ranks" } );
+ TableLayout const memoryStatLayout ( { "Umpire Memory Pool\n(reserved / % over total)",
+ "Min over ranks",
+ "Max over ranks",
+ "Avg over ranks",
+ "Sum over ranks" } );
TableTextFormatter const memoryStatLog( memoryStatLayout );
GEOS_LOG_RANK_0( memoryStatLog.toString( tableData ));
diff --git a/src/coreComponents/constitutive/ConstitutivePassThru.hpp b/src/coreComponents/constitutive/ConstitutivePassThru.hpp
index ec72812cdb1..7b5b1533134 100644
--- a/src/coreComponents/constitutive/ConstitutivePassThru.hpp
+++ b/src/coreComponents/constitutive/ConstitutivePassThru.hpp
@@ -101,7 +101,6 @@ struct ConstitutivePassThru< FrictionBase >
}
};
-
/**
* Specialization for models that derive from CoulombFriction.
*/
diff --git a/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp b/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp
index 30d43c9ae7f..6376553ec85 100644
--- a/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp
+++ b/src/coreComponents/constitutive/contact/RateAndStateFriction.cpp
@@ -31,12 +31,15 @@ RateAndStateFriction::RateAndStateFriction( string const & name, Group * const p
FrictionBase( name, parent )
{
registerWrapper( viewKeyStruct::aCoefficientString(), &m_a ).
+ setPlotLevel( PlotLevel::LEVEL_0 ).
setDescription( "Rate- and State-dependent friction coefficient a." );
registerWrapper( viewKeyStruct::bCoefficientString(), &m_b ).
+ setPlotLevel( PlotLevel::LEVEL_0 ).
setDescription( "Rate- and State-dependent friction coefficient b." );
registerWrapper( viewKeyStruct::DcCoefficientString(), &m_Dc ).
+ setPlotLevel( PlotLevel::LEVEL_0 ).
setDescription( "Rate- and State-dependent friction characteristic length." );
registerWrapper( viewKeyStruct::referenceVelocityString(), &m_V0 ).
diff --git a/src/coreComponents/functions/TableFunction.cpp b/src/coreComponents/functions/TableFunction.cpp
index 74f031fef87..3fc62833d41 100644
--- a/src/coreComponents/functions/TableFunction.cpp
+++ b/src/coreComponents/functions/TableFunction.cpp
@@ -307,7 +307,7 @@ string TableCSVFormatter::toString< TableFunction >( TableFunction const & table
units::getDescription( tableFunction.getDimUnit( 0 ) ),
units::getDescription( tableFunction.getDimUnit( 1 ) ) );
- TableLayout tableLayout( tableConverted.headerNames );
+ TableLayout const tableLayout( "", tableConverted.headerNames );
TableCSVFormatter csvFormat( tableLayout );
formatterStream << csvFormat.headerToString() << csvFormat.dataToString( tableConverted.tableData );
@@ -322,7 +322,7 @@ string TableTextFormatter::toString< TableFunction >( TableFunction const & tabl
units::Unit const valueUnit = tableFunction.getValueUnit();
arrayView1d< real64 const > const values = tableFunction.getValues();
integer const numDimensions = LvArray::integerConversion< integer >( coordinates.size() );
- string const filename = tableFunction.getName();
+ std::string_view filename = tableFunction.getName();
string logOutput;
GEOS_LOG_RANK_0( GEOS_FMT( "Values in the table are represented by : {}", units::getDescription( valueUnit )));
@@ -335,12 +335,10 @@ string TableTextFormatter::toString< TableFunction >( TableFunction const & tabl
{
tableData.addRow( coords[idx], values[idx] );
}
-
- TableLayout const tableLayout( {
+ TableLayout const tableLayout( filename, {
string( units::getDescription( tableFunction.getDimUnit( 0 ))),
string( units::getDescription( valueUnit ))
- }, filename );
-
+ } );
TableTextFormatter const logTable( tableLayout );
logOutput = logTable.toString( tableData );
}
@@ -358,17 +356,16 @@ string TableTextFormatter::toString< TableFunction >( TableFunction const & tabl
units::getDescription( tableFunction.getDimUnit( 0 ) ),
units::getDescription( tableFunction.getDimUnit( 1 ) ));
- TableLayout tableLayout( tableConverted.headerNames, filename );
-
+ TableLayout const tableLayout( filename, tableConverted.headerNames );
TableTextFormatter const table2DLog( tableLayout );
logOutput = table2DLog.toString( tableConverted.tableData );
}
else
{
- string log = GEOS_FMT( "The {} PVT table exceeding 500 rows.\nTo visualize the tables, go to the generated csv \n", filename );
- TableLayout const tableLayoutInfos( {TableLayout::ColumnParam{{log}, TableLayout::Alignment::left}}, filename );
+ string const log = GEOS_FMT( "The {} PVT table exceeding 500 rows.\nTo visualize the tables, go to the generated csv", filename );
+ TableLayout const tableLayoutInfos( filename, {log} );
TableTextFormatter const tableLog( tableLayoutInfos );
- logOutput = tableLog.layoutToString();
+ logOutput = tableLog.toString();
}
}
return logOutput;
diff --git a/src/coreComponents/linearAlgebra/CMakeLists.txt b/src/coreComponents/linearAlgebra/CMakeLists.txt
index 99cc0bc77d4..b99b0697b03 100644
--- a/src/coreComponents/linearAlgebra/CMakeLists.txt
+++ b/src/coreComponents/linearAlgebra/CMakeLists.txt
@@ -128,6 +128,7 @@ if( ENABLE_HYPRE )
interfaces/hypre/mgrStrategies/HybridSinglePhasePoromechanics.hpp
interfaces/hypre/mgrStrategies/Hydrofracture.hpp
interfaces/hypre/mgrStrategies/LagrangianContactMechanics.hpp
+ interfaces/hypre/mgrStrategies/LagrangianContactMechanicsBubbleStabilization.hpp
interfaces/hypre/mgrStrategies/MultiphasePoromechanics.hpp
interfaces/hypre/mgrStrategies/SinglePhasePoromechanicsEmbeddedFractures.hpp
interfaces/hypre/mgrStrategies/SinglePhasePoromechanicsConformingFractures.hpp
diff --git a/src/coreComponents/linearAlgebra/interfaces/hypre/HypreMGR.cpp b/src/coreComponents/linearAlgebra/interfaces/hypre/HypreMGR.cpp
index 03791b006e1..466fc6ff04d 100644
--- a/src/coreComponents/linearAlgebra/interfaces/hypre/HypreMGR.cpp
+++ b/src/coreComponents/linearAlgebra/interfaces/hypre/HypreMGR.cpp
@@ -27,6 +27,7 @@
#include "linearAlgebra/interfaces/hypre/mgrStrategies/HybridSinglePhasePoromechanics.hpp"
#include "linearAlgebra/interfaces/hypre/mgrStrategies/Hydrofracture.hpp"
#include "linearAlgebra/interfaces/hypre/mgrStrategies/LagrangianContactMechanics.hpp"
+#include "linearAlgebra/interfaces/hypre/mgrStrategies/LagrangianContactMechanicsBubbleStabilization.hpp"
#include "linearAlgebra/interfaces/hypre/mgrStrategies/MultiphasePoromechanics.hpp"
#include "linearAlgebra/interfaces/hypre/mgrStrategies/MultiphasePoromechanicsReservoirFVM.hpp"
#include "linearAlgebra/interfaces/hypre/mgrStrategies/ReactiveCompositionalMultiphaseOBL.hpp"
@@ -138,6 +139,11 @@ void hypre::mgr::createMGR( LinearSolverParameters const & params,
setStrategy< LagrangianContactMechanics >( params.mgr, numComponentsPerField, precond, mgrData );
break;
}
+ case LinearSolverParameters::MGR::StrategyType::lagrangianContactMechanicsBubbleStab:
+ {
+ setStrategy< LagrangianContactMechanicsBubbleStabilization >( params.mgr, numComponentsPerField, precond, mgrData );
+ break;
+ }
case LinearSolverParameters::MGR::StrategyType::multiphasePoromechanics:
{
setStrategy< MultiphasePoromechanics >( params.mgr, numComponentsPerField, precond, mgrData );
diff --git a/src/coreComponents/linearAlgebra/interfaces/hypre/HypreMGR.hpp b/src/coreComponents/linearAlgebra/interfaces/hypre/HypreMGR.hpp
index 8bacdf8b978..c45bc4fe873 100644
--- a/src/coreComponents/linearAlgebra/interfaces/hypre/HypreMGR.hpp
+++ b/src/coreComponents/linearAlgebra/interfaces/hypre/HypreMGR.hpp
@@ -269,6 +269,32 @@ class MGRStrategyBase
setDisplacementAMG( mgrData.mechSolver, separateComponents );
HYPRE_MGRSetFSolver( precond.ptr, mgrData.mechSolver.solve, mgrData.mechSolver.setup, mgrData.mechSolver.ptr );
}
+ /**
+ * @brief
+ *
+ * @param solver
+ */
+ void setILUCoarseSolver( HyprePrecWrapper & solver )
+ {
+ /* (Required) Create ILU solver */
+ HYPRE_ILUCreate( &solver.ptr );
+
+ /* (Recommended) General solver options */
+ int const ilu_type = 0; /* 0, 1, 10, 11, 20, 21, 30, 31, 40, 41, 50 */
+ int const max_iter = 1;
+ double const tol = 0.0;
+ int const reordering = 0; /* 0: none, 1: RCM */
+ int const print_level = 0;
+ HYPRE_ILUSetType( solver.ptr, ilu_type );
+ HYPRE_ILUSetMaxIter( solver.ptr, max_iter );
+ HYPRE_ILUSetTol( solver.ptr, tol );
+ HYPRE_ILUSetLocalReordering( solver.ptr, reordering );
+ HYPRE_ILUSetPrintLevel( solver.ptr, print_level );
+
+ solver.setup = HYPRE_ILUSetup;
+ solver.solve = HYPRE_ILUSolve;
+ solver.destroy = HYPRE_ILUDestroy;
+ }
};
diff --git a/src/coreComponents/linearAlgebra/interfaces/hypre/mgrStrategies/LagrangianContactMechanicsBubbleStabilization.hpp b/src/coreComponents/linearAlgebra/interfaces/hypre/mgrStrategies/LagrangianContactMechanicsBubbleStabilization.hpp
new file mode 100644
index 00000000000..157137b8a8a
--- /dev/null
+++ b/src/coreComponents/linearAlgebra/interfaces/hypre/mgrStrategies/LagrangianContactMechanicsBubbleStabilization.hpp
@@ -0,0 +1,119 @@
+/*
+ * ------------------------------------------------------------------------------------------------------------
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
+ * Copyright (c) 2018-2024 TotalEnergies
+ * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
+ * Copyright (c) 2023-2024 Chevron
+ * Copyright (c) 2019- GEOS/GEOSX Contributors
+ * All rights reserved
+ *
+ * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
+ * ------------------------------------------------------------------------------------------------------------
+ */
+
+/**
+ * @file LagrangianContactMechanicsBubbleStabilization.hpp
+ */
+
+#ifndef GEOS_LINEARALGEBRA_INTERFACES_HYPREMGRLAGRANGIACONTACTMECHANICSBUBBLESTAB_HPP_
+#define GEOS_LINEARALGEBRA_INTERFACES_HYPREMGRLAGRANGIACONTACTMECHANICSBUBBLESTAB_HPP_
+
+#include "linearAlgebra/interfaces/hypre/HypreMGR.hpp"
+
+namespace geos
+{
+
+namespace hypre
+{
+
+namespace mgr
+{
+
+/**
+ * @brief LagrangianContactMechanicsBubbleStabilization strategy
+ *
+ * Contact mechanics with face-centered lagrangian multipliers
+ *
+ * dofLabel: 0 = displacement, x-component
+ * dofLabel: 1 = displacement, y-component
+ * dofLabel: 2 = displacement, z-component
+ * dofLabel: 3 = displacement bubble function, x-component
+ * dofLabel: 4 = displacement bubble function, y-component
+ * dofLabel: 5 = displacement bubble function, z-component
+ * dofLabel: 6 = face-centered lagrange multiplier (tn)
+ * dofLabel: 7 = face-centered lagrange multiplier (tt1)
+ * dofLabel: 8 = face-centered lagrange multiplier (tt2)
+ *
+ * 2-level MGR strategy:
+ * Level 0:
+ * 1. F-points: bubbles (3,4,5), C-points: displacements + multipliers (0,1,2,6,7,8)
+ * 2. F-points smoother: l1jacobi
+ * 3. Global smoother: none
+ * Level 1:
+ * 1. F-points: multipliers (6,7,8), C-points: displacements (0,1,2)
+ * 2. F-points smoother: l1jacobi
+ * 3. Global smoother: none
+ *
+ * C-points coarse-grid/Schur complement solver: boomer AMG
+
+ */
+class LagrangianContactMechanicsBubbleStabilization : public MGRStrategyBase< 2 >
+{
+public:
+
+ /**
+ * @brief Constructor.
+ */
+ explicit LagrangianContactMechanicsBubbleStabilization( arrayView1d< int const > const & )
+ : MGRStrategyBase( 9 )
+ {
+ // Level 0: we keep all three displacements and the Lagrange Multipliers
+ m_labels[0] = { 0, 1, 2, 6, 7, 8 };
+ // Level 1: we keep all three displacements
+ m_labels[1] = { 0, 1, 2 };
+
+ setupLabels();
+
+ // Level 0
+ m_levelFRelaxType[0] = MGRFRelaxationType::l1jacobi;
+ m_levelFRelaxIters[0] = 1;
+ m_levelInterpType[0] = MGRInterpolationType::blockJacobi;
+ m_levelRestrictType[0] = MGRRestrictionType::injection;
+ m_levelCoarseGridMethod[0] = MGRCoarseGridMethod::galerkin;
+ m_levelGlobalSmootherType[0] = MGRGlobalSmootherType::none;
+
+ // Level 1
+ m_levelFRelaxType[1] = MGRFRelaxationType::l1jacobi;
+ m_levelFRelaxIters[1] = 1;
+ m_levelInterpType[1] = MGRInterpolationType::blockJacobi;
+ m_levelRestrictType[1] = MGRRestrictionType::injection;
+ m_levelCoarseGridMethod[1] = MGRCoarseGridMethod::galerkin;
+ m_levelGlobalSmootherType[1] = MGRGlobalSmootherType::none;
+ }
+
+ /**
+ * @brief Setup the MGR strategy.
+ * @param mgrParams MGR configuration parameters
+ * @param precond preconditioner wrapper
+ * @param mgrData auxiliary MGR data
+ */
+ void setup( LinearSolverParameters::MGR const & mgrParams,
+ HyprePrecWrapper & precond,
+ HypreMGRData & mgrData )
+ {
+ setReduction( precond, mgrData );
+
+ // Configure the BoomerAMG solver used as mgr coarse solver for the displacement reduced system
+ setDisplacementAMG( mgrData.coarseSolver, mgrParams.separateComponents );
+ }
+};
+
+} // namespace mgr
+
+} // namespace hypre
+
+} // namespace geos
+
+#endif /*GEOS_LINEARALGEBRA_INTERFACES_HYPREMGRLAGRANGIACONTACTMECHANICSBUBBLESTAB_HPP_*/
diff --git a/src/coreComponents/linearAlgebra/utilities/LinearSolverParameters.hpp b/src/coreComponents/linearAlgebra/utilities/LinearSolverParameters.hpp
index 803946ac95c..4d43955a0e1 100644
--- a/src/coreComponents/linearAlgebra/utilities/LinearSolverParameters.hpp
+++ b/src/coreComponents/linearAlgebra/utilities/LinearSolverParameters.hpp
@@ -295,6 +295,7 @@ struct LinearSolverParameters
thermalMultiphasePoromechanics, ///< thermal multiphase poromechanics with finite volume compositional multiphase flow
hydrofracture, ///< hydrofracture
lagrangianContactMechanics, ///< Lagrangian contact mechanics
+ lagrangianContactMechanicsBubbleStab, ///< Lagrangian contact mechanics with bubble stabilization
solidMechanicsEmbeddedFractures ///< Embedded fractures mechanics
};
@@ -387,6 +388,7 @@ ENUM_STRINGS( LinearSolverParameters::MGR::StrategyType,
"thermalMultiphasePoromechanics",
"hydrofracture",
"lagrangianContactMechanics",
+ "lagrangianContactMechanicsBubbleStab",
"solidMechanicsEmbeddedFractures" );
/// Declare strings associated with enumeration values.
diff --git a/src/coreComponents/mesh/DomainPartition.cpp b/src/coreComponents/mesh/DomainPartition.cpp
index befc10b4850..528ac6b08cf 100644
--- a/src/coreComponents/mesh/DomainPartition.cpp
+++ b/src/coreComponents/mesh/DomainPartition.cpp
@@ -18,6 +18,9 @@
*/
#include "DomainPartition.hpp"
+#include "common/format/table/TableData.hpp"
+#include "common/format/table/TableFormatter.hpp"
+#include "common/format/table/TableLayout.hpp"
#include "common/DataTypes.hpp"
#include "common/TimingMacros.hpp"
@@ -322,13 +325,60 @@ void DomainPartition::addNeighbors( const unsigned int idim,
void DomainPartition::outputPartitionInformation() const
{
+ using stringutilities::addCommaSeparators;
- auto numberOfEntities = []( ObjectManagerBase const & objectManager )
+ struct RankMeshStats
{
- return std::make_pair( objectManager.getNumberOfLocalIndices(), objectManager.getNumberOfGhosts() );
+ // Table rows will follow this enum ordering
+ enum StatIndex
+ {
+ Node = 0, Edge, Face, Elem, Count
+ };
+ std::array< globalIndex, 4 > localCount = {};
+ std::array< globalIndex, 4 > ghostCount = {};
+ std::array< double, 4 > ratio = {};
+ };
+
+ auto fillStats = []( RankMeshStats & stat,
+ RankMeshStats::StatIndex statIndex,
+ ObjectManagerBase const & objectManager )
+ {
+ stat.localCount[ statIndex ] += objectManager.getNumberOfLocalIndices();
+ stat.ghostCount[ statIndex ] += objectManager.getNumberOfGhosts();
+ };
+
+ auto computeRatios = []( RankMeshStats & stat )
+ {
+ for( size_t i = 0; i < RankMeshStats::StatIndex::Count; ++i )
+ {
+ stat.ratio[i] = stat.localCount[i] + stat.ghostCount[i] == 0 ? 0 :
+ (double)stat.localCount[i] / (double)(stat.localCount[i] + stat.ghostCount[i]);
+ }
+ };
+
+ auto addLocalGhostRow = []( TableData & tableData, RankMeshStats const & stat, string_view heading )
+ {
+ tableData.addRow( heading,
+ addCommaSeparators( stat.localCount[0] ), addCommaSeparators( stat.ghostCount[0] ),
+ addCommaSeparators( stat.localCount[0] + stat.ghostCount[0] ),
+ addCommaSeparators( stat.localCount[1] ), addCommaSeparators( stat.ghostCount[1] ),
+ addCommaSeparators( stat.localCount[1] + stat.ghostCount[1] ),
+ addCommaSeparators( stat.localCount[2] ), addCommaSeparators( stat.ghostCount[2] ),
+ addCommaSeparators( stat.localCount[2] + stat.ghostCount[2] ),
+ addCommaSeparators( stat.localCount[3] ), addCommaSeparators( stat.ghostCount[3] ),
+ addCommaSeparators( stat.localCount[3] + stat.ghostCount[3] ) );
};
- GEOS_LOG_RANK_0( "MPI Partition information:" );
+ auto addSummaryRow = []( TableData & tableData, std::array< double, 4 > stats, string_view heading )
+ {
+ tableData.addRow( heading,
+ CellType::MergeNext, CellType::MergeNext, stats[0],
+ CellType::MergeNext, CellType::MergeNext, stats[1],
+ CellType::MergeNext, CellType::MergeNext, stats[2],
+ CellType::MergeNext, CellType::MergeNext, stats[3] );
+ };
+
+ GEOS_LOG_RANK_0( "MPI Partitioning information:" );
forMeshBodies( [&]( MeshBody const & meshBody )
{
@@ -336,128 +386,117 @@ void DomainPartition::outputPartitionInformation() const
{
if( level!=0 )
{
+ // formatting is done on rank 0
+ std::vector< RankMeshStats > allRankStats;
+ allRankStats.resize( MpiWrapper::commSize() );
+
+ { // Compute stats of the current rank, then gather it on rank 0
+ RankMeshStats rankStats{};
+ fillStats( rankStats, RankMeshStats::Node, meshLevel.getNodeManager() );
+ fillStats( rankStats, RankMeshStats::Edge, meshLevel.getEdgeManager() );
+ fillStats( rankStats, RankMeshStats::Face, meshLevel.getFaceManager() );
+
+ meshLevel.getElemManager().forElementSubRegions< CellElementSubRegion >(
+ [&]( CellElementSubRegion const & subRegion )
+ {
+ fillStats( rankStats, RankMeshStats::Elem, subRegion );
+ } );
- // get the number of local and ghost entities for each type
- auto const [ numLocalNodes, numGhostNodes ] = numberOfEntities( meshLevel.getNodeManager() );
- real64 const nodeRatio = ( numLocalNodes + numGhostNodes ) > 0 ? real64( numLocalNodes ) / real64( numLocalNodes + numGhostNodes ) : -1.0;
- auto const [ numLocalEdges, numGhostEdges ] = numberOfEntities( meshLevel.getEdgeManager() );
- real64 const edgeRatio = ( numLocalEdges + numGhostEdges ) > 0 ? real64( numLocalEdges ) / real64( numLocalEdges + numGhostEdges ) : -1.0;
- auto const [ numLocalFaces, numGhostFaces ] = numberOfEntities( meshLevel.getFaceManager() );
- real64 const faceRatio = ( numLocalFaces + numGhostFaces ) > 0 ? real64( numLocalFaces ) / real64( numLocalFaces + numGhostFaces ) : -1.0;
-
- localIndex numLocalElems = 0;
- localIndex numGhostElems = 0;
- meshLevel.getElemManager().forElementSubRegions< CellElementSubRegion >( [&]( CellElementSubRegion const & subRegion )
- {
- auto [ numLocalElemsInSubRegion, numGhostElemsInSubRegion ] = numberOfEntities( subRegion );
- numLocalElems += numLocalElemsInSubRegion;
- numGhostElems += numGhostElemsInSubRegion;
- } );
- real64 const elemRatio = ( numLocalElems + numGhostElems ) > 0 ? real64( numLocalElems ) / real64( numLocalElems + numGhostElems ) : -1.0;
-
- localIndex const values[8] = { numLocalNodes, numGhostNodes, numLocalEdges, numGhostEdges, numLocalFaces, numGhostFaces, numLocalElems, numGhostElems };
- localIndex minValues[8] = {0};
- localIndex maxValues[8] = {0};
- MpiWrapper::allReduce( values, minValues, 8, MPI_MIN, MPI_COMM_WORLD );
- MpiWrapper::allReduce( values, maxValues, 8, MPI_MAX, MPI_COMM_WORLD );
- localIndex const minNumLocalNodes = minValues[0];
- localIndex const maxNumLocalNodes = maxValues[0];
- localIndex const minNumGhostNodes = minValues[1];
- localIndex const maxNumGhostNodes = maxValues[1];
- localIndex const minNumLocalEdges = minValues[2];
- localIndex const maxNumLocalEdges = maxValues[2];
- localIndex const minNumGhostEdges = minValues[3];
- localIndex const maxNumGhostEdges = maxValues[3];
- localIndex const minNumLocalFaces = minValues[4];
- localIndex const maxNumLocalFaces = maxValues[4];
- localIndex const minNumGhostFaces = minValues[5];
- localIndex const maxNumGhostFaces = maxValues[5];
- localIndex const minNumLocalElems = minValues[6];
- localIndex const maxNumLocalElems = maxValues[6];
- localIndex const minNumGhostElems = minValues[7];
- localIndex const maxNumGhostElems = maxValues[7];
-
- real64 const ratios[4] = { nodeRatio, edgeRatio, faceRatio, elemRatio };
- real64 minRatios[4] = {0};
- real64 maxRatios[4] = {0};
- MpiWrapper::allReduce( ratios, minRatios, 4, MPI_MIN, MPI_COMM_WORLD );
- MpiWrapper::allReduce( ratios, maxRatios, 4, MPI_MAX, MPI_COMM_WORLD );
- real64 const minNodeRatio = minRatios[0];
- real64 const maxNodeRatio = maxRatios[0];
- real64 const minEdgeRatio = minRatios[1];
- real64 const maxEdgeRatio = maxRatios[1];
- real64 const minFaceRatio = minRatios[2];
- real64 const maxFaceRatio = maxRatios[2];
- real64 const minElemRatio = minRatios[3];
- real64 const maxElemRatio = maxRatios[3];
-
- GEOS_LOG_RANK_0( " MeshBody: " + meshBody.getName() + " MeshLevel: " + meshLevel.getName() + "\n" );
- GEOS_LOG_RANK_0( " |------------------------------------------------------------------------------------------------------------------------------------------------|" );
- GEOS_LOG_RANK_0( " | | Nodes | Edges | Faces | Elems |" );
- GEOS_LOG_RANK_0( " |------------------------------------------------------------------------------------------------------------------------------------------------|" );
- GEOS_LOG_RANK_0( GEOS_FMT( " |min(local/total)| {:4.2f} | {:4.2f} | {:4.2f} | {:4.2f} | ",
- minNodeRatio,
- minEdgeRatio,
- minFaceRatio,
- minElemRatio ) );
- GEOS_LOG_RANK_0( GEOS_FMT( " |max(local/total)| {:4.2f} | {:4.2f} | {:4.2f} | {:4.2f} | ",
- maxNodeRatio,
- maxEdgeRatio,
- maxFaceRatio,
- maxElemRatio ) );
- GEOS_LOG_RANK_0( " |------------------------------------------------------------------------------------------------------------------------------------------------|" );
- GEOS_LOG_RANK_0( " | Rank | local | ghost | local | ghost | local | ghost | local | ghost |" );
- GEOS_LOG_RANK_0( " |----------------|---------------|---------------|---------------|---------------|---------------|---------------|---------------|---------------|" );
-
-
- GEOS_LOG_RANK_0( GEOS_FMT( " | min | {:>13} | {:>13} | {:>13} | {:>13} | {:>13} | {:>13} | {:>13} | {:>13} |",
- stringutilities::addCommaSeparators( minNumLocalNodes ),
- stringutilities::addCommaSeparators( minNumGhostNodes ),
- stringutilities::addCommaSeparators( minNumLocalEdges ),
- stringutilities::addCommaSeparators( minNumGhostEdges ),
- stringutilities::addCommaSeparators( minNumLocalFaces ),
- stringutilities::addCommaSeparators( minNumGhostFaces ),
- stringutilities::addCommaSeparators( minNumLocalElems ),
- stringutilities::addCommaSeparators( minNumGhostElems ) ) );
-
- GEOS_LOG_RANK_0( GEOS_FMT( " | max | {:>13} | {:>13} | {:>13} | {:>13} | {:>13} | {:>13} | {:>13} | {:>13} |",
- stringutilities::addCommaSeparators( maxNumLocalNodes ),
- stringutilities::addCommaSeparators( maxNumGhostNodes ),
- stringutilities::addCommaSeparators( maxNumLocalEdges ),
- stringutilities::addCommaSeparators( maxNumGhostEdges ),
- stringutilities::addCommaSeparators( maxNumLocalFaces ),
- stringutilities::addCommaSeparators( maxNumGhostFaces ),
- stringutilities::addCommaSeparators( maxNumLocalElems ),
- stringutilities::addCommaSeparators( maxNumGhostElems ) ) );
-
- GEOS_LOG_RANK_0( " |------------------------------------------------------------------------------------------------------------------------------------------------|" );
-
- // output in rank order
- int const thisRank = MpiWrapper::commRank();
- for( int rank=0; rank13} | {:>13} | {:>13} | {:>13} | {:>13} | {:>13} | {:>13} | {:>13} | ",
- rank,
- stringutilities::addCommaSeparators( numLocalNodes ),
- stringutilities::addCommaSeparators( numGhostNodes ),
- stringutilities::addCommaSeparators( numLocalEdges ),
- stringutilities::addCommaSeparators( numGhostEdges ),
- stringutilities::addCommaSeparators( numLocalFaces ),
- stringutilities::addCommaSeparators( numGhostFaces ),
- stringutilities::addCommaSeparators( numLocalElems ),
- stringutilities::addCommaSeparators( numGhostElems ) ) );
+ if( rankId == 1 )
+ tableData.addSeparator();
+
+ addLocalGhostRow( tableData, allRankStats[rankId], std::to_string( rankId ) );
}
- MpiWrapper::barrier();
+
+ RankMeshStats sumStats{};
+ RankMeshStats minStats{};
+ RankMeshStats maxStats{};
+
+ for( size_t statId = 0; statId < RankMeshStats::Count; ++statId )
+ {
+ minStats.localCount[statId] = std::numeric_limits< globalIndex >::max();
+ minStats.ghostCount[statId] = std::numeric_limits< globalIndex >::max();
+ minStats.ratio[statId] = std::numeric_limits< double >::max();
+
+ maxStats.localCount[statId] = std::numeric_limits< globalIndex >::min();
+ maxStats.ghostCount[statId] = std::numeric_limits< globalIndex >::min();
+ maxStats.ratio[statId] = std::numeric_limits< double >::min();
+ }
+
+ for( int rankId = 0; rankId < MpiWrapper::commSize(); ++rankId )
+ {
+ for( size_t statId = 0; statId < RankMeshStats::Count; ++statId )
+ {
+ sumStats.localCount[statId] += allRankStats[rankId].localCount[statId];
+ sumStats.ghostCount[statId] += allRankStats[rankId].ghostCount[statId];
+
+ minStats.localCount[statId] = std::min( minStats.localCount[statId], allRankStats[rankId].localCount[statId] );
+ minStats.ghostCount[statId] = std::min( minStats.ghostCount[statId], allRankStats[rankId].ghostCount[statId] );
+ minStats.ratio[statId] = std::min( minStats.ratio[statId], allRankStats[rankId].ratio[statId] );
+
+ maxStats.localCount[statId] = std::max( maxStats.localCount[statId], allRankStats[rankId].localCount[statId] );
+ maxStats.ghostCount[statId] = std::max( maxStats.ghostCount[statId], allRankStats[rankId].ghostCount[statId] );
+ maxStats.ratio[statId] = std::max( maxStats.ratio[statId], allRankStats[rankId].ratio[statId] );
+ }
+ }
+
+ tableData.addSeparator();
+ addLocalGhostRow( tableData, sumStats, "sum" );
+ addLocalGhostRow( tableData, minStats, "min" );
+ addLocalGhostRow( tableData, maxStats, "max" );
+
+ std::array< double, 4 > localTotalMinRatio;
+ std::array< double, 4 > localTotalMaxRatio;
+
+ for( size_t statId = 0; statId < RankMeshStats::Count; ++statId )
+ {
+ localTotalMinRatio[statId] = std::numeric_limits< double >::max();
+ localTotalMaxRatio[statId] = std::numeric_limits< double >::min();
+ }
+
+ for( size_t statId = 0; statId < RankMeshStats::Count; ++statId )
+ {
+ localTotalMinRatio[statId] = std::min( localTotalMinRatio[statId], minStats.ratio[statId] );
+ localTotalMaxRatio[statId] = std::max( localTotalMinRatio[statId], maxStats.ratio[statId] );
+ }
+ tableData.addSeparator();
+ addSummaryRow( tableData, localTotalMinRatio, "min(local/total)" );
+ addSummaryRow( tableData, localTotalMaxRatio, "max(local/total)" );
+
+ TableTextFormatter logPartition( layout );
+ GEOS_LOG_RANK_0( logPartition.toString( tableData ));
}
- MpiWrapper::barrier();
- GEOS_LOG_RANK_0( " |------------------------------------------------------------------------------------------------------------------------------------------------|" );
+
}
} );
- }
-
- );
+ } );
}
diff --git a/src/coreComponents/mesh/generators/WellGeneratorBase.cpp b/src/coreComponents/mesh/generators/WellGeneratorBase.cpp
index af80ec09c8a..5debc76589f 100644
--- a/src/coreComponents/mesh/generators/WellGeneratorBase.cpp
+++ b/src/coreComponents/mesh/generators/WellGeneratorBase.cpp
@@ -513,7 +513,7 @@ void WellGeneratorBase::mergePerforations( array1d< array1d< localIndex > > cons
void WellGeneratorBase::logInternalWell() const
{
- TableData tableWellData;
+ TableData wellData;
for( globalIndex iwelem = 0; iwelem < m_numElems; ++iwelem )
{
std::optional< globalIndex > nextElement;
@@ -529,40 +529,38 @@ void WellGeneratorBase::logInternalWell() const
prevElement = m_prevElemId[iwelem][0];
}
- tableWellData.addRow( iwelem,
- m_elemCenterCoords[iwelem][0],
- m_elemCenterCoords[iwelem][1],
- m_elemCenterCoords[iwelem][2],
- prevElement,
- nextElement );
+ wellData.addRow( iwelem,
+ m_elemCenterCoords[iwelem][0],
+ m_elemCenterCoords[iwelem][1],
+ m_elemCenterCoords[iwelem][2],
+ prevElement,
+ nextElement );
}
- string const wellTitle = GEOS_FMT( "Well '{}' Element Table", getName() );
- TableLayout const tableWellLayout = TableLayout( {
- TableLayout::ColumnParam{"Element no.", TableLayout::Alignment::right},
- TableLayout::ColumnParam{"CoordX", TableLayout::Alignment::right},
- TableLayout::ColumnParam{"CoordY", TableLayout::Alignment::right},
- TableLayout::ColumnParam{"CoordZ", TableLayout::Alignment::right},
- TableLayout::ColumnParam{"Prev\nElement", TableLayout::Alignment::right},
- TableLayout::ColumnParam{"Next\nElement", TableLayout::Alignment::right},
- }, wellTitle );
-
- TableTextFormatter const tableFormatter( tableWellLayout );
- GEOS_LOG_RANK_0( tableFormatter.toString( tableWellData ));
+ TableLayout const wellLayout( GEOS_FMT( "Well '{}' Element Table", getName() ),
+ {"Element no.",
+ "CoordX",
+ "CoordY",
+ "CoordZ",
+ "Prev\nElement",
+ "Next\nElement"} );
+
+ TableTextFormatter const wellFormatter( wellLayout );
+ GEOS_LOG_RANK_0( wellFormatter.toString( wellData ));
}
void WellGeneratorBase::logPerforationTable() const
{
- TableData tablePerfoData;
+ TableData dataPerforation;
for( globalIndex iperf = 0; iperf < m_numPerforations; ++iperf )
{
- tablePerfoData.addRow( iperf, m_perfCoords[iperf], m_perfElemId[iperf] );
+ dataPerforation.addRow( iperf, m_perfCoords[iperf], m_perfElemId[iperf] );
}
- TableLayout const tableLayoutPerfo ( {"Perforation no.", "Coordinates", "Well element no."},
- GEOS_FMT( "Well '{}' Perforation Table", getName() ) );
- TableTextFormatter const tablePerfoLog( tableLayoutPerfo );
- GEOS_LOG_RANK_0( tablePerfoLog.toString( tablePerfoData ));
+ TableLayout const layoutPerforation ( GEOS_FMT( "Well '{}' Perforation Table", getName()),
+ { "Perforation no.", "Coordinates", "Well element no." } );
+ TableTextFormatter const logPerforation( layoutPerforation );
+ GEOS_LOG_RANK_0( logPerforation.toString( dataPerforation ));
}
}
diff --git a/src/coreComponents/physicsSolvers/LinearSolverParameters.cpp b/src/coreComponents/physicsSolvers/LinearSolverParameters.cpp
index a5f5b402760..cdf39353527 100644
--- a/src/coreComponents/physicsSolvers/LinearSolverParameters.cpp
+++ b/src/coreComponents/physicsSolvers/LinearSolverParameters.cpp
@@ -341,10 +341,8 @@ void LinearSolverParametersInput::print()
tableData.addRow( "ILU(T) threshold factor", m_parameters.ifact.threshold );
}
}
- TableLayout const tableLayout = TableLayout( {
- TableLayout::ColumnParam{"Parameter", TableLayout::Alignment::left},
- TableLayout::ColumnParam{"Value", TableLayout::Alignment::left},
- }, GEOS_FMT( "{}: linear solver", getParent().getName() ) );
+ TableLayout const tableLayout = TableLayout( GEOS_FMT( "{}: linear solver", getParent().getName() ),
+ { "Parameter", "Value" } );
TableTextFormatter const tableFormatter( tableLayout );
GEOS_LOG_RANK_0( tableFormatter.toString( tableData ));
}
diff --git a/src/coreComponents/physicsSolvers/NonlinearSolverParameters.cpp b/src/coreComponents/physicsSolvers/NonlinearSolverParameters.cpp
index 86563d4be24..dd9c0d58a7c 100644
--- a/src/coreComponents/physicsSolvers/NonlinearSolverParameters.cpp
+++ b/src/coreComponents/physicsSolvers/NonlinearSolverParameters.cpp
@@ -235,10 +235,8 @@ void NonlinearSolverParameters::print() const
tableData.addRow( "Sequential convergence criterion", m_sequentialConvergenceCriterion );
tableData.addRow( "Subcycling", m_subcyclingOption );
}
- TableLayout const tableLayout = TableLayout( {
- TableLayout::ColumnParam{"Parameter", TableLayout::Alignment::left},
- TableLayout::ColumnParam{"Value", TableLayout::Alignment::left},
- }, GEOS_FMT( "{}: nonlinear solver", getParent().getName() ) );
+ TableLayout const tableLayout = TableLayout( GEOS_FMT( "{}: nonlinear solver", getParent().getName() ),
+ { "Parameter", "Value" } );
TableTextFormatter const tableFormatter( tableLayout );
GEOS_LOG_RANK_0( tableFormatter.toString( tableData ));
}
diff --git a/src/coreComponents/physicsSolvers/contact/ContactFields.hpp b/src/coreComponents/physicsSolvers/contact/ContactFields.hpp
index df37934c0cd..2c61762010c 100644
--- a/src/coreComponents/physicsSolvers/contact/ContactFields.hpp
+++ b/src/coreComponents/physicsSolvers/contact/ContactFields.hpp
@@ -75,7 +75,7 @@ DECLARE_FIELD( dispJump,
"Displacement jump vector in the local reference system" );
DECLARE_FIELD( dispJump_n,
- "displacementJump",
+ "displacementJump_n",
array2d< real64 >,
0,
NOPLOT,
@@ -98,6 +98,14 @@ DECLARE_FIELD( deltaSlip,
WRITE_AND_READ,
"Slip increment" );
+DECLARE_FIELD( deltaSlip_n,
+ "deltaSlip_n",
+ array2d< real64 >,
+ 0.0,
+ NOPLOT,
+ WRITE_AND_READ,
+ "Initial slip increment at this time step" );
+
DECLARE_FIELD( deltaDispJump,
"deltaDisplacementJump",
array2d< real64 >,
diff --git a/src/coreComponents/physicsSolvers/contact/ContactSolverBase.cpp b/src/coreComponents/physicsSolvers/contact/ContactSolverBase.cpp
index 6fecd60e93c..c1c886aa3dd 100644
--- a/src/coreComponents/physicsSolvers/contact/ContactSolverBase.cpp
+++ b/src/coreComponents/physicsSolvers/contact/ContactSolverBase.cpp
@@ -26,6 +26,7 @@
#include "physicsSolvers/contact/LogLevelsInfo.hpp"
#include "physicsSolvers/solidMechanics/SolidMechanicsLagrangianFEM.hpp"
#include "common/GEOS_RAJA_Interface.hpp"
+#include "fieldSpecification/FieldSpecificationManager.hpp"
namespace geos
{
@@ -66,6 +67,7 @@ void ContactSolverBase::registerDataOnMesh( dataRepository::Group & meshBodies )
forFractureRegionOnMeshTargets( meshBodies, [&] ( SurfaceElementRegion & fractureRegion )
{
string const labels[3] = { "normal", "tangent1", "tangent2" };
+ string const labelsTangent[2] = { "tangent1", "tangent2" };
fractureRegion.forElementSubRegions< SurfaceElementSubRegion >( [&]( SurfaceElementSubRegion & subRegion )
{
@@ -83,6 +85,10 @@ void ContactSolverBase::registerDataOnMesh( dataRepository::Group & meshBodies )
setDimLabels( 1, labels ).
reference().resizeDimension< 1 >( 3 );
+ subRegion.registerField< fields::contact::dispJump_n >( getName() ).
+ setDimLabels( 1, labels ).
+ reference().resizeDimension< 1 >( 3 );
+
subRegion.registerField< fields::contact::traction >( getName() ).
setDimLabels( 1, labels ).
reference().resizeDimension< 1 >( 3 );
@@ -93,7 +99,11 @@ void ContactSolverBase::registerDataOnMesh( dataRepository::Group & meshBodies )
subRegion.registerField< fields::contact::slip >( getName() );
- subRegion.registerField< fields::contact::deltaSlip >( getName() );
+ subRegion.registerField< fields::contact::deltaSlip >( getName() ).
+ setDimLabels( 1, labelsTangent ).reference().resizeDimension< 1 >( 2 );
+
+ subRegion.registerField< fields::contact::deltaSlip_n >( this->getName() ).
+ setDimLabels( 1, labelsTangent ).reference().resizeDimension< 1 >( 2 );
} );
} );
diff --git a/src/coreComponents/physicsSolvers/contact/SolidMechanicsLagrangeContactBubbleStab.cpp b/src/coreComponents/physicsSolvers/contact/SolidMechanicsLagrangeContactBubbleStab.cpp
index 2d1f139362b..7c2543a3a08 100644
--- a/src/coreComponents/physicsSolvers/contact/SolidMechanicsLagrangeContactBubbleStab.cpp
+++ b/src/coreComponents/physicsSolvers/contact/SolidMechanicsLagrangeContactBubbleStab.cpp
@@ -46,6 +46,10 @@ SolidMechanicsLagrangeContactBubbleStab::SolidMechanicsLagrangeContactBubbleStab
m_faceTypeToFiniteElements["Quadrilateral"] = std::make_unique< finiteElement::H1_QuadrilateralFace_Lagrange1_GaussLegendre2 >();
m_faceTypeToFiniteElements["Triangle"] = std::make_unique< finiteElement::H1_TriangleFace_Lagrange1_Gauss1 >();
+ LinearSolverParameters & linSolParams = m_linearSolverParameters.get();
+ linSolParams.mgr.strategy = LinearSolverParameters::MGR::StrategyType::lagrangianContactMechanicsBubbleStab;
+ linSolParams.mgr.separateComponents = true;
+ linSolParams.dofsPerNode = 3;
}
SolidMechanicsLagrangeContactBubbleStab::~SolidMechanicsLagrangeContactBubbleStab()
@@ -249,6 +253,7 @@ void SolidMechanicsLagrangeContactBubbleStab::setupSystem( DomainPartition & dom
solution.create( dofManager.numLocalDofs(), MPI_COMM_GEOS );
computeRotationMatrices( domain );
+
}
void SolidMechanicsLagrangeContactBubbleStab::computeRotationMatrices( DomainPartition & domain ) const
@@ -324,10 +329,6 @@ void SolidMechanicsLagrangeContactBubbleStab::assembleSystem( real64 const time,
assembleStabilization( dt, domain, dofManager, localMatrix, localRhs );
assembleContact( dt, domain, dofManager, localMatrix, localRhs );
-
- // parallel_matrix.create( localMatrix.toViewConst(), dofManager.numLocalDofs(), MPI_COMM_GEOS );
- // parallel_matrix.write("newMatrix.mtx");
- // std::cout << localRhs << std::endl;
}
void SolidMechanicsLagrangeContactBubbleStab::assembleStabilization( real64 const dt,
diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseStatistics.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseStatistics.cpp
index 7f44f5f5c16..842c333bafe 100644
--- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseStatistics.cpp
+++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseStatistics.cpp
@@ -29,6 +29,9 @@
#include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp"
#include "physicsSolvers/fluidFlow/kernels/compositional/StatisticsKernel.hpp"
#include "physicsSolvers/fluidFlow/LogLevelsInfo.hpp"
+#include "common/format/table/TableData.hpp"
+#include "common/format/table/TableFormatter.hpp"
+#include "common/format/table/TableLayout.hpp"
namespace geos
@@ -104,41 +107,75 @@ void CompositionalMultiphaseStatistics::registerDataOnMesh( Group & meshBodies )
region.registerWrapper< RegionStatistics >( viewKeyStruct::regionStatisticsString() ).
setRestartFlags( RestartFlags::NO_WRITE );
region.excludeWrappersFromPacking( { viewKeyStruct::regionStatisticsString() } );
- RegionStatistics & regionStatistics = region.getReference< RegionStatistics >( viewKeyStruct::regionStatisticsString() );
+ RegionStatistics & stats = region.getReference< RegionStatistics >( viewKeyStruct::regionStatisticsString() );
- regionStatistics.phasePoreVolume.resizeDimension< 0 >( numPhases );
- regionStatistics.phaseMass.resizeDimension< 0 >( numPhases );
- regionStatistics.trappedPhaseMass.resizeDimension< 0 >( numPhases );
- regionStatistics.immobilePhaseMass.resizeDimension< 0 >( numPhases );
- regionStatistics.componentMass.resizeDimension< 0, 1 >( numPhases, numComps );
+ stats.phasePoreVolume.resizeDimension< 0 >( numPhases );
+ stats.phaseMass.resizeDimension< 0 >( numPhases );
+ stats.trappedPhaseMass.resizeDimension< 0 >( numPhases );
+ stats.immobilePhaseMass.resizeDimension< 0 >( numPhases );
+ stats.componentMass.resizeDimension< 0, 1 >( numPhases, numComps );
- // write output header
if( m_writeCSV > 0 && MpiWrapper::commRank() == 0 )
{
- std::ofstream outputFile( m_outputDir + "/" + regionNames[i] + ".csv" );
- string_view massUnit = units::getSymbol( m_solver->getMassUnit() );
- outputFile <<
- "Time [s],Min pressure [Pa],Average pressure [Pa],Max pressure [Pa],Min delta pressure [Pa],Max delta pressure [Pa]," <<
- "Min temperature [Pa],Average temperature [Pa],Max temperature [Pa],Total dynamic pore volume [rm^3]";
- for( integer ip = 0; ip < numPhases; ++ip )
- outputFile << ",Phase " << ip << " dynamic pore volume [rm^3]";
- for( integer ip = 0; ip < numPhases; ++ip )
- outputFile << ",Phase " << ip << " mass [" << massUnit << "]";
- for( integer ip = 0; ip < numPhases; ++ip )
- outputFile << ",Trapped phase " << ip << " mass (metric 1) [" << massUnit << "]";
- for( integer ip = 0; ip < numPhases; ++ip )
- outputFile << ",Non-trapped phase " << ip << " mass (metric 1) [" << massUnit << "]";
- for( integer ip = 0; ip < numPhases; ++ip )
- outputFile << ",Immobile phase " << ip << " mass (metric 2) [" << massUnit << "]";
- for( integer ip = 0; ip < numPhases; ++ip )
- outputFile << ",Mobile phase " << ip << " mass (metric 2) [" << massUnit << "]";
- for( integer ip = 0; ip < numPhases; ++ip )
+ auto addStatsValue = []( std::ostringstream & pstatsLayout, TableLayout & ptableLayout,
+ string const & description, string_view pmassUnit,
+ integer pnumPhases, integer pnumComps = 0 )
{
- for( integer ic = 0; ic < numComps; ++ic )
- outputFile << ",Component " << ic << " (phase " << ip << ") mass [" << massUnit << "]";
- }
- outputFile << std::endl;
- outputFile.close();
+ for( int ip = 0; ip < pnumPhases; ++ip )
+ {
+ if( pnumComps == 0 )
+ {
+ pstatsLayout << description << " (phase " << ip << ") [" << pmassUnit << "]";
+ }
+ else
+ {
+ for( int ic = 0; ic < pnumComps; ++ic )
+ {
+ pstatsLayout << "Component " << ic << " (phase " << ip << ") mass [" << pmassUnit << "]";
+ if( ic == 0 )
+ {
+ pstatsLayout << ",";
+ }
+ }
+ }
+ if( ip == 0 )
+ {
+ pstatsLayout << ",";
+ }
+ }
+
+ ptableLayout.addToColumns( pstatsLayout.str());
+ pstatsLayout.str( "" );
+ };
+
+ string_view massUnit = units::getSymbol( m_solver->getMassUnit() );
+
+ TableLayout tableLayout( {
+ TableLayout::Column().setName( "Time [s]" ),
+ TableLayout::Column().setName( "Min pressure [Pa]" ),
+ TableLayout::Column().setName( "Average pressure [Pa]" ),
+ TableLayout::Column().setName( "Max pressure [Pa]" ),
+ TableLayout::Column().setName( "Min delta pressure [Pa]" ),
+ TableLayout::Column().setName( "Max delta pressure [Pa]" ),
+ TableLayout::Column().setName( "Min temperature [Pa]" ),
+ TableLayout::Column().setName( "Average temperature [Pa]" ),
+ TableLayout::Column().setName( "Max temperature [Pa]" ),
+ TableLayout::Column().setName( "Total dynamic pore volume [rm^3]" ),
+ TableLayout::Column().setName( GEOS_FMT( "Phase mass [{}] dynamic pore volume [rm^3]", massUnit ) ),
+ } );
+
+ std::ostringstream statsLayout;
+ addStatsValue( statsLayout, tableLayout, "Phase dynamic pore volume", massUnit, numPhases );
+ addStatsValue( statsLayout, tableLayout, "Phase", massUnit, numPhases );
+ addStatsValue( statsLayout, tableLayout, "Trapped phase mass (metric 1)", massUnit, numPhases );
+ addStatsValue( statsLayout, tableLayout, "Non-trapped phase mass (metric 1)", massUnit, numPhases );
+ addStatsValue( statsLayout, tableLayout, "Immobile phase mass (metric 2)", massUnit, numPhases );
+ addStatsValue( statsLayout, tableLayout, "Mobile phase mass (metric 2)", massUnit, numPhases );
+ addStatsValue( statsLayout, tableLayout, "Component", massUnit, numPhases, numComps );
+
+ std::ofstream outputFile( m_outputDir + "/" + regionNames[i] + ".csv" );
+ TableCSVFormatter csvFormatter( tableLayout );
+ outputFile << csvFormatter.headerToString();
}
}
}
@@ -192,27 +229,27 @@ void CompositionalMultiphaseStatistics::computeRegionStatistics( real64 const ti
for( integer i = 0; i < regionNames.size(); ++i )
{
ElementRegionBase & region = elemManager.getRegion( regionNames[i] );
- RegionStatistics & regionStatistics = region.getReference< RegionStatistics >( viewKeyStruct::regionStatisticsString() );
+ RegionStatistics & stats = region.getReference< RegionStatistics >( viewKeyStruct::regionStatisticsString() );
- regionStatistics.averagePressure = 0.0;
- regionStatistics.maxPressure = 0.0;
- regionStatistics.minPressure = LvArray::NumericLimits< real64 >::max;
+ stats.averagePressure = 0.0;
+ stats.maxPressure = 0.0;
+ stats.minPressure = LvArray::NumericLimits< real64 >::max;
- regionStatistics.maxDeltaPressure = -LvArray::NumericLimits< real64 >::max;
- regionStatistics.minDeltaPressure = LvArray::NumericLimits< real64 >::max;
+ stats.maxDeltaPressure = -LvArray::NumericLimits< real64 >::max;
+ stats.minDeltaPressure = LvArray::NumericLimits< real64 >::max;
- regionStatistics.averageTemperature = 0.0;
- regionStatistics.maxTemperature = 0.0;
- regionStatistics.minTemperature = LvArray::NumericLimits< real64 >::max;
+ stats.averageTemperature = 0.0;
+ stats.maxTemperature = 0.0;
+ stats.minTemperature = LvArray::NumericLimits< real64 >::max;
- regionStatistics.totalPoreVolume = 0.0;
- regionStatistics.totalUncompactedPoreVolume = 0.0;
- regionStatistics.phasePoreVolume.setValues< serialPolicy >( 0.0 );
+ stats.totalPoreVolume = 0.0;
+ stats.totalUncompactedPoreVolume = 0.0;
+ stats.phasePoreVolume.setValues< serialPolicy >( 0.0 );
- regionStatistics.phaseMass.setValues< serialPolicy >( 0.0 );
- regionStatistics.trappedPhaseMass.setValues< serialPolicy >( 0.0 );
- regionStatistics.immobilePhaseMass.setValues< serialPolicy >( 0.0 );
- regionStatistics.componentMass.setValues< serialPolicy >( 0.0 );
+ stats.phaseMass.setValues< serialPolicy >( 0.0 );
+ stats.trappedPhaseMass.setValues< serialPolicy >( 0.0 );
+ stats.immobilePhaseMass.setValues< serialPolicy >( 0.0 );
+ stats.componentMass.setValues< serialPolicy >( 0.0 );
}
// Step 2: increment the average/min/max quantities for all the subRegions
@@ -297,48 +334,48 @@ void CompositionalMultiphaseStatistics::computeRegionStatistics( real64 const ti
subRegionComponentMass.toView() );
ElementRegionBase & region = elemManager.getRegion( ElementRegionBase::getParentRegion( subRegion ).getName() );
- RegionStatistics & regionStatistics = region.getReference< RegionStatistics >( viewKeyStruct::regionStatisticsString() );
+ RegionStatistics & stats = region.getReference< RegionStatistics >( viewKeyStruct::regionStatisticsString() );
- regionStatistics.averagePressure += subRegionAvgPresNumerator;
- if( subRegionMinPres < regionStatistics.minPressure )
+ stats.averagePressure += subRegionAvgPresNumerator;
+ if( subRegionMinPres < stats.minPressure )
{
- regionStatistics.minPressure = subRegionMinPres;
+ stats.minPressure = subRegionMinPres;
}
- if( subRegionMaxPres > regionStatistics.maxPressure )
+ if( subRegionMaxPres > stats.maxPressure )
{
- regionStatistics.maxPressure = subRegionMaxPres;
+ stats.maxPressure = subRegionMaxPres;
}
- if( subRegionMinDeltaPres < regionStatistics.minDeltaPressure )
+ if( subRegionMinDeltaPres < stats.minDeltaPressure )
{
- regionStatistics.minDeltaPressure = subRegionMinDeltaPres;
+ stats.minDeltaPressure = subRegionMinDeltaPres;
}
- if( subRegionMaxDeltaPres > regionStatistics.maxDeltaPressure )
+ if( subRegionMaxDeltaPres > stats.maxDeltaPressure )
{
- regionStatistics.maxDeltaPressure = subRegionMaxDeltaPres;
+ stats.maxDeltaPressure = subRegionMaxDeltaPres;
}
- regionStatistics.averageTemperature += subRegionAvgTempNumerator;
- if( subRegionMinTemp < regionStatistics.minTemperature )
+ stats.averageTemperature += subRegionAvgTempNumerator;
+ if( subRegionMinTemp < stats.minTemperature )
{
- regionStatistics.minTemperature = subRegionMinTemp;
+ stats.minTemperature = subRegionMinTemp;
}
- if( subRegionMaxTemp > regionStatistics.maxTemperature )
+ if( subRegionMaxTemp > stats.maxTemperature )
{
- regionStatistics.maxTemperature = subRegionMaxTemp;
+ stats.maxTemperature = subRegionMaxTemp;
}
- regionStatistics.totalUncompactedPoreVolume += subRegionTotalUncompactedPoreVol;
+ stats.totalUncompactedPoreVolume += subRegionTotalUncompactedPoreVol;
for( integer ip = 0; ip < numPhases; ++ip )
{
- regionStatistics.phasePoreVolume[ip] += subRegionPhaseDynamicPoreVol[ip];
- regionStatistics.phaseMass[ip] += subRegionPhaseMass[ip];
- regionStatistics.trappedPhaseMass[ip] += subRegionTrappedPhaseMass[ip];
- regionStatistics.immobilePhaseMass[ip] += subRegionImmobilePhaseMass[ip];
+ stats.phasePoreVolume[ip] += subRegionPhaseDynamicPoreVol[ip];
+ stats.phaseMass[ip] += subRegionPhaseMass[ip];
+ stats.trappedPhaseMass[ip] += subRegionTrappedPhaseMass[ip];
+ stats.immobilePhaseMass[ip] += subRegionImmobilePhaseMass[ip];
for( integer ic = 0; ic < numComps; ++ic )
{
- regionStatistics.componentMass[ip][ic] += subRegionComponentMass[ip][ic];
+ stats.componentMass[ip][ic] += subRegionComponentMass[ip][ic];
}
}
@@ -348,40 +385,40 @@ void CompositionalMultiphaseStatistics::computeRegionStatistics( real64 const ti
for( integer i = 0; i < regionNames.size(); ++i )
{
ElementRegionBase & region = elemManager.getRegion( regionNames[i] );
- RegionStatistics & regionStatistics = region.getReference< RegionStatistics >( viewKeyStruct::regionStatisticsString() );
-
- regionStatistics.minPressure = MpiWrapper::min( regionStatistics.minPressure );
- regionStatistics.maxPressure = MpiWrapper::max( regionStatistics.maxPressure );
- regionStatistics.minDeltaPressure = MpiWrapper::min( regionStatistics.minDeltaPressure );
- regionStatistics.maxDeltaPressure = MpiWrapper::max( regionStatistics.maxDeltaPressure );
- regionStatistics.minTemperature = MpiWrapper::min( regionStatistics.minTemperature );
- regionStatistics.maxTemperature = MpiWrapper::max( regionStatistics.maxTemperature );
- regionStatistics.totalUncompactedPoreVolume = MpiWrapper::sum( regionStatistics.totalUncompactedPoreVolume );
- regionStatistics.totalPoreVolume = 0.0;
+ RegionStatistics & stats = region.getReference< RegionStatistics >( viewKeyStruct::regionStatisticsString() );
+
+ stats.minPressure = MpiWrapper::min( stats.minPressure );
+ stats.maxPressure = MpiWrapper::max( stats.maxPressure );
+ stats.minDeltaPressure = MpiWrapper::min( stats.minDeltaPressure );
+ stats.maxDeltaPressure = MpiWrapper::max( stats.maxDeltaPressure );
+ stats.minTemperature = MpiWrapper::min( stats.minTemperature );
+ stats.maxTemperature = MpiWrapper::max( stats.maxTemperature );
+ stats.totalUncompactedPoreVolume = MpiWrapper::sum( stats.totalUncompactedPoreVolume );
+ stats.totalPoreVolume = 0.0;
for( integer ip = 0; ip < numPhases; ++ip )
{
- regionStatistics.phasePoreVolume[ip] = MpiWrapper::sum( regionStatistics.phasePoreVolume[ip] );
- regionStatistics.phaseMass[ip] = MpiWrapper::sum( regionStatistics.phaseMass[ip] );
- regionStatistics.trappedPhaseMass[ip] = MpiWrapper::sum( regionStatistics.trappedPhaseMass[ip] );
- regionStatistics.immobilePhaseMass[ip] = MpiWrapper::sum( regionStatistics.immobilePhaseMass[ip] );
- regionStatistics.totalPoreVolume += regionStatistics.phasePoreVolume[ip];
+ stats.phasePoreVolume[ip] = MpiWrapper::sum( stats.phasePoreVolume[ip] );
+ stats.phaseMass[ip] = MpiWrapper::sum( stats.phaseMass[ip] );
+ stats.trappedPhaseMass[ip] = MpiWrapper::sum( stats.trappedPhaseMass[ip] );
+ stats.immobilePhaseMass[ip] = MpiWrapper::sum( stats.immobilePhaseMass[ip] );
+ stats.totalPoreVolume += stats.phasePoreVolume[ip];
for( integer ic = 0; ic < numComps; ++ic )
{
- regionStatistics.componentMass[ip][ic] = MpiWrapper::sum( regionStatistics.componentMass[ip][ic] );
+ stats.componentMass[ip][ic] = MpiWrapper::sum( stats.componentMass[ip][ic] );
}
}
- regionStatistics.averagePressure = MpiWrapper::sum( regionStatistics.averagePressure );
- regionStatistics.averageTemperature = MpiWrapper::sum( regionStatistics.averageTemperature );
- if( regionStatistics.totalUncompactedPoreVolume > 0 )
+ stats.averagePressure = MpiWrapper::sum( stats.averagePressure );
+ stats.averageTemperature = MpiWrapper::sum( stats.averageTemperature );
+ if( stats.totalUncompactedPoreVolume > 0 )
{
- float invTotalUncompactedPoreVolume = 1.0 / regionStatistics.totalUncompactedPoreVolume;
- regionStatistics.averagePressure *= invTotalUncompactedPoreVolume;
- regionStatistics.averageTemperature *= invTotalUncompactedPoreVolume;
+ float invTotalUncompactedPoreVolume = 1.0 / stats.totalUncompactedPoreVolume;
+ stats.averagePressure *= invTotalUncompactedPoreVolume;
+ stats.averageTemperature *= invTotalUncompactedPoreVolume;
}
else
{
- regionStatistics.averagePressure = 0.0;
- regionStatistics.averageTemperature = 0.0;
+ stats.averagePressure = 0.0;
+ stats.averageTemperature = 0.0;
GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::Statistics,
GEOS_FMT( "{}, {}: Cannot compute average pressure because region pore volume is zero.", getName(), regionNames[i] ) );
}
@@ -392,79 +429,108 @@ void CompositionalMultiphaseStatistics::computeRegionStatistics( real64 const ti
array1d< real64 > mobilePhaseMass( numPhases );
for( integer ip = 0; ip < numPhases; ++ip )
{
- nonTrappedPhaseMass[ip] = regionStatistics.phaseMass[ip] - regionStatistics.trappedPhaseMass[ip];
- mobilePhaseMass[ip] = regionStatistics.phaseMass[ip] - regionStatistics.immobilePhaseMass[ip];
+ nonTrappedPhaseMass[ip] = stats.phaseMass[ip] - stats.trappedPhaseMass[ip];
+ mobilePhaseMass[ip] = stats.phaseMass[ip] - stats.immobilePhaseMass[ip];
}
string_view massUnit = units::getSymbol( m_solver->getMassUnit() );
- string statPrefix = GEOS_FMT( "{}, {} (time {} s):", getName(), regionNames[i], time );
- GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::Statistics,
- GEOS_FMT( "{} Pressure (min, average, max): {}, {}, {} Pa",
- statPrefix, regionStatistics.minPressure, regionStatistics.averagePressure, regionStatistics.maxPressure ) );
- GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::Statistics,
- GEOS_FMT( "{} Delta pressure (min, max): {}, {} Pa",
- statPrefix, regionStatistics.minDeltaPressure, regionStatistics.maxDeltaPressure ) );
- GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::Statistics,
- GEOS_FMT( "{} Temperature (min, average, max): {}, {}, {} K",
- statPrefix, regionStatistics.minTemperature, regionStatistics.averageTemperature,
- regionStatistics.maxTemperature ) );
- GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::Statistics,
- GEOS_FMT( "{} Total dynamic pore volume: {} rm^3",
- statPrefix, regionStatistics.totalPoreVolume ) );
- GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::Statistics,
- GEOS_FMT( "{} Phase dynamic pore volume: {} rm^3",
- statPrefix, regionStatistics.phasePoreVolume ) );
- GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::Statistics,
- GEOS_FMT( "{} Phase mass: {} {}",
- statPrefix, regionStatistics.phaseMass, massUnit ) );
-
- // metric 1: trapping computed with the Land trapping coefficient
- GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::Statistics,
- GEOS_FMT( "{} Trapped phase mass (metric 1): {} {}",
- statPrefix, regionStatistics.trappedPhaseMass, massUnit ) );
- GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::Statistics,
- GEOS_FMT( "{} Non-trapped phase mass (metric 1): {} {}",
- statPrefix, nonTrappedPhaseMass, massUnit ) );
-
- // metric 2: immobile phase mass computed with a threshold on relative permeability
- GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::Statistics,
- GEOS_FMT( "{} Immobile phase mass (metric 2): {} {}",
- statPrefix, regionStatistics.immobilePhaseMass, massUnit ) );
- GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::Statistics,
- GEOS_FMT( "{} Mobile phase mass (metric 2): {} {}",
- statPrefix, mobilePhaseMass, massUnit ) );
-
- GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::Statistics,
- GEOS_FMT( "{} Component mass: {} {}",
- statPrefix, regionStatistics.componentMass, massUnit ) );
- if( m_writeCSV > 0 && MpiWrapper::commRank() == 0 )
+ std::vector< string > phaseCompName;
+ phaseCompName.reserve( numPhases*numComps );
+ std::vector< string > massValues;
+ phaseCompName.reserve( numPhases*numComps );
+
+ ConstitutiveManager const & constitutiveManager = this->getGroupByPath< ConstitutiveManager >( "/Problem/domain/Constitutive" );
+ MultiFluidBase const & fluid = constitutiveManager.getGroup< MultiFluidBase >( m_solver->referenceFluidModelName() );
+ auto const phaseNames = fluid.phaseNames();
+ auto const componentNames = fluid.componentNames();
+ for( integer ip = 0; ip < numPhases; ++ip )
{
- std::ofstream outputFile( m_outputDir + "/" + regionNames[i] + ".csv", std::ios_base::app );
- outputFile << time << "," << regionStatistics.minPressure << "," << regionStatistics.averagePressure << "," << regionStatistics.maxPressure << "," <<
- regionStatistics.minDeltaPressure << "," << regionStatistics.maxDeltaPressure << "," << regionStatistics.minTemperature << "," <<
- regionStatistics.averageTemperature << "," << regionStatistics.maxTemperature << "," << regionStatistics.totalPoreVolume;
- for( integer ip = 0; ip < numPhases; ++ip )
- outputFile << "," << regionStatistics.phasePoreVolume[ip];
- for( integer ip = 0; ip < numPhases; ++ip )
- outputFile << "," << regionStatistics.phaseMass[ip];
- for( integer ip = 0; ip < numPhases; ++ip )
- outputFile << "," << regionStatistics.trappedPhaseMass[ip];
- for( integer ip = 0; ip < numPhases; ++ip )
- outputFile << "," << nonTrappedPhaseMass[ip];
- for( integer ip = 0; ip < numPhases; ++ip )
- outputFile << "," << regionStatistics.immobilePhaseMass[ip];
- for( integer ip = 0; ip < numPhases; ++ip )
- outputFile << "," << mobilePhaseMass[ip];
- for( integer ip = 0; ip < numPhases; ++ip )
+ for( integer ic = 0; ic < numComps; ++ic )
{
- for( integer ic = 0; ic < numComps; ++ic )
- outputFile << "," << regionStatistics.componentMass[ip][ic];
+ std::stringstream ss;
+ ss << phaseNames[ip]<< ", " < 0 && MpiWrapper::commRank() == 0 )
+ {
+ TableData tableData;
+ tableData.addRow( time, stats.minPressure, stats.averagePressure, stats.maxPressure, stats.minDeltaPressure, stats.maxDeltaPressure,
+ stats.minTemperature, stats.averageTemperature, stats.maxTemperature, stats.totalPoreVolume,
+ stringutilities::joinLambda( stats.phasePoreVolume, "\n", []( auto data ) { return data[0]; } ),
+ stringutilities::joinLambda( stats.phaseMass, "\n", []( auto data ) { return data[0]; } ),
+ stringutilities::joinLambda( stats.trappedPhaseMass, "\n", []( auto value ) { return value[0]; } ),
+ stringutilities::joinLambda( nonTrappedPhaseMass, "\n", []( auto value ) { return value[0]; } ),
+ stringutilities::joinLambda( stats.immobilePhaseMass, "\n", []( auto value ) { return value[0]; } ),
+ stringutilities::joinLambda( mobilePhaseMass, "\n", []( auto value ) { return value[0]; } ),
+ stringutilities::join( massValues, '\n' ) );
+
+ std::ofstream outputFile( m_outputDir + "/" + regionNames[i] + ".csv", std::ios_base::app );
+ TableCSVFormatter const csvOutput;
+ outputFile << csvOutput.dataToString( tableData );
outputFile.close();
}
}
+
}
void CompositionalMultiphaseStatistics::computeCFLNumbers( real64 const time,
diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseStatistics.hpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseStatistics.hpp
index bee1a2468a4..f8f9afafa90 100644
--- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseStatistics.hpp
+++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseStatistics.hpp
@@ -118,8 +118,6 @@ class CompositionalMultiphaseStatistics : public FieldStatisticsBase< Compositio
array1d< real64 > immobilePhaseMass;
/// region component mass
array2d< real64 > componentMass;
-
-
};
/**
diff --git a/src/coreComponents/physicsSolvers/fluidFlow/LogLevelsInfo.hpp b/src/coreComponents/physicsSolvers/fluidFlow/LogLevelsInfo.hpp
index c42ac620388..0f8c9eb60c3 100644
--- a/src/coreComponents/physicsSolvers/fluidFlow/LogLevelsInfo.hpp
+++ b/src/coreComponents/physicsSolvers/fluidFlow/LogLevelsInfo.hpp
@@ -48,6 +48,25 @@ struct Statistics
static constexpr std::string_view getDescription() { return "Print statistics"; }
};
+struct AggregatedSourceFluxStats
+{
+ static constexpr int getMinLogLevel() { return 1; }
+ static constexpr std::string_view getDescription() { return "Print aggregated statistics of all source fluxes in a mesh"; }
+};
+
+struct DetailedSourceFluxStats
+{
+ static constexpr int getMinLogLevel() { return 2; }
+ static constexpr std::string_view getDescription() { return "Print statistics for each source flux in a mesh"; }
+};
+
+struct DetailedRegionsSourceFluxStats
+{
+ static constexpr int getMinLogLevel() { return 3; }
+ static constexpr std::string_view getDescription() { return "Print statistics for each source flux in each regions"; }
+};
+
+
/// @endcond
///@}
diff --git a/src/coreComponents/physicsSolvers/fluidFlow/SinglePhaseStatistics.cpp b/src/coreComponents/physicsSolvers/fluidFlow/SinglePhaseStatistics.cpp
index 26ed404707d..b92701b6ee1 100644
--- a/src/coreComponents/physicsSolvers/fluidFlow/SinglePhaseStatistics.cpp
+++ b/src/coreComponents/physicsSolvers/fluidFlow/SinglePhaseStatistics.cpp
@@ -27,6 +27,9 @@
#include "physicsSolvers/fluidFlow/SinglePhaseBaseFields.hpp"
#include "physicsSolvers/fluidFlow/kernels/singlePhase/StatisticsKernel.hpp"
#include "physicsSolvers/fluidFlow/LogLevelsInfo.hpp"
+#include "common/format/table/TableData.hpp"
+#include "common/format/table/TableFormatter.hpp"
+#include "common/format/table/TableLayout.hpp"
namespace geos
{
@@ -101,28 +104,27 @@ void SinglePhaseStatistics::computeRegionStatistics( real64 const time,
arrayView1d< string const > const & regionNames ) const
{
GEOS_MARK_FUNCTION;
-
// Step 1: initialize the average/min/max quantities
ElementRegionManager & elemManager = mesh.getElemManager();
for( integer i = 0; i < regionNames.size(); ++i )
{
ElementRegionBase & region = elemManager.getRegion( regionNames[i] );
- RegionStatistics & regionStatistics = region.getReference< RegionStatistics >( viewKeyStruct::regionStatisticsString() );
+ RegionStatistics & stats = region.getReference< RegionStatistics >( viewKeyStruct::regionStatisticsString() );
- regionStatistics.averagePressure = 0.0;
- regionStatistics.maxPressure = -LvArray::NumericLimits< real64 >::max;
- regionStatistics.minPressure = LvArray::NumericLimits< real64 >::max;
+ stats.averagePressure = 0.0;
+ stats.maxPressure = -LvArray::NumericLimits< real64 >::max;
+ stats.minPressure = LvArray::NumericLimits< real64 >::max;
- regionStatistics.maxDeltaPressure = -LvArray::NumericLimits< real64 >::max;
- regionStatistics.minDeltaPressure = LvArray::NumericLimits< real64 >::max;
+ stats.maxDeltaPressure = -LvArray::NumericLimits< real64 >::max;
+ stats.minDeltaPressure = LvArray::NumericLimits< real64 >::max;
- regionStatistics.averageTemperature = 0.0;
- regionStatistics.maxTemperature = -LvArray::NumericLimits< real64 >::max;
- regionStatistics.minTemperature = LvArray::NumericLimits< real64 >::max;
+ stats.averageTemperature = 0.0;
+ stats.maxTemperature = -LvArray::NumericLimits< real64 >::max;
+ stats.minTemperature = LvArray::NumericLimits< real64 >::max;
- regionStatistics.totalPoreVolume = 0.0;
- regionStatistics.totalUncompactedPoreVolume = 0.0;
- regionStatistics.totalMass = 0.0;
+ stats.totalPoreVolume = 0.0;
+ stats.totalUncompactedPoreVolume = 0.0;
+ stats.totalMass = 0.0;
}
// Step 2: increment the average/min/max quantities for all the subRegions
@@ -181,101 +183,103 @@ void SinglePhaseStatistics::computeRegionStatistics( real64 const time,
subRegionTotalMass );
ElementRegionBase & region = elemManager.getRegion( ElementRegionBase::getParentRegion( subRegion ).getName() );
- RegionStatistics & regionStatistics = region.getReference< RegionStatistics >( viewKeyStruct::regionStatisticsString() );
+ RegionStatistics & stats = region.getReference< RegionStatistics >( viewKeyStruct::regionStatisticsString() );
- regionStatistics.averagePressure += subRegionAvgPresNumerator;
- if( subRegionMinPres < regionStatistics.minPressure )
+ stats.averagePressure += subRegionAvgPresNumerator;
+ if( subRegionMinPres < stats.minPressure )
{
- regionStatistics.minPressure = subRegionMinPres;
+ stats.minPressure = subRegionMinPres;
}
- if( subRegionMaxPres > regionStatistics.maxPressure )
+ if( subRegionMaxPres > stats.maxPressure )
{
- regionStatistics.maxPressure = subRegionMaxPres;
+ stats.maxPressure = subRegionMaxPres;
}
- if( subRegionMinDeltaPres < regionStatistics.minDeltaPressure )
+ if( subRegionMinDeltaPres < stats.minDeltaPressure )
{
- regionStatistics.minDeltaPressure = subRegionMinDeltaPres;
+ stats.minDeltaPressure = subRegionMinDeltaPres;
}
- if( subRegionMaxDeltaPres > regionStatistics.maxDeltaPressure )
+ if( subRegionMaxDeltaPres > stats.maxDeltaPressure )
{
- regionStatistics.maxDeltaPressure = subRegionMaxDeltaPres;
+ stats.maxDeltaPressure = subRegionMaxDeltaPres;
}
- regionStatistics.averageTemperature += subRegionAvgTempNumerator;
- if( subRegionMinTemp < regionStatistics.minTemperature )
+ stats.averageTemperature += subRegionAvgTempNumerator;
+ if( subRegionMinTemp < stats.minTemperature )
{
- regionStatistics.minTemperature = subRegionMinTemp;
+ stats.minTemperature = subRegionMinTemp;
}
- if( subRegionMaxTemp > regionStatistics.maxTemperature )
+ if( subRegionMaxTemp > stats.maxTemperature )
{
- regionStatistics.maxTemperature = subRegionMaxTemp;
+ stats.maxTemperature = subRegionMaxTemp;
}
- regionStatistics.totalUncompactedPoreVolume += subRegionTotalUncompactedPoreVol;
- regionStatistics.totalPoreVolume += subRegionTotalPoreVol;
- regionStatistics.totalMass += subRegionTotalMass;
+ stats.totalUncompactedPoreVolume += subRegionTotalUncompactedPoreVol;
+ stats.totalPoreVolume += subRegionTotalPoreVol;
+ stats.totalMass += subRegionTotalMass;
} );
// Step 3: synchronize the results over the MPI ranks
for( integer i = 0; i < regionNames.size(); ++i )
{
ElementRegionBase & region = elemManager.getRegion( regionNames[i] );
- RegionStatistics & regionStatistics = region.getReference< RegionStatistics >( viewKeyStruct::regionStatisticsString() );
+ RegionStatistics & stats = region.getReference< RegionStatistics >( viewKeyStruct::regionStatisticsString() );
- regionStatistics.minPressure = MpiWrapper::min( regionStatistics.minPressure );
- regionStatistics.averagePressure = MpiWrapper::sum( regionStatistics.averagePressure );
- regionStatistics.maxPressure = MpiWrapper::max( regionStatistics.maxPressure );
+ stats.minPressure = MpiWrapper::min( stats.minPressure );
+ stats.averagePressure = MpiWrapper::sum( stats.averagePressure );
+ stats.maxPressure = MpiWrapper::max( stats.maxPressure );
- regionStatistics.minDeltaPressure = MpiWrapper::min( regionStatistics.minDeltaPressure );
- regionStatistics.maxDeltaPressure = MpiWrapper::max( regionStatistics.maxDeltaPressure );
+ stats.minDeltaPressure = MpiWrapper::min( stats.minDeltaPressure );
+ stats.maxDeltaPressure = MpiWrapper::max( stats.maxDeltaPressure );
- regionStatistics.minTemperature = MpiWrapper::min( regionStatistics.minTemperature );
- regionStatistics.averageTemperature = MpiWrapper::sum( regionStatistics.averageTemperature );
- regionStatistics.maxTemperature = MpiWrapper::max( regionStatistics.maxTemperature );
+ stats.minTemperature = MpiWrapper::min( stats.minTemperature );
+ stats.averageTemperature = MpiWrapper::sum( stats.averageTemperature );
+ stats.maxTemperature = MpiWrapper::max( stats.maxTemperature );
- regionStatistics.totalUncompactedPoreVolume = MpiWrapper::sum( regionStatistics.totalUncompactedPoreVolume );
- regionStatistics.totalPoreVolume = MpiWrapper::sum( regionStatistics.totalPoreVolume );
- regionStatistics.totalMass = MpiWrapper::sum( regionStatistics.totalMass );
+ stats.totalUncompactedPoreVolume = MpiWrapper::sum( stats.totalUncompactedPoreVolume );
+ stats.totalPoreVolume = MpiWrapper::sum( stats.totalPoreVolume );
+ stats.totalMass = MpiWrapper::sum( stats.totalMass );
- if( regionStatistics.totalUncompactedPoreVolume > 0 )
+ if( stats.totalUncompactedPoreVolume > 0 )
{
- float invTotalUncompactedPoreVolume = 1.0 / regionStatistics.totalUncompactedPoreVolume;
- regionStatistics.averagePressure *= invTotalUncompactedPoreVolume;
- regionStatistics.averageTemperature *= invTotalUncompactedPoreVolume;
+ float invTotalUncompactedPoreVolume = 1.0 / stats.totalUncompactedPoreVolume;
+ stats.averagePressure *= invTotalUncompactedPoreVolume;
+ stats.averageTemperature *= invTotalUncompactedPoreVolume;
}
else
{
- regionStatistics.averagePressure = 0.0;
- regionStatistics.averageTemperature = 0.0;
+ stats.averagePressure = 0.0;
+ stats.averageTemperature = 0.0;
GEOS_WARNING( GEOS_FMT( "{}, {}: Cannot compute average pressure & temperature because region pore volume is zero.", getName(), regionNames[i] ) );
}
- string statPrefix = GEOS_FMT( "{}, {} (time {} s):", getName(), regionNames[i], time );
- GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::Statistics,
- GEOS_FMT( "{} Pressure (min, average, max): {}, {}, {} Pa",
- statPrefix, regionStatistics.minPressure, regionStatistics.averagePressure, regionStatistics.maxPressure ) );
- GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::Statistics,
- GEOS_FMT( "{} Delta pressure (min, max): {}, {} Pa",
- statPrefix, regionStatistics.minDeltaPressure, regionStatistics.maxDeltaPressure ) );
- GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::Statistics,
- GEOS_FMT( "{} Temperature (min, average, max): {}, {}, {} K",
- statPrefix, regionStatistics.minTemperature, regionStatistics.averageTemperature,
- regionStatistics.maxTemperature ) );
- GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::Statistics,
- GEOS_FMT( "{} Total dynamic pore volume: {} rm^3",
- statPrefix, regionStatistics.totalPoreVolume ) );
- GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::Statistics,
- GEOS_FMT( "{} Total fluid mass: {} kg",
- statPrefix, regionStatistics.totalMass ) );
+ string_view massUnit = units::getSymbol( m_solver->getMassUnit() );
+
+ TableData singPhaseStatsData;
+ singPhaseStatsData.addRow( "Pressure[Pa]", stats.minPressure, stats.averagePressure, stats.maxPressure );
+ singPhaseStatsData.addRow( "Delta pressure [Pa]", stats.minDeltaPressure, "/", stats.maxDeltaPressure );
+ singPhaseStatsData.addRow( "Temperature [K]", stats.minTemperature, stats.averageTemperature, stats.maxTemperature );
+ singPhaseStatsData.addSeparator();
+ singPhaseStatsData.addSeparator();
+ singPhaseStatsData.addRow( "statistics", CellType::MergeNext, CellType::MergeNext, "value" );
+ singPhaseStatsData.addSeparator();
+
+ singPhaseStatsData.addRow( "Total dynamic pore volume [rm^3]", CellType::MergeNext, CellType::MergeNext, stats.totalPoreVolume );
+ singPhaseStatsData.addSeparator();
+ singPhaseStatsData.addRow( GEOS_FMT( "Total fluid mass [{}]", massUnit ), CellType::MergeNext, CellType::MergeNext, stats.totalMass );
+
+ string const title = GEOS_FMT( "{}, {} (time {} s):", getName(), regionNames[i], time );
+ TableLayout const singPhaseStatsLayout( title, { "statistics", "min", "average", "max" } );
+ TableTextFormatter tableFormatter( singPhaseStatsLayout );
+ GEOS_LOG_RANK_0( tableFormatter.toString( singPhaseStatsData ) );
if( m_writeCSV > 0 && MpiWrapper::commRank() == 0 )
{
std::ofstream outputFile( m_outputDir + "/" + regionNames[i] + ".csv", std::ios_base::app );
- outputFile << time << "," << regionStatistics.minPressure << "," << regionStatistics.averagePressure << "," << regionStatistics.maxPressure << "," <<
- regionStatistics.minDeltaPressure << "," << regionStatistics.maxDeltaPressure << "," <<
- regionStatistics.minTemperature << "," << regionStatistics.averageTemperature << "," << regionStatistics.maxTemperature << "," <<
- regionStatistics.totalPoreVolume << "," << regionStatistics.totalMass << std::endl;
+ outputFile << time << "," << stats.minPressure << "," << stats.averagePressure << "," << stats.maxPressure << "," <<
+ stats.minDeltaPressure << "," << stats.maxDeltaPressure << "," <<
+ stats.minTemperature << "," << stats.averageTemperature << "," << stats.maxTemperature << "," <<
+ stats.totalPoreVolume << "," << stats.totalMass << std::endl;
outputFile.close();
}
}
diff --git a/src/coreComponents/physicsSolvers/fluidFlow/SourceFluxStatistics.cpp b/src/coreComponents/physicsSolvers/fluidFlow/SourceFluxStatistics.cpp
index 6c8a1e36cb3..2373d3dd112 100644
--- a/src/coreComponents/physicsSolvers/fluidFlow/SourceFluxStatistics.cpp
+++ b/src/coreComponents/physicsSolvers/fluidFlow/SourceFluxStatistics.cpp
@@ -22,6 +22,7 @@
#include "fieldSpecification/SourceFluxBoundaryCondition.hpp"
#include "fieldSpecification/FieldSpecificationManager.hpp"
#include "LvArray/src/tensorOps.hpp"
+#include "physicsSolvers/fluidFlow/LogLevelsInfo.hpp"
namespace geos
{
@@ -45,6 +46,10 @@ SourceFluxStatsAggregator::SourceFluxStatsAggregator( const string & name,
setDescription( GEOS_FMT( "Name(s) array of the {0}(s) for which we want the statistics. "
"Use \"*\" to target all {0}.",
SourceFluxBoundaryCondition::catalogName() ) );
+
+ addLogLevel< logInfo::DetailedSourceFluxStats >();
+ addLogLevel< logInfo::DetailedRegionsSourceFluxStats >();
+ addLogLevel< logInfo::AggregatedSourceFluxStats >();
}
void SourceFluxStatsAggregator::postInputInitialization()
@@ -79,14 +84,34 @@ void SourceFluxStatsAggregator::postInputInitialization()
Wrapper< SourceFluxStatsAggregator::WrappedStats > &
SourceFluxStatsAggregator::registerWrappedStats( Group & group,
string_view fluxName,
- string_view elementSetName )
+ string_view elementSetName,
+ string_array & filenames )
{
string const wrapperName = getStatWrapperName( fluxName );
Wrapper< WrappedStats > & statsWrapper = group.registerWrapper< WrappedStats >( wrapperName );
statsWrapper.setRestartFlags( RestartFlags::NO_WRITE );
- statsWrapper.reference().setTarget( getName(), fluxName );
- writeStatsToCSV( elementSetName, statsWrapper.reference(), true );
+ WrappedStats & stats = statsWrapper.reference();
+ stats.setTarget( getName(), fluxName );
+
+ { //tableLayout initialisation
+ string_view massUnit = units::getSymbol( m_solver->getMassUnit() );
+
+ string const logMassColumn = GEOS_FMT( "Produced mass [{}]", massUnit );
+ string const logRateColumn = GEOS_FMT( "Production rate [{}]", massUnit );
+ TableLayout statsLogLayout( "", { "region", logMassColumn, logRateColumn } );
+ m_logLayout = statsLogLayout;
+
+ string const csvMassColumn = GEOS_FMT( "Produced mass [{}]", massUnit );
+ string const csvRateColumn = GEOS_FMT( "Production rate [{}]", massUnit );
+
+ filenames.emplace_back( GEOS_FMT( "{}/{}_{}_{}.csv",
+ m_outputDir,
+ stats.getAggregatorName(), stats.getFluxName(), elementSetName ) );
+
+ TableLayout statsCSVLayout( "", {"Time [s]", "Element Count", csvMassColumn, csvRateColumn} );
+ m_csvLayout = statsCSVLayout;
+ }
return statsWrapper;
}
@@ -101,22 +126,28 @@ void SourceFluxStatsAggregator::registerDataOnMesh( Group & meshBodies )
MeshLevel & mesh,
arrayView1d< string const > const & )
{
- registerWrappedStats( mesh, viewKeyStruct::fluxSetWrapperString(), viewKeyStruct::allRegionWrapperString() );
+ registerWrappedStats( mesh,
+ viewKeyStruct::fluxSetWrapperString(),
+ viewKeyStruct::allRegionWrapperString(),
+ m_allRegionWrapperFluxFilename );
for( string const & fluxName : m_fluxNames )
{
- registerWrappedStats( mesh, fluxName, viewKeyStruct::allRegionWrapperString() );
+ registerWrappedStats( mesh,
+ fluxName,
+ viewKeyStruct::allRegionWrapperString(),
+ m_allRegionFluxsfilename );
mesh.getElemManager().forElementRegions( [&]( ElementRegionBase & region )
{
Wrapper< WrappedStats > & regionStatsWrapper =
- registerWrappedStats( region, fluxName, region.getName() );
+ registerWrappedStats( region, fluxName, region.getName(), m_regionsfilename );
region.excludeWrappersFromPacking( { regionStatsWrapper.getName() } );
region.forElementSubRegions( [&]( ElementSubRegionBase & subRegion )
{
Wrapper< WrappedStats > & subRegionStatsWrapper =
- registerWrappedStats( subRegion, fluxName, subRegion.getName() );
+ registerWrappedStats( subRegion, fluxName, subRegion.getName(), m_subRegionsfilename );
subRegion.excludeWrappersFromPacking( { subRegionStatsWrapper.getName() } );
} );
} );
@@ -124,61 +155,59 @@ void SourceFluxStatsAggregator::registerDataOnMesh( Group & meshBodies )
} );
}
-void SourceFluxStatsAggregator::writeStatsToLog( integer minLogLevel,
- string_view elementSetName,
- WrappedStats const & wrappedStats )
+void SourceFluxStatsAggregator::gatherStatsForLog( bool logLevelActive,
+ string_view elementSetName,
+ TableData & tableData,
+ WrappedStats const & wrappedStats )
{
- if( getLogLevel() >= minLogLevel && logger::internal::rank == 0 )
+ if( logLevelActive && logger::internal::rank == 0 )
{
- GEOS_LOG_RANK( GEOS_FMT( "{} {} (of {}, in {}): Producing on {} elements",
- catalogName(), getName(), wrappedStats.getFluxName(), elementSetName,
- wrappedStats.stats().m_elementCount ) );
-
- // we want to format differently if we have got multiple phases or not
- string_view massUnit = units::getSymbol( m_solver->getMassUnit() );
if( wrappedStats.stats().m_producedMass.size() == 1 )
{
- GEOS_LOG_RANK( GEOS_FMT( "{} {} (of {}, in {}): Produced mass = {} {}",
- catalogName(), getName(), wrappedStats.getFluxName(), elementSetName,
- wrappedStats.stats().m_producedMass[0], massUnit ) );
- GEOS_LOG_RANK( GEOS_FMT( "{} {} (of {}, in {}): Production rate = {} {}/s",
- catalogName(), getName(), wrappedStats.getFluxName(), elementSetName,
- wrappedStats.stats().m_productionRate[0], massUnit ) );
+ tableData.addRow( elementSetName,
+ GEOS_FMT( "{}", wrappedStats.stats().m_producedMass[0] ),
+ GEOS_FMT( "{}", wrappedStats.stats().m_productionRate[0] ) );
}
else
{
- GEOS_LOG_RANK( GEOS_FMT( "{} {} (of {}, in {}): Produced mass = {} {}",
- catalogName(), getName(), wrappedStats.getFluxName(), elementSetName,
- wrappedStats.stats().m_producedMass, massUnit ) );
- GEOS_LOG_RANK( GEOS_FMT( "{} {} (of {}, in {}): Production rate = {} {}/s",
- catalogName(), getName(), wrappedStats.getFluxName(), elementSetName,
- wrappedStats.stats().m_productionRate, massUnit ) );
+ tableData.addRow( elementSetName,
+ GEOS_FMT( "{}", wrappedStats.stats().m_producedMass ),
+ GEOS_FMT( "{}", wrappedStats.stats().m_productionRate ) );
}
}
}
-void SourceFluxStatsAggregator::writeStatsToCSV( string_view elementSetName, WrappedStats const & stats,
- bool writeHeader )
+void SourceFluxStatsAggregator::outputStatsToLog( bool logLevelActive, string_view elementSetName, TableData const & tableMeshData )
{
- if( m_writeCSV > 0 && MpiWrapper::commRank() == 0 )
+ if( logLevelActive && logger::internal::rank == 0 )
{
- string const fileName = GEOS_FMT( "{}/{}_{}_{}.csv",
- m_outputDir,
- stats.getAggregatorName(), stats.getFluxName(), elementSetName );
- std::ofstream outputFile( fileName,
- writeHeader ? std::ios_base::out : std::ios_base::app );
- if( writeHeader )
- {
- outputFile << GEOS_FMT( "Time [s],Element Count,Producted Mass [{0}],Production Rate [{0}/s]",
- units::getSymbol( m_solver->getMassUnit() ) ) << std::endl;
- }
- else
+ m_logLayout.setTitle( GEOS_FMT( "Source flux statistics in {}", elementSetName ));
+ TableTextFormatter const tableStatFormatter( m_logLayout );
+ GEOS_LOG_RANK( tableStatFormatter.toString( tableMeshData ) );
+ }
+}
+void SourceFluxStatsAggregator::outputStatsToCSV( string_array const & filenames, TableData & csvData )
+{
+ if( m_writeCSV > 0 && logger::internal::rank == 0 )
+ {
+ for( auto const & filename : filenames )
{
- outputFile << GEOS_FMT( "{},{},{},{}",
- stats.getStatsPeriodStart(), stats.stats().m_elementCount,
- stats.stats().m_producedMass, stats.stats().m_productionRate ) << std::endl;
+ std::ofstream outputFile( filename );
+
+ TableCSVFormatter const tableStatFormatter( m_csvLayout );
+ outputFile << tableStatFormatter.toString( csvData );
+ outputFile.close();
}
- outputFile.close();
+ csvData.clear();
+ }
+}
+
+void SourceFluxStatsAggregator::gatherStatsForCSV( TableData & tableData, WrappedStats const & stats )
+{
+ if( m_writeCSV > 0 && MpiWrapper::commRank() == 0 )
+ {
+ tableData.addRow( stats.getStatsPeriodStart(), stats.stats().m_elementCount,
+ stats.stats().m_producedMass, stats.stats().m_productionRate );
}
}
@@ -189,16 +218,21 @@ bool SourceFluxStatsAggregator::execute( real64 const GEOS_UNUSED_PARAM( time_n
real64 const GEOS_UNUSED_PARAM( eventProgress ),
DomainPartition & domain )
{
+ bool const fluxMeshesStats = isLogLevelActive< logInfo::AggregatedSourceFluxStats >( getLogLevel() );
+ bool const fluxesStats = isLogLevelActive< logInfo::DetailedSourceFluxStats >( getLogLevel() );
+ bool const regionsStats = isLogLevelActive< logInfo::DetailedRegionsSourceFluxStats >( getLogLevel() );
forMeshLevelStatsWrapper( domain,
[&] ( MeshLevel & meshLevel, WrappedStats & meshLevelStats )
{
+ TableData tableMeshData;
+ TableData csvData;
meshLevelStats.stats() = StatData();
-
forAllFluxStatsWrappers( meshLevel,
[&] ( MeshLevel &, WrappedStats & fluxStats )
{
fluxStats.stats() = StatData();
-
+ TableData tableFluxData;
+ TableData tableRegionsData;
forAllRegionStatsWrappers( meshLevel, fluxStats.getFluxName(),
[&] ( ElementRegionBase & region, WrappedStats & regionStats )
{
@@ -210,21 +244,31 @@ bool SourceFluxStatsAggregator::execute( real64 const GEOS_UNUSED_PARAM( time_n
subRegionStats.finalizePeriod();
regionStats.stats().combine( subRegionStats.stats() );
} );
-
fluxStats.stats().combine( regionStats.stats() );
- writeStatsToLog( 3, region.getName(), regionStats );
- writeStatsToCSV( region.getName(), regionStats, false );
+
+ gatherStatsForLog( regionsStats, region.getName(), tableRegionsData, regionStats );
+ gatherStatsForCSV( csvData, regionStats );
} );
+ outputStatsToLog( regionsStats, fluxStats.getFluxName(), tableRegionsData );
+ outputStatsToCSV( m_regionsfilename, csvData );
+
meshLevelStats.stats().combine( fluxStats.stats() );
- writeStatsToLog( 2, viewKeyStruct::allRegionWrapperString(), fluxStats );
- writeStatsToCSV( viewKeyStruct::allRegionWrapperString(), fluxStats, false );
+
+ gatherStatsForLog( fluxesStats, viewKeyStruct::allRegionWrapperString(), tableFluxData, fluxStats );
+ gatherStatsForCSV( csvData, fluxStats );
+
+ outputStatsToLog( fluxesStats, fluxStats.getFluxName(), tableFluxData );
+ outputStatsToCSV( m_allRegionFluxsfilename, csvData );
+
} );
+ gatherStatsForLog( fluxMeshesStats,
+ viewKeyStruct::allRegionWrapperString(), tableMeshData, meshLevelStats );
+ gatherStatsForCSV( csvData, meshLevelStats );
- writeStatsToLog( 1, viewKeyStruct::allRegionWrapperString(), meshLevelStats );
- writeStatsToCSV( viewKeyStruct::allRegionWrapperString(), meshLevelStats, false );
+ outputStatsToLog( fluxMeshesStats, meshLevelStats.getFluxName(), tableMeshData );
+ outputStatsToCSV( m_allRegionWrapperFluxFilename, csvData );
} );
-
return false;
}
diff --git a/src/coreComponents/physicsSolvers/fluidFlow/SourceFluxStatistics.hpp b/src/coreComponents/physicsSolvers/fluidFlow/SourceFluxStatistics.hpp
index 43dad5d1c3a..d8d87e45b09 100644
--- a/src/coreComponents/physicsSolvers/fluidFlow/SourceFluxStatistics.hpp
+++ b/src/coreComponents/physicsSolvers/fluidFlow/SourceFluxStatistics.hpp
@@ -23,7 +23,10 @@
#include "../FieldStatisticsBase.hpp"
#include "FlowSolverBase.hpp"
#include "mesh/DomainPartition.hpp"
-
+#include "common/format/table/TableData.hpp"
+#include "common/format/table/TableFormatter.hpp"
+#include "common/format/table/TableLayout.hpp"
+#include