120282da2SJoe Wallwork #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 220282da2SJoe Wallwork #include <petscblaslapack.h> 320282da2SJoe Wallwork 4fe902aceSJoe Wallwork PetscLogEvent DMPLEX_MetricEnforceSPD, DMPLEX_MetricNormalize, DMPLEX_MetricAverage, DMPLEX_MetricIntersection; 5fe902aceSJoe Wallwork 6d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricSetFromOptions(DM dm) 7d71ae5a4SJacob Faibussowitsch { 8bc00d7afSJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 931b70465SJoe Wallwork MPI_Comm comm; 1093520041SJoe Wallwork PetscBool isotropic = PETSC_FALSE, uniform = PETSC_FALSE, restrictAnisotropyFirst = PETSC_FALSE; 1176f360caSJoe Wallwork PetscBool noInsert = PETSC_FALSE, noSwap = PETSC_FALSE, noMove = PETSC_FALSE, noSurf = PETSC_FALSE; 12cc2eee55SJoe Wallwork PetscInt verbosity = -1, numIter = 3; 13ae8b063eSJoe Wallwork PetscReal h_min = 1.0e-30, h_max = 1.0e+30, a_max = 1.0e+05, p = 1.0, target = 1000.0, beta = 1.3, hausd = 0.01; 1431b70465SJoe Wallwork 1531b70465SJoe Wallwork PetscFunctionBegin; 16bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(PetscNew(&plex->metricCtx)); 179566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 18d0609cedSBarry Smith PetscOptionsBegin(comm, "", "Riemannian metric options", "DMPlexMetric"); 199566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_metric_isotropic", "Is the metric isotropic?", "DMPlexMetricCreateIsotropic", isotropic, &isotropic, NULL)); 209566063dSJacob Faibussowitsch PetscCall(DMPlexMetricSetIsotropic(dm, isotropic)); 219566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_metric_uniform", "Is the metric uniform?", "DMPlexMetricCreateUniform", uniform, &uniform, NULL)); 229566063dSJacob Faibussowitsch PetscCall(DMPlexMetricSetUniform(dm, uniform)); 239566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_metric_restrict_anisotropy_first", "Should anisotropy be restricted before normalization?", "DMPlexNormalize", restrictAnisotropyFirst, &restrictAnisotropyFirst, NULL)); 249566063dSJacob Faibussowitsch PetscCall(DMPlexMetricSetRestrictAnisotropyFirst(dm, restrictAnisotropyFirst)); 259566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_metric_no_insert", "Turn off node insertion and deletion", "DMAdaptMetric", noInsert, &noInsert, NULL)); 269566063dSJacob Faibussowitsch PetscCall(DMPlexMetricSetNoInsertion(dm, noInsert)); 279566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_metric_no_swap", "Turn off facet swapping", "DMAdaptMetric", noSwap, &noSwap, NULL)); 289566063dSJacob Faibussowitsch PetscCall(DMPlexMetricSetNoSwapping(dm, noSwap)); 299566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_metric_no_move", "Turn off facet node movement", "DMAdaptMetric", noMove, &noMove, NULL)); 309566063dSJacob Faibussowitsch PetscCall(DMPlexMetricSetNoMovement(dm, noMove)); 319566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_metric_no_surf", "Turn off surface modification", "DMAdaptMetric", noSurf, &noSurf, NULL)); 329566063dSJacob Faibussowitsch PetscCall(DMPlexMetricSetNoSurf(dm, noSurf)); 339566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_metric_num_iterations", "Number of ParMmg adaptation iterations", "DMAdaptMetric", numIter, &numIter, NULL, 0)); 349566063dSJacob Faibussowitsch PetscCall(DMPlexMetricSetNumIterations(dm, numIter)); 359566063dSJacob Faibussowitsch PetscCall(PetscOptionsRangeInt("-dm_plex_metric_verbosity", "Verbosity of metric-based mesh adaptation package (-1 = silent, 10 = maximum)", "DMAdaptMetric", verbosity, &verbosity, NULL, -1, 10)); 369566063dSJacob Faibussowitsch PetscCall(DMPlexMetricSetVerbosity(dm, verbosity)); 379566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_metric_h_min", "Minimum tolerated metric magnitude", "DMPlexMetricEnforceSPD", h_min, &h_min, NULL)); 389566063dSJacob Faibussowitsch PetscCall(DMPlexMetricSetMinimumMagnitude(dm, h_min)); 399566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_metric_h_max", "Maximum tolerated metric magnitude", "DMPlexMetricEnforceSPD", h_max, &h_max, NULL)); 409566063dSJacob Faibussowitsch PetscCall(DMPlexMetricSetMaximumMagnitude(dm, h_max)); 419566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_metric_a_max", "Maximum tolerated anisotropy", "DMPlexMetricEnforceSPD", a_max, &a_max, NULL)); 429566063dSJacob Faibussowitsch PetscCall(DMPlexMetricSetMaximumAnisotropy(dm, a_max)); 439566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_metric_p", "L-p normalization order", "DMPlexMetricNormalize", p, &p, NULL)); 449566063dSJacob Faibussowitsch PetscCall(DMPlexMetricSetNormalizationOrder(dm, p)); 459566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_metric_target_complexity", "Target metric complexity", "DMPlexMetricNormalize", target, &target, NULL)); 469566063dSJacob Faibussowitsch PetscCall(DMPlexMetricSetTargetComplexity(dm, target)); 479566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_metric_gradation_factor", "Metric gradation factor", "DMAdaptMetric", beta, &beta, NULL)); 489566063dSJacob Faibussowitsch PetscCall(DMPlexMetricSetGradationFactor(dm, beta)); 499566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_metric_hausdorff_number", "Metric Hausdorff number", "DMAdaptMetric", hausd, &hausd, NULL)); 509566063dSJacob Faibussowitsch PetscCall(DMPlexMetricSetHausdorffNumber(dm, hausd)); 51d0609cedSBarry Smith PetscOptionsEnd(); 523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5331b70465SJoe Wallwork } 5431b70465SJoe Wallwork 55cb7bfe8cSJoe Wallwork /*@ 5631b70465SJoe Wallwork DMPlexMetricSetIsotropic - Record whether a metric is isotropic 5731b70465SJoe Wallwork 5860225df5SJacob Faibussowitsch Input Parameters: 592fe279fdSBarry Smith + dm - The `DM` 6031b70465SJoe Wallwork - isotropic - Is the metric isotropic? 6131b70465SJoe Wallwork 6231b70465SJoe Wallwork Level: beginner 6331b70465SJoe Wallwork 642fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricIsIsotropic()`, `DMPlexMetricSetUniform()`, `DMPlexMetricSetRestrictAnisotropyFirst()` 65cb7bfe8cSJoe Wallwork @*/ 66d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricSetIsotropic(DM dm, PetscBool isotropic) 67d71ae5a4SJacob Faibussowitsch { 6831b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 6931b70465SJoe Wallwork 7031b70465SJoe Wallwork PetscFunctionBegin; 71bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 7231b70465SJoe Wallwork plex->metricCtx->isotropic = isotropic; 733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7431b70465SJoe Wallwork } 7531b70465SJoe Wallwork 76cb7bfe8cSJoe Wallwork /*@ 7793520041SJoe Wallwork DMPlexMetricIsIsotropic - Is a metric isotropic? 7831b70465SJoe Wallwork 7960225df5SJacob Faibussowitsch Input Parameters: 802fe279fdSBarry Smith . dm - The `DM` 8131b70465SJoe Wallwork 8260225df5SJacob Faibussowitsch Output Parameters: 8331b70465SJoe Wallwork . isotropic - Is the metric isotropic? 8431b70465SJoe Wallwork 8531b70465SJoe Wallwork Level: beginner 8631b70465SJoe Wallwork 872fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricSetIsotropic()`, `DMPlexMetricIsUniform()`, `DMPlexMetricRestrictAnisotropyFirst()` 88cb7bfe8cSJoe Wallwork @*/ 89d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricIsIsotropic(DM dm, PetscBool *isotropic) 90d71ae5a4SJacob Faibussowitsch { 9131b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 9231b70465SJoe Wallwork 9331b70465SJoe Wallwork PetscFunctionBegin; 94bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 9531b70465SJoe Wallwork *isotropic = plex->metricCtx->isotropic; 963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9731b70465SJoe Wallwork } 9831b70465SJoe Wallwork 99cb7bfe8cSJoe Wallwork /*@ 10093520041SJoe Wallwork DMPlexMetricSetUniform - Record whether a metric is uniform 10193520041SJoe Wallwork 10260225df5SJacob Faibussowitsch Input Parameters: 1032fe279fdSBarry Smith + dm - The `DM` 10493520041SJoe Wallwork - uniform - Is the metric uniform? 10593520041SJoe Wallwork 10693520041SJoe Wallwork Level: beginner 10793520041SJoe Wallwork 1082fe279fdSBarry Smith Note: 10993520041SJoe Wallwork If the metric is specified as uniform then it is assumed to be isotropic, too. 11093520041SJoe Wallwork 1112fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricIsUniform()`, `DMPlexMetricSetIsotropic()`, `DMPlexMetricSetRestrictAnisotropyFirst()` 11293520041SJoe Wallwork @*/ 113d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricSetUniform(DM dm, PetscBool uniform) 114d71ae5a4SJacob Faibussowitsch { 11593520041SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 11693520041SJoe Wallwork 11793520041SJoe Wallwork PetscFunctionBegin; 118bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 11993520041SJoe Wallwork plex->metricCtx->uniform = uniform; 12093520041SJoe Wallwork if (uniform) plex->metricCtx->isotropic = uniform; 1213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12293520041SJoe Wallwork } 12393520041SJoe Wallwork 12493520041SJoe Wallwork /*@ 12593520041SJoe Wallwork DMPlexMetricIsUniform - Is a metric uniform? 12693520041SJoe Wallwork 12760225df5SJacob Faibussowitsch Input Parameters: 1282fe279fdSBarry Smith . dm - The `DM` 12993520041SJoe Wallwork 13060225df5SJacob Faibussowitsch Output Parameters: 13193520041SJoe Wallwork . uniform - Is the metric uniform? 13293520041SJoe Wallwork 13393520041SJoe Wallwork Level: beginner 13493520041SJoe Wallwork 1352fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricSetUniform()`, `DMPlexMetricIsIsotropic()`, `DMPlexMetricRestrictAnisotropyFirst()` 13693520041SJoe Wallwork @*/ 137d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricIsUniform(DM dm, PetscBool *uniform) 138d71ae5a4SJacob Faibussowitsch { 13993520041SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 14093520041SJoe Wallwork 14193520041SJoe Wallwork PetscFunctionBegin; 142bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 14393520041SJoe Wallwork *uniform = plex->metricCtx->uniform; 1443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14593520041SJoe Wallwork } 14693520041SJoe Wallwork 14793520041SJoe Wallwork /*@ 14831b70465SJoe Wallwork DMPlexMetricSetRestrictAnisotropyFirst - Record whether anisotropy should be restricted before normalization 14931b70465SJoe Wallwork 15060225df5SJacob Faibussowitsch Input Parameters: 1512fe279fdSBarry Smith + dm - The `DM` 15231b70465SJoe Wallwork - restrictAnisotropyFirst - Should anisotropy be normalized first? 15331b70465SJoe Wallwork 15431b70465SJoe Wallwork Level: beginner 15531b70465SJoe Wallwork 1562fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricSetIsotropic()`, `DMPlexMetricRestrictAnisotropyFirst()` 157cb7bfe8cSJoe Wallwork @*/ 158d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricSetRestrictAnisotropyFirst(DM dm, PetscBool restrictAnisotropyFirst) 159d71ae5a4SJacob Faibussowitsch { 16031b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 16131b70465SJoe Wallwork 16231b70465SJoe Wallwork PetscFunctionBegin; 163bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 16431b70465SJoe Wallwork plex->metricCtx->restrictAnisotropyFirst = restrictAnisotropyFirst; 1653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16631b70465SJoe Wallwork } 16731b70465SJoe Wallwork 168cb7bfe8cSJoe Wallwork /*@ 16931b70465SJoe Wallwork DMPlexMetricRestrictAnisotropyFirst - Is anisotropy restricted before normalization or after? 17031b70465SJoe Wallwork 17160225df5SJacob Faibussowitsch Input Parameters: 1722fe279fdSBarry Smith . dm - The `DM` 17331b70465SJoe Wallwork 17460225df5SJacob Faibussowitsch Output Parameters: 17531b70465SJoe Wallwork . restrictAnisotropyFirst - Is anisotropy be normalized first? 17631b70465SJoe Wallwork 17731b70465SJoe Wallwork Level: beginner 17831b70465SJoe Wallwork 1792fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricIsIsotropic()`, `DMPlexMetricSetRestrictAnisotropyFirst()` 180cb7bfe8cSJoe Wallwork @*/ 181d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricRestrictAnisotropyFirst(DM dm, PetscBool *restrictAnisotropyFirst) 182d71ae5a4SJacob Faibussowitsch { 18331b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 18431b70465SJoe Wallwork 18531b70465SJoe Wallwork PetscFunctionBegin; 186bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 18731b70465SJoe Wallwork *restrictAnisotropyFirst = plex->metricCtx->restrictAnisotropyFirst; 1883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18931b70465SJoe Wallwork } 19031b70465SJoe Wallwork 191cb7bfe8cSJoe Wallwork /*@ 192cc2eee55SJoe Wallwork DMPlexMetricSetNoInsertion - Should node insertion and deletion be turned off? 193cc2eee55SJoe Wallwork 19460225df5SJacob Faibussowitsch Input Parameters: 1952fe279fdSBarry Smith + dm - The `DM` 196cc2eee55SJoe Wallwork - noInsert - Should node insertion and deletion be turned off? 197cc2eee55SJoe Wallwork 198cc2eee55SJoe Wallwork Level: beginner 199cc2eee55SJoe Wallwork 2002fe279fdSBarry Smith Note: 201cb7bfe8cSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 202cb7bfe8cSJoe Wallwork 2032fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricNoInsertion()`, `DMPlexMetricSetNoSwapping()`, `DMPlexMetricSetNoMovement()`, `DMPlexMetricSetNoSurf()` 204cb7bfe8cSJoe Wallwork @*/ 205d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricSetNoInsertion(DM dm, PetscBool noInsert) 206d71ae5a4SJacob Faibussowitsch { 207cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 208cc2eee55SJoe Wallwork 209cc2eee55SJoe Wallwork PetscFunctionBegin; 210bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 211cc2eee55SJoe Wallwork plex->metricCtx->noInsert = noInsert; 2123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 213cc2eee55SJoe Wallwork } 214cc2eee55SJoe Wallwork 215cb7bfe8cSJoe Wallwork /*@ 216cc2eee55SJoe Wallwork DMPlexMetricNoInsertion - Are node insertion and deletion turned off? 217cc2eee55SJoe Wallwork 21860225df5SJacob Faibussowitsch Input Parameters: 2192fe279fdSBarry Smith . dm - The `DM` 220cc2eee55SJoe Wallwork 22160225df5SJacob Faibussowitsch Output Parameters: 222cc2eee55SJoe Wallwork . noInsert - Are node insertion and deletion turned off? 223cc2eee55SJoe Wallwork 224cc2eee55SJoe Wallwork Level: beginner 225cc2eee55SJoe Wallwork 2262fe279fdSBarry Smith Note: 227cb7bfe8cSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 228cb7bfe8cSJoe Wallwork 2292fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricSetNoInsertion()`, `DMPlexMetricNoSwapping()`, `DMPlexMetricNoMovement()`, `DMPlexMetricNoSurf()` 230cb7bfe8cSJoe Wallwork @*/ 231d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricNoInsertion(DM dm, PetscBool *noInsert) 232d71ae5a4SJacob Faibussowitsch { 233cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 234cc2eee55SJoe Wallwork 235cc2eee55SJoe Wallwork PetscFunctionBegin; 236bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 237cc2eee55SJoe Wallwork *noInsert = plex->metricCtx->noInsert; 2383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 239cc2eee55SJoe Wallwork } 240cc2eee55SJoe Wallwork 241cb7bfe8cSJoe Wallwork /*@ 242cc2eee55SJoe Wallwork DMPlexMetricSetNoSwapping - Should facet swapping be turned off? 243cc2eee55SJoe Wallwork 24460225df5SJacob Faibussowitsch Input Parameters: 2452fe279fdSBarry Smith + dm - The `DM` 246cc2eee55SJoe Wallwork - noSwap - Should facet swapping be turned off? 247cc2eee55SJoe Wallwork 248cc2eee55SJoe Wallwork Level: beginner 249cc2eee55SJoe Wallwork 2502fe279fdSBarry Smith Note: 251cb7bfe8cSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 252cb7bfe8cSJoe Wallwork 2532fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricNoSwapping()`, `DMPlexMetricSetNoInsertion()`, `DMPlexMetricSetNoMovement()`, `DMPlexMetricSetNoSurf()` 254cb7bfe8cSJoe Wallwork @*/ 255d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricSetNoSwapping(DM dm, PetscBool noSwap) 256d71ae5a4SJacob Faibussowitsch { 257cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 258cc2eee55SJoe Wallwork 259cc2eee55SJoe Wallwork PetscFunctionBegin; 260bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 261cc2eee55SJoe Wallwork plex->metricCtx->noSwap = noSwap; 2623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 263cc2eee55SJoe Wallwork } 264cc2eee55SJoe Wallwork 265cb7bfe8cSJoe Wallwork /*@ 266cc2eee55SJoe Wallwork DMPlexMetricNoSwapping - Is facet swapping turned off? 267cc2eee55SJoe Wallwork 26860225df5SJacob Faibussowitsch Input Parameters: 2692fe279fdSBarry Smith . dm - The `DM` 270cc2eee55SJoe Wallwork 27160225df5SJacob Faibussowitsch Output Parameters: 272cc2eee55SJoe Wallwork . noSwap - Is facet swapping turned off? 273cc2eee55SJoe Wallwork 274cc2eee55SJoe Wallwork Level: beginner 275cc2eee55SJoe Wallwork 2762fe279fdSBarry Smith Note: 277cb7bfe8cSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 278cb7bfe8cSJoe Wallwork 2792fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricSetNoSwapping()`, `DMPlexMetricNoInsertion()`, `DMPlexMetricNoMovement()`, `DMPlexMetricNoSurf()` 280cb7bfe8cSJoe Wallwork @*/ 281d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricNoSwapping(DM dm, PetscBool *noSwap) 282d71ae5a4SJacob Faibussowitsch { 283cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 284cc2eee55SJoe Wallwork 285cc2eee55SJoe Wallwork PetscFunctionBegin; 286bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 287cc2eee55SJoe Wallwork *noSwap = plex->metricCtx->noSwap; 2883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 289cc2eee55SJoe Wallwork } 290cc2eee55SJoe Wallwork 291cb7bfe8cSJoe Wallwork /*@ 292cc2eee55SJoe Wallwork DMPlexMetricSetNoMovement - Should node movement be turned off? 293cc2eee55SJoe Wallwork 29460225df5SJacob Faibussowitsch Input Parameters: 2952fe279fdSBarry Smith + dm - The `DM` 296cc2eee55SJoe Wallwork - noMove - Should node movement be turned off? 297cc2eee55SJoe Wallwork 298cc2eee55SJoe Wallwork Level: beginner 299cc2eee55SJoe Wallwork 3002fe279fdSBarry Smith Note: 301cb7bfe8cSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 302cb7bfe8cSJoe Wallwork 3032fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricNoMovement()`, `DMPlexMetricSetNoInsertion()`, `DMPlexMetricSetNoSwapping()`, `DMPlexMetricSetNoSurf()` 304cb7bfe8cSJoe Wallwork @*/ 305d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricSetNoMovement(DM dm, PetscBool noMove) 306d71ae5a4SJacob Faibussowitsch { 307cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 308cc2eee55SJoe Wallwork 309cc2eee55SJoe Wallwork PetscFunctionBegin; 310bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 311cc2eee55SJoe Wallwork plex->metricCtx->noMove = noMove; 3123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 313cc2eee55SJoe Wallwork } 314cc2eee55SJoe Wallwork 315cb7bfe8cSJoe Wallwork /*@ 316cc2eee55SJoe Wallwork DMPlexMetricNoMovement - Is node movement turned off? 317cc2eee55SJoe Wallwork 31860225df5SJacob Faibussowitsch Input Parameters: 3192fe279fdSBarry Smith . dm - The `DM` 320cc2eee55SJoe Wallwork 32160225df5SJacob Faibussowitsch Output Parameters: 322cc2eee55SJoe Wallwork . noMove - Is node movement turned off? 323cc2eee55SJoe Wallwork 324cc2eee55SJoe Wallwork Level: beginner 325cc2eee55SJoe Wallwork 3262fe279fdSBarry Smith Note: 327cb7bfe8cSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 328cb7bfe8cSJoe Wallwork 3292fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricSetNoMovement()`, `DMPlexMetricNoInsertion()`, `DMPlexMetricNoSwapping()`, `DMPlexMetricNoSurf()` 330cb7bfe8cSJoe Wallwork @*/ 331d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricNoMovement(DM dm, PetscBool *noMove) 332d71ae5a4SJacob Faibussowitsch { 333cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 334cc2eee55SJoe Wallwork 335cc2eee55SJoe Wallwork PetscFunctionBegin; 336bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 337cc2eee55SJoe Wallwork *noMove = plex->metricCtx->noMove; 3383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 339cc2eee55SJoe Wallwork } 340cc2eee55SJoe Wallwork 341cb7bfe8cSJoe Wallwork /*@ 34276f360caSJoe Wallwork DMPlexMetricSetNoSurf - Should surface modification be turned off? 34376f360caSJoe Wallwork 34460225df5SJacob Faibussowitsch Input Parameters: 3452fe279fdSBarry Smith + dm - The `DM` 34676f360caSJoe Wallwork - noSurf - Should surface modification be turned off? 34776f360caSJoe Wallwork 34876f360caSJoe Wallwork Level: beginner 34976f360caSJoe Wallwork 3502fe279fdSBarry Smith Note: 35176f360caSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 35276f360caSJoe Wallwork 3532fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricNoSurf()`, `DMPlexMetricSetNoMovement()`, `DMPlexMetricSetNoInsertion()`, `DMPlexMetricSetNoSwapping()` 35476f360caSJoe Wallwork @*/ 355d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricSetNoSurf(DM dm, PetscBool noSurf) 356d71ae5a4SJacob Faibussowitsch { 35776f360caSJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 35876f360caSJoe Wallwork 35976f360caSJoe Wallwork PetscFunctionBegin; 360bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 36176f360caSJoe Wallwork plex->metricCtx->noSurf = noSurf; 3623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 36376f360caSJoe Wallwork } 36476f360caSJoe Wallwork 36576f360caSJoe Wallwork /*@ 36676f360caSJoe Wallwork DMPlexMetricNoSurf - Is surface modification turned off? 36776f360caSJoe Wallwork 36860225df5SJacob Faibussowitsch Input Parameters: 3692fe279fdSBarry Smith . dm - The `DM` 37076f360caSJoe Wallwork 37160225df5SJacob Faibussowitsch Output Parameters: 37276f360caSJoe Wallwork . noSurf - Is surface modification turned off? 37376f360caSJoe Wallwork 37476f360caSJoe Wallwork Level: beginner 37576f360caSJoe Wallwork 3762fe279fdSBarry Smith Note: 37776f360caSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 37876f360caSJoe Wallwork 3792fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricSetNoSurf()`, `DMPlexMetricNoMovement()`, `DMPlexMetricNoInsertion()`, `DMPlexMetricNoSwapping()` 38076f360caSJoe Wallwork @*/ 381d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricNoSurf(DM dm, PetscBool *noSurf) 382d71ae5a4SJacob Faibussowitsch { 38376f360caSJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 38476f360caSJoe Wallwork 38576f360caSJoe Wallwork PetscFunctionBegin; 386bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 38776f360caSJoe Wallwork *noSurf = plex->metricCtx->noSurf; 3883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 38976f360caSJoe Wallwork } 39076f360caSJoe Wallwork 39176f360caSJoe Wallwork /*@ 39231b70465SJoe Wallwork DMPlexMetricSetMinimumMagnitude - Set the minimum tolerated metric magnitude 39331b70465SJoe Wallwork 39460225df5SJacob Faibussowitsch Input Parameters: 3952fe279fdSBarry Smith + dm - The `DM` 39631b70465SJoe Wallwork - h_min - The minimum tolerated metric magnitude 39731b70465SJoe Wallwork 39831b70465SJoe Wallwork Level: beginner 39931b70465SJoe Wallwork 4002fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricGetMinimumMagnitude()`, `DMPlexMetricSetMaximumMagnitude()` 401cb7bfe8cSJoe Wallwork @*/ 402d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricSetMinimumMagnitude(DM dm, PetscReal h_min) 403d71ae5a4SJacob Faibussowitsch { 40431b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 40531b70465SJoe Wallwork 40631b70465SJoe Wallwork PetscFunctionBegin; 407bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 408bc00d7afSJoe Wallwork PetscCheck(h_min > 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Metric magnitudes must be in (0, inf)"); 40931b70465SJoe Wallwork plex->metricCtx->h_min = h_min; 4103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41131b70465SJoe Wallwork } 41231b70465SJoe Wallwork 413cb7bfe8cSJoe Wallwork /*@ 41431b70465SJoe Wallwork DMPlexMetricGetMinimumMagnitude - Get the minimum tolerated metric magnitude 41531b70465SJoe Wallwork 41660225df5SJacob Faibussowitsch Input Parameters: 4172fe279fdSBarry Smith . dm - The `DM` 41831b70465SJoe Wallwork 41960225df5SJacob Faibussowitsch Output Parameters: 42031b70465SJoe Wallwork . h_min - The minimum tolerated metric magnitude 42131b70465SJoe Wallwork 42231b70465SJoe Wallwork Level: beginner 42331b70465SJoe Wallwork 4242fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricSetMinimumMagnitude()`, `DMPlexMetricGetMaximumMagnitude()` 425cb7bfe8cSJoe Wallwork @*/ 426d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricGetMinimumMagnitude(DM dm, PetscReal *h_min) 427d71ae5a4SJacob Faibussowitsch { 42831b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 42931b70465SJoe Wallwork 43031b70465SJoe Wallwork PetscFunctionBegin; 431bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 43231b70465SJoe Wallwork *h_min = plex->metricCtx->h_min; 4333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43431b70465SJoe Wallwork } 43531b70465SJoe Wallwork 436cb7bfe8cSJoe Wallwork /*@ 43731b70465SJoe Wallwork DMPlexMetricSetMaximumMagnitude - Set the maximum tolerated metric magnitude 43831b70465SJoe Wallwork 43960225df5SJacob Faibussowitsch Input Parameters: 4402fe279fdSBarry Smith + dm - The `DM` 44131b70465SJoe Wallwork - h_max - The maximum tolerated metric magnitude 44231b70465SJoe Wallwork 44331b70465SJoe Wallwork Level: beginner 44431b70465SJoe Wallwork 4452fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricGetMaximumMagnitude()`, `DMPlexMetricSetMinimumMagnitude()` 446cb7bfe8cSJoe Wallwork @*/ 447d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricSetMaximumMagnitude(DM dm, PetscReal h_max) 448d71ae5a4SJacob Faibussowitsch { 44931b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 45031b70465SJoe Wallwork 45131b70465SJoe Wallwork PetscFunctionBegin; 452bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 453bc00d7afSJoe Wallwork PetscCheck(h_max > 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Metric magnitudes must be in (0, inf)"); 45431b70465SJoe Wallwork plex->metricCtx->h_max = h_max; 4553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 45631b70465SJoe Wallwork } 45731b70465SJoe Wallwork 458cb7bfe8cSJoe Wallwork /*@ 45931b70465SJoe Wallwork DMPlexMetricGetMaximumMagnitude - Get the maximum tolerated metric magnitude 46031b70465SJoe Wallwork 46160225df5SJacob Faibussowitsch Input Parameters: 4622fe279fdSBarry Smith . dm - The `DM` 46331b70465SJoe Wallwork 46460225df5SJacob Faibussowitsch Output Parameters: 46531b70465SJoe Wallwork . h_max - The maximum tolerated metric magnitude 46631b70465SJoe Wallwork 46731b70465SJoe Wallwork Level: beginner 46831b70465SJoe Wallwork 4692fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricSetMaximumMagnitude()`, `DMPlexMetricGetMinimumMagnitude()` 470cb7bfe8cSJoe Wallwork @*/ 471d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricGetMaximumMagnitude(DM dm, PetscReal *h_max) 472d71ae5a4SJacob Faibussowitsch { 47331b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 47431b70465SJoe Wallwork 47531b70465SJoe Wallwork PetscFunctionBegin; 476bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 47731b70465SJoe Wallwork *h_max = plex->metricCtx->h_max; 4783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 47931b70465SJoe Wallwork } 48031b70465SJoe Wallwork 481cb7bfe8cSJoe Wallwork /*@ 48231b70465SJoe Wallwork DMPlexMetricSetMaximumAnisotropy - Set the maximum tolerated metric anisotropy 48331b70465SJoe Wallwork 48460225df5SJacob Faibussowitsch Input Parameters: 4852fe279fdSBarry Smith + dm - The `DM` 48631b70465SJoe Wallwork - a_max - The maximum tolerated metric anisotropy 48731b70465SJoe Wallwork 48831b70465SJoe Wallwork Level: beginner 48931b70465SJoe Wallwork 4902fe279fdSBarry Smith Note: 4912fe279fdSBarry Smith If the value zero is given then anisotropy will not be restricted. Otherwise, it should be at least one. 49231b70465SJoe Wallwork 4932fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricGetMaximumAnisotropy()`, `DMPlexMetricSetMaximumMagnitude()` 494cb7bfe8cSJoe Wallwork @*/ 495d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricSetMaximumAnisotropy(DM dm, PetscReal a_max) 496d71ae5a4SJacob Faibussowitsch { 49731b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 49831b70465SJoe Wallwork 49931b70465SJoe Wallwork PetscFunctionBegin; 500bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 501bc00d7afSJoe Wallwork PetscCheck(a_max >= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Anisotropy must be in [1, inf)"); 50231b70465SJoe Wallwork plex->metricCtx->a_max = a_max; 5033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50431b70465SJoe Wallwork } 50531b70465SJoe Wallwork 506cb7bfe8cSJoe Wallwork /*@ 50731b70465SJoe Wallwork DMPlexMetricGetMaximumAnisotropy - Get the maximum tolerated metric anisotropy 50831b70465SJoe Wallwork 50960225df5SJacob Faibussowitsch Input Parameters: 5102fe279fdSBarry Smith . dm - The `DM` 51131b70465SJoe Wallwork 51260225df5SJacob Faibussowitsch Output Parameters: 51331b70465SJoe Wallwork . a_max - The maximum tolerated metric anisotropy 51431b70465SJoe Wallwork 51531b70465SJoe Wallwork Level: beginner 51631b70465SJoe Wallwork 5172fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricSetMaximumAnisotropy()`, `DMPlexMetricGetMaximumMagnitude()` 518cb7bfe8cSJoe Wallwork @*/ 519d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricGetMaximumAnisotropy(DM dm, PetscReal *a_max) 520d71ae5a4SJacob Faibussowitsch { 52131b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 52231b70465SJoe Wallwork 52331b70465SJoe Wallwork PetscFunctionBegin; 524bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 52531b70465SJoe Wallwork *a_max = plex->metricCtx->a_max; 5263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52731b70465SJoe Wallwork } 52831b70465SJoe Wallwork 529cb7bfe8cSJoe Wallwork /*@ 53031b70465SJoe Wallwork DMPlexMetricSetTargetComplexity - Set the target metric complexity 53131b70465SJoe Wallwork 53260225df5SJacob Faibussowitsch Input Parameters: 5332fe279fdSBarry Smith + dm - The `DM` 53431b70465SJoe Wallwork - targetComplexity - The target metric complexity 53531b70465SJoe Wallwork 53631b70465SJoe Wallwork Level: beginner 53731b70465SJoe Wallwork 5382fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricGetTargetComplexity()`, `DMPlexMetricSetNormalizationOrder()` 539cb7bfe8cSJoe Wallwork @*/ 540d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricSetTargetComplexity(DM dm, PetscReal targetComplexity) 541d71ae5a4SJacob Faibussowitsch { 54231b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 54331b70465SJoe Wallwork 54431b70465SJoe Wallwork PetscFunctionBegin; 545bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 546bc00d7afSJoe Wallwork PetscCheck(targetComplexity > 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Metric complexity must be in (0, inf)"); 54731b70465SJoe Wallwork plex->metricCtx->targetComplexity = targetComplexity; 5483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 54931b70465SJoe Wallwork } 55031b70465SJoe Wallwork 551cb7bfe8cSJoe Wallwork /*@ 55231b70465SJoe Wallwork DMPlexMetricGetTargetComplexity - Get the target metric complexity 55331b70465SJoe Wallwork 55460225df5SJacob Faibussowitsch Input Parameters: 5552fe279fdSBarry Smith . dm - The `DM` 55631b70465SJoe Wallwork 55760225df5SJacob Faibussowitsch Output Parameters: 55831b70465SJoe Wallwork . targetComplexity - The target metric complexity 55931b70465SJoe Wallwork 56031b70465SJoe Wallwork Level: beginner 56131b70465SJoe Wallwork 5622fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricSetTargetComplexity()`, `DMPlexMetricGetNormalizationOrder()` 563cb7bfe8cSJoe Wallwork @*/ 564d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricGetTargetComplexity(DM dm, PetscReal *targetComplexity) 565d71ae5a4SJacob Faibussowitsch { 56631b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 56731b70465SJoe Wallwork 56831b70465SJoe Wallwork PetscFunctionBegin; 569bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 57031b70465SJoe Wallwork *targetComplexity = plex->metricCtx->targetComplexity; 5713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57231b70465SJoe Wallwork } 57331b70465SJoe Wallwork 574cb7bfe8cSJoe Wallwork /*@ 57531b70465SJoe Wallwork DMPlexMetricSetNormalizationOrder - Set the order p for L-p normalization 57631b70465SJoe Wallwork 57760225df5SJacob Faibussowitsch Input Parameters: 5782fe279fdSBarry Smith + dm - The `DM` 57931b70465SJoe Wallwork - p - The normalization order 58031b70465SJoe Wallwork 58131b70465SJoe Wallwork Level: beginner 58231b70465SJoe Wallwork 5832fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricGetNormalizationOrder()`, `DMPlexMetricSetTargetComplexity()` 584cb7bfe8cSJoe Wallwork @*/ 585d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricSetNormalizationOrder(DM dm, PetscReal p) 586d71ae5a4SJacob Faibussowitsch { 58731b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 58831b70465SJoe Wallwork 58931b70465SJoe Wallwork PetscFunctionBegin; 590bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 591bc00d7afSJoe Wallwork PetscCheck(p >= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Normalization order must be in [1, inf)"); 59231b70465SJoe Wallwork plex->metricCtx->p = p; 5933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 59431b70465SJoe Wallwork } 59531b70465SJoe Wallwork 596cb7bfe8cSJoe Wallwork /*@ 59731b70465SJoe Wallwork DMPlexMetricGetNormalizationOrder - Get the order p for L-p normalization 59831b70465SJoe Wallwork 59960225df5SJacob Faibussowitsch Input Parameters: 6002fe279fdSBarry Smith . dm - The `DM` 60131b70465SJoe Wallwork 60260225df5SJacob Faibussowitsch Output Parameters: 60331b70465SJoe Wallwork . p - The normalization order 60431b70465SJoe Wallwork 60531b70465SJoe Wallwork Level: beginner 60631b70465SJoe Wallwork 6072fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricSetNormalizationOrder()`, `DMPlexMetricGetTargetComplexity()` 608cb7bfe8cSJoe Wallwork @*/ 609d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricGetNormalizationOrder(DM dm, PetscReal *p) 610d71ae5a4SJacob Faibussowitsch { 61131b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 61231b70465SJoe Wallwork 61331b70465SJoe Wallwork PetscFunctionBegin; 614bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 61531b70465SJoe Wallwork *p = plex->metricCtx->p; 6163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 61731b70465SJoe Wallwork } 61831b70465SJoe Wallwork 619cb7bfe8cSJoe Wallwork /*@ 620cc2eee55SJoe Wallwork DMPlexMetricSetGradationFactor - Set the metric gradation factor 621cc2eee55SJoe Wallwork 62260225df5SJacob Faibussowitsch Input Parameters: 6232fe279fdSBarry Smith + dm - The `DM` 624cc2eee55SJoe Wallwork - beta - The metric gradation factor 625cc2eee55SJoe Wallwork 626cc2eee55SJoe Wallwork Level: beginner 627cc2eee55SJoe Wallwork 628cc2eee55SJoe Wallwork Notes: 629cc2eee55SJoe Wallwork The gradation factor is the maximum tolerated length ratio between adjacent edges. 630cc2eee55SJoe Wallwork 631cc2eee55SJoe Wallwork Turn off gradation by passing the value -1. Otherwise, pass a positive value. 632cc2eee55SJoe Wallwork 633cb7bfe8cSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 634cb7bfe8cSJoe Wallwork 6352fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricGetGradationFactor()`, `DMPlexMetricSetHausdorffNumber()` 636cb7bfe8cSJoe Wallwork @*/ 637d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricSetGradationFactor(DM dm, PetscReal beta) 638d71ae5a4SJacob Faibussowitsch { 639cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 640cc2eee55SJoe Wallwork 641cc2eee55SJoe Wallwork PetscFunctionBegin; 642bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 643bc00d7afSJoe Wallwork PetscCheck(beta > 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Metric gradation factor must be in (0, inf)"); 644cc2eee55SJoe Wallwork plex->metricCtx->gradationFactor = beta; 6453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 646cc2eee55SJoe Wallwork } 647cc2eee55SJoe Wallwork 648cb7bfe8cSJoe Wallwork /*@ 649cc2eee55SJoe Wallwork DMPlexMetricGetGradationFactor - Get the metric gradation factor 650cc2eee55SJoe Wallwork 65160225df5SJacob Faibussowitsch Input Parameters: 6522fe279fdSBarry Smith . dm - The `DM` 653cc2eee55SJoe Wallwork 65460225df5SJacob Faibussowitsch Output Parameters: 655cc2eee55SJoe Wallwork . beta - The metric gradation factor 656cc2eee55SJoe Wallwork 657cc2eee55SJoe Wallwork Level: beginner 658cc2eee55SJoe Wallwork 659cb7bfe8cSJoe Wallwork Notes: 660cb7bfe8cSJoe Wallwork The gradation factor is the maximum tolerated length ratio between adjacent edges. 661cb7bfe8cSJoe Wallwork 662cb7bfe8cSJoe Wallwork The value -1 implies that gradation is turned off. 663cb7bfe8cSJoe Wallwork 664cb7bfe8cSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 665cc2eee55SJoe Wallwork 6662fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricSetGradationFactor()`, `DMPlexMetricGetHausdorffNumber()` 667cb7bfe8cSJoe Wallwork @*/ 668d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricGetGradationFactor(DM dm, PetscReal *beta) 669d71ae5a4SJacob Faibussowitsch { 670cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 671cc2eee55SJoe Wallwork 672cc2eee55SJoe Wallwork PetscFunctionBegin; 673bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 674cc2eee55SJoe Wallwork *beta = plex->metricCtx->gradationFactor; 6753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 676cc2eee55SJoe Wallwork } 677cc2eee55SJoe Wallwork 678cb7bfe8cSJoe Wallwork /*@ 679ae8b063eSJoe Wallwork DMPlexMetricSetHausdorffNumber - Set the metric Hausdorff number 680ae8b063eSJoe Wallwork 68160225df5SJacob Faibussowitsch Input Parameters: 6822fe279fdSBarry Smith + dm - The `DM` 683ae8b063eSJoe Wallwork - hausd - The metric Hausdorff number 684ae8b063eSJoe Wallwork 685ae8b063eSJoe Wallwork Level: beginner 686ae8b063eSJoe Wallwork 687ae8b063eSJoe Wallwork Notes: 688ae8b063eSJoe Wallwork The Hausdorff number imposes the maximal distance between the piecewise linear approximation of the 689ae8b063eSJoe Wallwork boundary and the reconstructed ideal boundary. Thus, a low Hausdorff parameter leads to refine the 690ae8b063eSJoe Wallwork high curvature areas. By default, the Hausdorff value is set to 0.01, which is a suitable value for 691ae8b063eSJoe Wallwork an object of size 1 in each direction. For smaller (resp. larger) objects, you may need to decrease 692ae8b063eSJoe Wallwork (resp. increase) the Hausdorff parameter. (Taken from 693ae8b063eSJoe Wallwork https://www.mmgtools.org/mmg-remesher-try-mmg/mmg-remesher-options/mmg-remesher-option-hausd). 694ae8b063eSJoe Wallwork 695ae8b063eSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 696ae8b063eSJoe Wallwork 6972fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricSetGradationFactor()`, `DMPlexMetricGetHausdorffNumber()` 698ae8b063eSJoe Wallwork @*/ 699d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricSetHausdorffNumber(DM dm, PetscReal hausd) 700d71ae5a4SJacob Faibussowitsch { 701ae8b063eSJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 702ae8b063eSJoe Wallwork 703ae8b063eSJoe Wallwork PetscFunctionBegin; 704bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 705bc00d7afSJoe Wallwork PetscCheck(hausd > 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Metric Hausdorff number must be in (0, inf)"); 706ae8b063eSJoe Wallwork plex->metricCtx->hausdorffNumber = hausd; 7073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 708ae8b063eSJoe Wallwork } 709ae8b063eSJoe Wallwork 710ae8b063eSJoe Wallwork /*@ 711ae8b063eSJoe Wallwork DMPlexMetricGetHausdorffNumber - Get the metric Hausdorff number 712ae8b063eSJoe Wallwork 71360225df5SJacob Faibussowitsch Input Parameters: 7142fe279fdSBarry Smith . dm - The `DM` 715ae8b063eSJoe Wallwork 71660225df5SJacob Faibussowitsch Output Parameters: 717ae8b063eSJoe Wallwork . hausd - The metric Hausdorff number 718ae8b063eSJoe Wallwork 719ae8b063eSJoe Wallwork Level: beginner 720ae8b063eSJoe Wallwork 721ae8b063eSJoe Wallwork Notes: 722ae8b063eSJoe Wallwork The Hausdorff number imposes the maximal distance between the piecewise linear approximation of the 723ae8b063eSJoe Wallwork boundary and the reconstructed ideal boundary. Thus, a low Hausdorff parameter leads to refine the 724ae8b063eSJoe Wallwork high curvature areas. By default, the Hausdorff value is set to 0.01, which is a suitable value for 725ae8b063eSJoe Wallwork an object of size 1 in each direction. For smaller (resp. larger) objects, you may need to decrease 726ae8b063eSJoe Wallwork (resp. increase) the Hausdorff parameter. (Taken from 727ae8b063eSJoe Wallwork https://www.mmgtools.org/mmg-remesher-try-mmg/mmg-remesher-options/mmg-remesher-option-hausd). 728ae8b063eSJoe Wallwork 729ae8b063eSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 730ae8b063eSJoe Wallwork 7312fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricGetGradationFactor()`, `DMPlexMetricSetHausdorffNumber()` 732ae8b063eSJoe Wallwork @*/ 733d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricGetHausdorffNumber(DM dm, PetscReal *hausd) 734d71ae5a4SJacob Faibussowitsch { 735ae8b063eSJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 736ae8b063eSJoe Wallwork 737ae8b063eSJoe Wallwork PetscFunctionBegin; 738bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 739ae8b063eSJoe Wallwork *hausd = plex->metricCtx->hausdorffNumber; 7403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 741ae8b063eSJoe Wallwork } 742ae8b063eSJoe Wallwork 743ae8b063eSJoe Wallwork /*@ 744cc2eee55SJoe Wallwork DMPlexMetricSetVerbosity - Set the verbosity of the mesh adaptation package 745cc2eee55SJoe Wallwork 74660225df5SJacob Faibussowitsch Input Parameters: 7472fe279fdSBarry Smith + dm - The `DM` 748cc2eee55SJoe Wallwork - verbosity - The verbosity, where -1 is silent and 10 is maximum 749cc2eee55SJoe Wallwork 750cb7bfe8cSJoe Wallwork Level: beginner 751cb7bfe8cSJoe Wallwork 7522fe279fdSBarry Smith Note: 753cb7bfe8cSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 754cb7bfe8cSJoe Wallwork 7552fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricGetVerbosity()`, `DMPlexMetricSetNumIterations()` 756cb7bfe8cSJoe Wallwork @*/ 757d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricSetVerbosity(DM dm, PetscInt verbosity) 758d71ae5a4SJacob Faibussowitsch { 759cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 760cc2eee55SJoe Wallwork 761cc2eee55SJoe Wallwork PetscFunctionBegin; 762bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 763cc2eee55SJoe Wallwork plex->metricCtx->verbosity = verbosity; 7643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 765cc2eee55SJoe Wallwork } 766cc2eee55SJoe Wallwork 767cb7bfe8cSJoe Wallwork /*@ 768cc2eee55SJoe Wallwork DMPlexMetricGetVerbosity - Get the verbosity of the mesh adaptation package 769cc2eee55SJoe Wallwork 77060225df5SJacob Faibussowitsch Input Parameters: 7712fe279fdSBarry Smith . dm - The `DM` 772cc2eee55SJoe Wallwork 77360225df5SJacob Faibussowitsch Output Parameters: 774cc2eee55SJoe Wallwork . verbosity - The verbosity, where -1 is silent and 10 is maximum 775cc2eee55SJoe Wallwork 776cb7bfe8cSJoe Wallwork Level: beginner 777cb7bfe8cSJoe Wallwork 7782fe279fdSBarry Smith Note: 779cb7bfe8cSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 780cb7bfe8cSJoe Wallwork 7812fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricSetVerbosity()`, `DMPlexMetricGetNumIterations()` 782cb7bfe8cSJoe Wallwork @*/ 783d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricGetVerbosity(DM dm, PetscInt *verbosity) 784d71ae5a4SJacob Faibussowitsch { 785cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 786cc2eee55SJoe Wallwork 787cc2eee55SJoe Wallwork PetscFunctionBegin; 788bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 789cc2eee55SJoe Wallwork *verbosity = plex->metricCtx->verbosity; 7903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 791cc2eee55SJoe Wallwork } 792cc2eee55SJoe Wallwork 793cb7bfe8cSJoe Wallwork /*@ 794cc2eee55SJoe Wallwork DMPlexMetricSetNumIterations - Set the number of parallel adaptation iterations 795cc2eee55SJoe Wallwork 79660225df5SJacob Faibussowitsch Input Parameters: 7972fe279fdSBarry Smith + dm - The `DM` 798cc2eee55SJoe Wallwork - numIter - the number of parallel adaptation iterations 799cc2eee55SJoe Wallwork 800cb7bfe8cSJoe Wallwork Level: beginner 801cb7bfe8cSJoe Wallwork 8022fe279fdSBarry Smith Note: 803cb7bfe8cSJoe Wallwork This is only used by ParMmg (not Pragmatic or Mmg). 804cc2eee55SJoe Wallwork 8052fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricSetVerbosity()`, `DMPlexMetricGetNumIterations()` 806cb7bfe8cSJoe Wallwork @*/ 807d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricSetNumIterations(DM dm, PetscInt numIter) 808d71ae5a4SJacob Faibussowitsch { 809cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 810cc2eee55SJoe Wallwork 811cc2eee55SJoe Wallwork PetscFunctionBegin; 812bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 813cc2eee55SJoe Wallwork plex->metricCtx->numIter = numIter; 8143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 815cc2eee55SJoe Wallwork } 816cc2eee55SJoe Wallwork 817cb7bfe8cSJoe Wallwork /*@ 818cc2eee55SJoe Wallwork DMPlexMetricGetNumIterations - Get the number of parallel adaptation iterations 819cc2eee55SJoe Wallwork 82060225df5SJacob Faibussowitsch Input Parameters: 8212fe279fdSBarry Smith . dm - The `DM` 822cc2eee55SJoe Wallwork 82360225df5SJacob Faibussowitsch Output Parameters: 824cc2eee55SJoe Wallwork . numIter - the number of parallel adaptation iterations 825cc2eee55SJoe Wallwork 826cb7bfe8cSJoe Wallwork Level: beginner 827cb7bfe8cSJoe Wallwork 8282fe279fdSBarry Smith Note: 829cb7bfe8cSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic or Mmg). 830cc2eee55SJoe Wallwork 8312fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricSetNumIterations()`, `DMPlexMetricGetVerbosity()` 832cb7bfe8cSJoe Wallwork @*/ 833d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricGetNumIterations(DM dm, PetscInt *numIter) 834d71ae5a4SJacob Faibussowitsch { 835cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *)dm->data; 836cc2eee55SJoe Wallwork 837cc2eee55SJoe Wallwork PetscFunctionBegin; 838bc00d7afSJoe Wallwork if (!plex->metricCtx) PetscCall(DMPlexMetricSetFromOptions(dm)); 839cc2eee55SJoe Wallwork *numIter = plex->metricCtx->numIter; 8403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 841cc2eee55SJoe Wallwork } 842cc2eee55SJoe Wallwork 84366976f2fSJacob Faibussowitsch static PetscErrorCode DMPlexP1FieldCreate_Private(DM dm, PetscInt f, PetscInt size, Vec *metric) 844d71ae5a4SJacob Faibussowitsch { 84520282da2SJoe Wallwork MPI_Comm comm; 84620282da2SJoe Wallwork PetscFE fe; 84720282da2SJoe Wallwork PetscInt dim; 84820282da2SJoe Wallwork 84920282da2SJoe Wallwork PetscFunctionBegin; 85020282da2SJoe Wallwork /* Extract metadata from dm */ 8519566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 8529566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 85320282da2SJoe Wallwork 85420282da2SJoe Wallwork /* Create a P1 field of the requested size */ 8559566063dSJacob Faibussowitsch PetscCall(PetscFECreateLagrange(comm, dim, size, PETSC_TRUE, 1, PETSC_DETERMINE, &fe)); 8569566063dSJacob Faibussowitsch PetscCall(DMSetField(dm, f, NULL, (PetscObject)fe)); 8579566063dSJacob Faibussowitsch PetscCall(DMCreateDS(dm)); 8589566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 8599566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dm, metric)); 8603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 86120282da2SJoe Wallwork } 86220282da2SJoe Wallwork 863cb7bfe8cSJoe Wallwork /*@ 86420282da2SJoe Wallwork DMPlexMetricCreate - Create a Riemannian metric field 86520282da2SJoe Wallwork 86660225df5SJacob Faibussowitsch Input Parameters: 8672fe279fdSBarry Smith + dm - The `DM` 86820282da2SJoe Wallwork - f - The field number to use 86920282da2SJoe Wallwork 87060225df5SJacob Faibussowitsch Output Parameter: 87120282da2SJoe Wallwork . metric - The metric 87220282da2SJoe Wallwork 8732fe279fdSBarry Smith Options Database Key: 8742fe279fdSBarry Smith . -dm_adaptor <pragmatic/mmg/parmmg> - specify dm adaptor to use 87520282da2SJoe Wallwork 8762fe279fdSBarry Smith Options Database Keys for Mmg and ParMmg: 8772fe279fdSBarry Smith + -dm_plex_metric_gradation_factor - Maximum ratio by which edge lengths may grow during gradation 8782fe279fdSBarry Smith . -dm_plex_metric_num_iterations - Number of parallel mesh adaptation iterations for ParMmg 8792fe279fdSBarry Smith . -dm_plex_metric_no_insert - Should node insertion/deletion be turned off? 8802fe279fdSBarry Smith . -dm_plex_metric_no_swap - Should facet swapping be turned off? 8812fe279fdSBarry Smith . -dm_plex_metric_no_move - Should node movement be turned off? 8822fe279fdSBarry Smith - -dm_plex_metric_verbosity - Choose a verbosity level from -1 (silent) to 10 (maximum). 88331b70465SJoe Wallwork 8842fe279fdSBarry Smith Options Database Keys for Riemannian metrics: 885cb7bfe8cSJoe Wallwork + -dm_plex_metric_isotropic - Is the metric isotropic? 88693520041SJoe Wallwork . -dm_plex_metric_uniform - Is the metric uniform? 887cb7bfe8cSJoe Wallwork . -dm_plex_metric_restrict_anisotropy_first - Should anisotropy be restricted before normalization? 888cb7bfe8cSJoe Wallwork . -dm_plex_metric_h_min - Minimum tolerated metric magnitude 889cb7bfe8cSJoe Wallwork . -dm_plex_metric_h_max - Maximum tolerated metric magnitude 890cb7bfe8cSJoe Wallwork . -dm_plex_metric_a_max - Maximum tolerated anisotropy 891cb7bfe8cSJoe Wallwork . -dm_plex_metric_p - L-p normalization order 89267b8a455SSatish Balay - -dm_plex_metric_target_complexity - Target metric complexity 893cb7bfe8cSJoe Wallwork 8942fe279fdSBarry Smith Level: beginner 895cb7bfe8cSJoe Wallwork 8962fe279fdSBarry Smith Note: 8972fe279fdSBarry Smith It is assumed that the `DM` is comprised of simplices. 898cb7bfe8cSJoe Wallwork 8992fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricCreateUniform()`, `DMPlexMetricCreateIsotropic()` 900cb7bfe8cSJoe Wallwork @*/ 901d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricCreate(DM dm, PetscInt f, Vec *metric) 902d71ae5a4SJacob Faibussowitsch { 90393520041SJoe Wallwork PetscBool isotropic, uniform; 90420282da2SJoe Wallwork PetscInt coordDim, Nd; 90520282da2SJoe Wallwork 90620282da2SJoe Wallwork PetscFunctionBegin; 9079566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &coordDim)); 90820282da2SJoe Wallwork Nd = coordDim * coordDim; 9099566063dSJacob Faibussowitsch PetscCall(DMPlexMetricIsUniform(dm, &uniform)); 9109566063dSJacob Faibussowitsch PetscCall(DMPlexMetricIsIsotropic(dm, &isotropic)); 91193520041SJoe Wallwork if (uniform) { 91293520041SJoe Wallwork MPI_Comm comm; 91393520041SJoe Wallwork 9149566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 915bc00d7afSJoe Wallwork PetscCheck(isotropic, comm, PETSC_ERR_SUP, "Uniform anisotropic metrics not supported"); 9169566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, metric)); 9179566063dSJacob Faibussowitsch PetscCall(VecSetSizes(*metric, 1, PETSC_DECIDE)); 9189566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(*metric)); 919f6db075bSJoe Wallwork } else if (isotropic) PetscCall(DMPlexP1FieldCreate_Private(dm, f, 1, metric)); 920f6db075bSJoe Wallwork else PetscCall(DMPlexP1FieldCreate_Private(dm, f, Nd, metric)); 9213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 92220282da2SJoe Wallwork } 92320282da2SJoe Wallwork 924cb7bfe8cSJoe Wallwork /*@ 92520282da2SJoe Wallwork DMPlexMetricCreateUniform - Construct a uniform isotropic metric 92620282da2SJoe Wallwork 92760225df5SJacob Faibussowitsch Input Parameters: 9282fe279fdSBarry Smith + dm - The `DM` 92920282da2SJoe Wallwork . f - The field number to use 93020282da2SJoe Wallwork - alpha - Scaling parameter for the diagonal 93120282da2SJoe Wallwork 93260225df5SJacob Faibussowitsch Output Parameter: 93320282da2SJoe Wallwork . metric - The uniform metric 93420282da2SJoe Wallwork 93520282da2SJoe Wallwork Level: beginner 93620282da2SJoe Wallwork 9372fe279fdSBarry Smith Note: 9382fe279fdSBarry Smith In this case, the metric is constant in space and so is only specified for a single vertex. 93920282da2SJoe Wallwork 9402fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricCreate()`, `DMPlexMetricCreateIsotropic()` 941cb7bfe8cSJoe Wallwork @*/ 942d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricCreateUniform(DM dm, PetscInt f, PetscReal alpha, Vec *metric) 943d71ae5a4SJacob Faibussowitsch { 94420282da2SJoe Wallwork PetscFunctionBegin; 9459566063dSJacob Faibussowitsch PetscCall(DMPlexMetricSetUniform(dm, PETSC_TRUE)); 9469566063dSJacob Faibussowitsch PetscCall(DMPlexMetricCreate(dm, f, metric)); 9472c71b3e2SJacob Faibussowitsch PetscCheck(alpha, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Uniform metric scaling is undefined"); 948bc00d7afSJoe Wallwork PetscCheck(alpha > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Uniform metric scaling should be in (0, inf)"); 9499566063dSJacob Faibussowitsch PetscCall(VecSet(*metric, alpha)); 9509566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(*metric)); 9519566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(*metric)); 9523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 95320282da2SJoe Wallwork } 95420282da2SJoe Wallwork 955d71ae5a4SJacob Faibussowitsch static void identity(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 956d71ae5a4SJacob Faibussowitsch { 95793520041SJoe Wallwork f0[0] = u[0]; 95893520041SJoe Wallwork } 95993520041SJoe Wallwork 960cb7bfe8cSJoe Wallwork /*@ 96120282da2SJoe Wallwork DMPlexMetricCreateIsotropic - Construct an isotropic metric from an error indicator 96220282da2SJoe Wallwork 96360225df5SJacob Faibussowitsch Input Parameters: 9642fe279fdSBarry Smith + dm - The `DM` 96520282da2SJoe Wallwork . f - The field number to use 96620282da2SJoe Wallwork - indicator - The error indicator 96720282da2SJoe Wallwork 96860225df5SJacob Faibussowitsch Output Parameter: 96920282da2SJoe Wallwork . metric - The isotropic metric 97020282da2SJoe Wallwork 97120282da2SJoe Wallwork Level: beginner 97220282da2SJoe Wallwork 97320282da2SJoe Wallwork Notes: 9742fe279fdSBarry Smith It is assumed that the `DM` is comprised of simplices. 97520282da2SJoe Wallwork 97693520041SJoe Wallwork The indicator needs to be a scalar field. If it is not defined vertex-wise, then it is projected appropriately. 97720282da2SJoe Wallwork 9782fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricCreate()`, `DMPlexMetricCreateUniform()` 979cb7bfe8cSJoe Wallwork @*/ 980d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricCreateIsotropic(DM dm, PetscInt f, Vec indicator, Vec *metric) 981d71ae5a4SJacob Faibussowitsch { 98293520041SJoe Wallwork PetscInt m, n; 98320282da2SJoe Wallwork 98420282da2SJoe Wallwork PetscFunctionBegin; 9859566063dSJacob Faibussowitsch PetscCall(DMPlexMetricSetIsotropic(dm, PETSC_TRUE)); 9869566063dSJacob Faibussowitsch PetscCall(DMPlexMetricCreate(dm, f, metric)); 9879566063dSJacob Faibussowitsch PetscCall(VecGetSize(indicator, &m)); 9889566063dSJacob Faibussowitsch PetscCall(VecGetSize(*metric, &n)); 9899566063dSJacob Faibussowitsch if (m == n) PetscCall(VecCopy(indicator, *metric)); 99093520041SJoe Wallwork else { 99193520041SJoe Wallwork DM dmIndi; 9929371c9d4SSatish Balay void (*funcs[1])(PetscInt, PetscInt, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]); 99393520041SJoe Wallwork 9949566063dSJacob Faibussowitsch PetscCall(VecGetDM(indicator, &dmIndi)); 99593520041SJoe Wallwork funcs[0] = identity; 9969566063dSJacob Faibussowitsch PetscCall(DMProjectFieldLocal(dmIndi, 0.0, indicator, funcs, INSERT_VALUES, *metric)); 99720282da2SJoe Wallwork } 9983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 99920282da2SJoe Wallwork } 100020282da2SJoe Wallwork 1001f6db075bSJoe Wallwork /*@ 1002f6db075bSJoe Wallwork DMPlexMetricDeterminantCreate - Create the determinant field for a Riemannian metric 1003f6db075bSJoe Wallwork 100460225df5SJacob Faibussowitsch Input Parameters: 10052fe279fdSBarry Smith + dm - The `DM` of the metric field 1006f6db075bSJoe Wallwork - f - The field number to use 1007f6db075bSJoe Wallwork 100860225df5SJacob Faibussowitsch Output Parameters: 1009f6db075bSJoe Wallwork + determinant - The determinant field 10102fe279fdSBarry Smith - dmDet - The corresponding `DM` 1011f6db075bSJoe Wallwork 1012f6db075bSJoe Wallwork Level: beginner 1013f6db075bSJoe Wallwork 10142fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricCreateUniform()`, `DMPlexMetricCreateIsotropic()`, `DMPlexMetricCreate()` 1015f6db075bSJoe Wallwork @*/ 1016d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricDeterminantCreate(DM dm, PetscInt f, Vec *determinant, DM *dmDet) 1017d71ae5a4SJacob Faibussowitsch { 1018f6db075bSJoe Wallwork PetscBool uniform; 1019f6db075bSJoe Wallwork 1020f6db075bSJoe Wallwork PetscFunctionBegin; 1021f6db075bSJoe Wallwork PetscCall(DMPlexMetricIsUniform(dm, &uniform)); 1022f6db075bSJoe Wallwork PetscCall(DMClone(dm, dmDet)); 1023f6db075bSJoe Wallwork if (uniform) { 1024f6db075bSJoe Wallwork MPI_Comm comm; 1025f6db075bSJoe Wallwork 1026f6db075bSJoe Wallwork PetscCall(PetscObjectGetComm((PetscObject)*dmDet, &comm)); 1027f6db075bSJoe Wallwork PetscCall(VecCreate(comm, determinant)); 1028f6db075bSJoe Wallwork PetscCall(VecSetSizes(*determinant, 1, PETSC_DECIDE)); 1029f6db075bSJoe Wallwork PetscCall(VecSetFromOptions(*determinant)); 1030f6db075bSJoe Wallwork } else PetscCall(DMPlexP1FieldCreate_Private(*dmDet, f, 1, determinant)); 10313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1032f6db075bSJoe Wallwork } 1033f6db075bSJoe Wallwork 1034d71ae5a4SJacob Faibussowitsch static PetscErrorCode LAPACKsyevFail(PetscInt dim, PetscScalar Mpos[]) 1035d71ae5a4SJacob Faibussowitsch { 103682490253SJoe Wallwork PetscInt i, j; 103782490253SJoe Wallwork 103882490253SJoe Wallwork PetscFunctionBegin; 10393ba16761SJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "Failed to apply LAPACKsyev to the matrix\n")); 104082490253SJoe Wallwork for (i = 0; i < dim; ++i) { 10413ba16761SJacob Faibussowitsch if (i == 0) PetscCall(PetscPrintf(PETSC_COMM_SELF, " [[")); 10423ba16761SJacob Faibussowitsch else PetscCall(PetscPrintf(PETSC_COMM_SELF, " [")); 104382490253SJoe Wallwork for (j = 0; j < dim; ++j) { 10443ba16761SJacob Faibussowitsch if (j < dim - 1) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%15.8e, ", (double)PetscAbsScalar(Mpos[i * dim + j]))); 10453ba16761SJacob Faibussowitsch else PetscCall(PetscPrintf(PETSC_COMM_SELF, "%15.8e", (double)PetscAbsScalar(Mpos[i * dim + j]))); 104682490253SJoe Wallwork } 10473ba16761SJacob Faibussowitsch if (i < dim - 1) PetscCall(PetscPrintf(PETSC_COMM_SELF, "]\n")); 10483ba16761SJacob Faibussowitsch else PetscCall(PetscPrintf(PETSC_COMM_SELF, "]]\n")); 104982490253SJoe Wallwork } 10503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 105182490253SJoe Wallwork } 105282490253SJoe Wallwork 1053d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMetricModify_Private(PetscInt dim, PetscReal h_min, PetscReal h_max, PetscReal a_max, PetscScalar Mp[], PetscScalar *detMp) 1054d71ae5a4SJacob Faibussowitsch { 105520282da2SJoe Wallwork PetscInt i, j, k; 105620282da2SJoe Wallwork PetscReal *eigs, max_eig, l_min = 1.0 / (h_max * h_max), l_max = 1.0 / (h_min * h_min), la_min = 1.0 / (a_max * a_max); 105720282da2SJoe Wallwork PetscScalar *Mpos; 105820282da2SJoe Wallwork 105920282da2SJoe Wallwork PetscFunctionBegin; 10609566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(dim * dim, &Mpos, dim, &eigs)); 106120282da2SJoe Wallwork 106220282da2SJoe Wallwork /* Symmetrize */ 106320282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 106420282da2SJoe Wallwork Mpos[i * dim + i] = Mp[i * dim + i]; 106520282da2SJoe Wallwork for (j = i + 1; j < dim; ++j) { 106620282da2SJoe Wallwork Mpos[i * dim + j] = 0.5 * (Mp[i * dim + j] + Mp[j * dim + i]); 106720282da2SJoe Wallwork Mpos[j * dim + i] = Mpos[i * dim + j]; 106820282da2SJoe Wallwork } 106920282da2SJoe Wallwork } 107020282da2SJoe Wallwork 107120282da2SJoe Wallwork /* Compute eigendecomposition */ 107293520041SJoe Wallwork if (dim == 1) { 107393520041SJoe Wallwork /* Isotropic case */ 107493520041SJoe Wallwork eigs[0] = PetscRealPart(Mpos[0]); 107593520041SJoe Wallwork Mpos[0] = 1.0; 107693520041SJoe Wallwork } else { 107793520041SJoe Wallwork /* Anisotropic case */ 107820282da2SJoe Wallwork PetscScalar *work; 1079*835f2295SStefano Zampini PetscBLASInt lwork; 108020282da2SJoe Wallwork 1081*835f2295SStefano Zampini PetscCall(PetscBLASIntCast(5 * dim, &lwork)); 10829566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(5 * dim, &work)); 108320282da2SJoe Wallwork { 108420282da2SJoe Wallwork PetscBLASInt lierr; 108520282da2SJoe Wallwork PetscBLASInt nb; 108620282da2SJoe Wallwork 10879566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(dim, &nb)); 10889566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 108920282da2SJoe Wallwork #if defined(PETSC_USE_COMPLEX) 109020282da2SJoe Wallwork { 109120282da2SJoe Wallwork PetscReal *rwork; 10929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3 * dim, &rwork)); 1093792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &nb, Mpos, &nb, eigs, work, &lwork, rwork, &lierr)); 10949566063dSJacob Faibussowitsch PetscCall(PetscFree(rwork)); 109520282da2SJoe Wallwork } 109620282da2SJoe Wallwork #else 1097792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &nb, Mpos, &nb, eigs, work, &lwork, &lierr)); 109820282da2SJoe Wallwork #endif 109982490253SJoe Wallwork if (lierr) { 110082490253SJoe Wallwork for (i = 0; i < dim; ++i) { 110182490253SJoe Wallwork Mpos[i * dim + i] = Mp[i * dim + i]; 110282490253SJoe Wallwork for (j = i + 1; j < dim; ++j) { 110382490253SJoe Wallwork Mpos[i * dim + j] = 0.5 * (Mp[i * dim + j] + Mp[j * dim + i]); 110482490253SJoe Wallwork Mpos[j * dim + i] = Mpos[i * dim + j]; 110582490253SJoe Wallwork } 110682490253SJoe Wallwork } 11073ba16761SJacob Faibussowitsch PetscCall(LAPACKsyevFail(dim, Mpos)); 1108*835f2295SStefano Zampini SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in LAPACK routine %" PetscBLASInt_FMT, lierr); 110982490253SJoe Wallwork } 11109566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 111120282da2SJoe Wallwork } 11129566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 111320282da2SJoe Wallwork } 111420282da2SJoe Wallwork 111520282da2SJoe Wallwork /* Reflect to positive orthant and enforce maximum and minimum size */ 111620282da2SJoe Wallwork max_eig = 0.0; 111720282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 111820282da2SJoe Wallwork eigs[i] = PetscMin(l_max, PetscMax(l_min, PetscAbsReal(eigs[i]))); 111920282da2SJoe Wallwork max_eig = PetscMax(eigs[i], max_eig); 112020282da2SJoe Wallwork } 112120282da2SJoe Wallwork 11223f07679eSJoe Wallwork /* Enforce maximum anisotropy and compute determinant */ 11233f07679eSJoe Wallwork *detMp = 1.0; 112420282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 1125ac314011SJoe Wallwork if (a_max >= 1.0) eigs[i] = PetscMax(eigs[i], max_eig * la_min); 11263f07679eSJoe Wallwork *detMp *= eigs[i]; 112720282da2SJoe Wallwork } 112820282da2SJoe Wallwork 112920282da2SJoe Wallwork /* Reconstruct Hessian */ 113020282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 113120282da2SJoe Wallwork for (j = 0; j < dim; ++j) { 113220282da2SJoe Wallwork Mp[i * dim + j] = 0.0; 1133ad540459SPierre Jolivet for (k = 0; k < dim; ++k) Mp[i * dim + j] += Mpos[k * dim + i] * eigs[k] * Mpos[k * dim + j]; 113420282da2SJoe Wallwork } 113520282da2SJoe Wallwork } 11369566063dSJacob Faibussowitsch PetscCall(PetscFree2(Mpos, eigs)); 11373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 113820282da2SJoe Wallwork } 113920282da2SJoe Wallwork 1140cb7bfe8cSJoe Wallwork /*@ 114120282da2SJoe Wallwork DMPlexMetricEnforceSPD - Enforce symmetric positive-definiteness of a metric 114220282da2SJoe Wallwork 114360225df5SJacob Faibussowitsch Input Parameters: 11442fe279fdSBarry Smith + dm - The `DM` 11453f07679eSJoe Wallwork . metricIn - The metric 114699abec2bSJoe Wallwork . restrictSizes - Should maximum/minimum metric magnitudes be enforced? 11473f07679eSJoe Wallwork - restrictAnisotropy - Should maximum anisotropy be enforced? 114820282da2SJoe Wallwork 114960225df5SJacob Faibussowitsch Output Parameters: 11503f07679eSJoe Wallwork + metricOut - The metric 11513f07679eSJoe Wallwork - determinant - Its determinant 115220282da2SJoe Wallwork 11532fe279fdSBarry Smith Options Database Keys: 115493520041SJoe Wallwork + -dm_plex_metric_isotropic - Is the metric isotropic? 115593520041SJoe Wallwork . -dm_plex_metric_uniform - Is the metric uniform? 115693520041SJoe Wallwork . -dm_plex_metric_h_min - Minimum tolerated metric magnitude 1157cb7bfe8cSJoe Wallwork . -dm_plex_metric_h_max - Maximum tolerated metric magnitude 1158cb7bfe8cSJoe Wallwork - -dm_plex_metric_a_max - Maximum tolerated anisotropy 1159cb7bfe8cSJoe Wallwork 11602fe279fdSBarry Smith Level: beginner 11612fe279fdSBarry Smith 11622fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricNormalize()`, `DMPlexMetricIntersection()` 1163cb7bfe8cSJoe Wallwork @*/ 1164d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricEnforceSPD(DM dm, Vec metricIn, PetscBool restrictSizes, PetscBool restrictAnisotropy, Vec metricOut, Vec determinant) 1165d71ae5a4SJacob Faibussowitsch { 11663f07679eSJoe Wallwork DM dmDet; 116793520041SJoe Wallwork PetscBool isotropic, uniform; 116820282da2SJoe Wallwork PetscInt dim, vStart, vEnd, v; 11693f07679eSJoe Wallwork PetscScalar *met, *det; 117061451c10SMatthew G. Knepley PetscReal h_min = 1.0e-30, h_max = 1.0e+30, a_max = 1.0e+15; 117120282da2SJoe Wallwork 117220282da2SJoe Wallwork PetscFunctionBegin; 11739566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_MetricEnforceSPD, 0, 0, 0, 0)); 117420282da2SJoe Wallwork 117520282da2SJoe Wallwork /* Extract metadata from dm */ 11769566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 117720282da2SJoe Wallwork if (restrictSizes) { 11789566063dSJacob Faibussowitsch PetscCall(DMPlexMetricGetMinimumMagnitude(dm, &h_min)); 11799566063dSJacob Faibussowitsch PetscCall(DMPlexMetricGetMaximumMagnitude(dm, &h_max)); 118099abec2bSJoe Wallwork h_min = PetscMax(h_min, 1.0e-30); 118199abec2bSJoe Wallwork h_max = PetscMin(h_max, 1.0e+30); 1182bc00d7afSJoe Wallwork PetscCheck(h_min < h_max, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Minimum metric magnitude should be smaller than maximum metric magnitude"); 118399abec2bSJoe Wallwork } 118499abec2bSJoe Wallwork if (restrictAnisotropy) { 11859566063dSJacob Faibussowitsch PetscCall(DMPlexMetricGetMaximumAnisotropy(dm, &a_max)); 118699abec2bSJoe Wallwork a_max = PetscMin(a_max, 1.0e+30); 118720282da2SJoe Wallwork } 118820282da2SJoe Wallwork 118993520041SJoe Wallwork /* Setup output metric */ 11905241a91fSJoe Wallwork PetscCall(VecCopy(metricIn, metricOut)); 119193520041SJoe Wallwork 119293520041SJoe Wallwork /* Enforce SPD and extract determinant */ 11935241a91fSJoe Wallwork PetscCall(VecGetArray(metricOut, &met)); 11949566063dSJacob Faibussowitsch PetscCall(DMPlexMetricIsUniform(dm, &uniform)); 11959566063dSJacob Faibussowitsch PetscCall(DMPlexMetricIsIsotropic(dm, &isotropic)); 119693520041SJoe Wallwork if (uniform) { 1197d1a5b989SMatthew G. Knepley PetscCheck(isotropic, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Uniform anisotropic metrics cannot exist"); 119893520041SJoe Wallwork 119993520041SJoe Wallwork /* Uniform case */ 12005241a91fSJoe Wallwork PetscCall(VecGetArray(determinant, &det)); 12019566063dSJacob Faibussowitsch PetscCall(DMPlexMetricModify_Private(1, h_min, h_max, a_max, met, det)); 12025241a91fSJoe Wallwork PetscCall(VecRestoreArray(determinant, &det)); 120393520041SJoe Wallwork } else { 120493520041SJoe Wallwork /* Spatially varying case */ 120593520041SJoe Wallwork PetscInt nrow; 120693520041SJoe Wallwork 120793520041SJoe Wallwork if (isotropic) nrow = 1; 120893520041SJoe Wallwork else nrow = dim; 12095241a91fSJoe Wallwork PetscCall(VecGetDM(determinant, &dmDet)); 12109566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 12115241a91fSJoe Wallwork PetscCall(VecGetArray(determinant, &det)); 121220282da2SJoe Wallwork for (v = vStart; v < vEnd; ++v) { 12133f07679eSJoe Wallwork PetscScalar *vmet, *vdet; 12149566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRef(dm, v, met, &vmet)); 12159566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRef(dmDet, v, det, &vdet)); 12169566063dSJacob Faibussowitsch PetscCall(DMPlexMetricModify_Private(nrow, h_min, h_max, a_max, vmet, vdet)); 121720282da2SJoe Wallwork } 12185241a91fSJoe Wallwork PetscCall(VecRestoreArray(determinant, &det)); 121993520041SJoe Wallwork } 12205241a91fSJoe Wallwork PetscCall(VecRestoreArray(metricOut, &met)); 1221fe902aceSJoe Wallwork 12229566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_MetricEnforceSPD, 0, 0, 0, 0)); 12233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 122420282da2SJoe Wallwork } 122520282da2SJoe Wallwork 1226d71ae5a4SJacob Faibussowitsch static void detMFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 1227d71ae5a4SJacob Faibussowitsch { 122820282da2SJoe Wallwork const PetscScalar p = constants[0]; 122920282da2SJoe Wallwork 1230985ad86eSJose E. Roman f0[0] = PetscPowScalar(u[0], p / (2.0 * p + dim)); 123120282da2SJoe Wallwork } 123220282da2SJoe Wallwork 1233cb7bfe8cSJoe Wallwork /*@ 123420282da2SJoe Wallwork DMPlexMetricNormalize - Apply L-p normalization to a metric 123520282da2SJoe Wallwork 123660225df5SJacob Faibussowitsch Input Parameters: 12372fe279fdSBarry Smith + dm - The `DM` 123820282da2SJoe Wallwork . metricIn - The unnormalized metric 123916522936SJoe Wallwork . restrictSizes - Should maximum/minimum metric magnitudes be enforced? 124016522936SJoe Wallwork - restrictAnisotropy - Should maximum metric anisotropy be enforced? 124120282da2SJoe Wallwork 124260225df5SJacob Faibussowitsch Output Parameters: 12432fe279fdSBarry Smith + metricOut - The normalized metric 12442fe279fdSBarry Smith - determinant - computed determinant 124520282da2SJoe Wallwork 12462fe279fdSBarry Smith Options Database Keys: 124793520041SJoe Wallwork + -dm_plex_metric_isotropic - Is the metric isotropic? 124893520041SJoe Wallwork . -dm_plex_metric_uniform - Is the metric uniform? 124993520041SJoe Wallwork . -dm_plex_metric_restrict_anisotropy_first - Should anisotropy be restricted before normalization? 1250cb7bfe8cSJoe Wallwork . -dm_plex_metric_h_min - Minimum tolerated metric magnitude 1251cb7bfe8cSJoe Wallwork . -dm_plex_metric_h_max - Maximum tolerated metric magnitude 1252cb7bfe8cSJoe Wallwork . -dm_plex_metric_a_max - Maximum tolerated anisotropy 1253cb7bfe8cSJoe Wallwork . -dm_plex_metric_p - L-p normalization order 1254cb7bfe8cSJoe Wallwork - -dm_plex_metric_target_complexity - Target metric complexity 1255cb7bfe8cSJoe Wallwork 12562fe279fdSBarry Smith Level: beginner 12572fe279fdSBarry Smith 12582fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricEnforceSPD()`, `DMPlexMetricIntersection()` 1259cb7bfe8cSJoe Wallwork @*/ 1260d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricNormalize(DM dm, Vec metricIn, PetscBool restrictSizes, PetscBool restrictAnisotropy, Vec metricOut, Vec determinant) 1261d71ae5a4SJacob Faibussowitsch { 12623f07679eSJoe Wallwork DM dmDet; 126320282da2SJoe Wallwork MPI_Comm comm; 126493520041SJoe Wallwork PetscBool restrictAnisotropyFirst, isotropic, uniform; 126520282da2SJoe Wallwork PetscDS ds; 126620282da2SJoe Wallwork PetscInt dim, Nd, vStart, vEnd, v, i; 12673f07679eSJoe Wallwork PetscScalar *met, *det, integral, constants[1]; 126893520041SJoe Wallwork PetscReal p, h_min = 1.0e-30, h_max = 1.0e+30, a_max = 0.0, factGlob, fact, target, realIntegral; 126920282da2SJoe Wallwork 127020282da2SJoe Wallwork PetscFunctionBegin; 12719566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_MetricNormalize, 0, 0, 0, 0)); 127220282da2SJoe Wallwork 127320282da2SJoe Wallwork /* Extract metadata from dm */ 12749566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 12759566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 12769566063dSJacob Faibussowitsch PetscCall(DMPlexMetricIsUniform(dm, &uniform)); 12779566063dSJacob Faibussowitsch PetscCall(DMPlexMetricIsIsotropic(dm, &isotropic)); 127893520041SJoe Wallwork if (isotropic) Nd = 1; 127993520041SJoe Wallwork else Nd = dim * dim; 128020282da2SJoe Wallwork 128120282da2SJoe Wallwork /* Set up metric and ensure it is SPD */ 12829566063dSJacob Faibussowitsch PetscCall(DMPlexMetricRestrictAnisotropyFirst(dm, &restrictAnisotropyFirst)); 12835241a91fSJoe Wallwork PetscCall(DMPlexMetricEnforceSPD(dm, metricIn, PETSC_FALSE, (PetscBool)(restrictAnisotropy && restrictAnisotropyFirst), metricOut, determinant)); 128420282da2SJoe Wallwork 128520282da2SJoe Wallwork /* Compute global normalization factor */ 12869566063dSJacob Faibussowitsch PetscCall(DMPlexMetricGetTargetComplexity(dm, &target)); 12879566063dSJacob Faibussowitsch PetscCall(DMPlexMetricGetNormalizationOrder(dm, &p)); 128816522936SJoe Wallwork constants[0] = p; 128993520041SJoe Wallwork if (uniform) { 1290bc00d7afSJoe Wallwork PetscCheck(isotropic, comm, PETSC_ERR_SUP, "Uniform anisotropic metrics not supported"); 129193520041SJoe Wallwork DM dmTmp; 129293520041SJoe Wallwork Vec tmp; 129393520041SJoe Wallwork 12949566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &dmTmp)); 12959566063dSJacob Faibussowitsch PetscCall(DMPlexP1FieldCreate_Private(dmTmp, 0, 1, &tmp)); 12969566063dSJacob Faibussowitsch PetscCall(VecGetArray(determinant, &det)); 12979566063dSJacob Faibussowitsch PetscCall(VecSet(tmp, det[0])); 12989566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(determinant, &det)); 12999566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmTmp, &ds)); 13009566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(ds, 1, constants)); 13019566063dSJacob Faibussowitsch PetscCall(PetscDSSetObjective(ds, 0, detMFunc)); 13029566063dSJacob Faibussowitsch PetscCall(DMPlexComputeIntegralFEM(dmTmp, tmp, &integral, NULL)); 13039566063dSJacob Faibussowitsch PetscCall(VecDestroy(&tmp)); 13049566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmTmp)); 130593520041SJoe Wallwork } else { 13069566063dSJacob Faibussowitsch PetscCall(VecGetDM(determinant, &dmDet)); 13079566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmDet, &ds)); 13089566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(ds, 1, constants)); 13099566063dSJacob Faibussowitsch PetscCall(PetscDSSetObjective(ds, 0, detMFunc)); 13109566063dSJacob Faibussowitsch PetscCall(DMPlexComputeIntegralFEM(dmDet, determinant, &integral, NULL)); 131193520041SJoe Wallwork } 13123f07679eSJoe Wallwork realIntegral = PetscRealPart(integral); 1313bc00d7afSJoe Wallwork PetscCheck(realIntegral > 1.0e-30, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Global metric normalization factor must be in (0, inf). Is the input metric positive-definite?"); 13143f07679eSJoe Wallwork factGlob = PetscPowReal(target / realIntegral, 2.0 / dim); 131520282da2SJoe Wallwork 131620282da2SJoe Wallwork /* Apply local scaling */ 131720282da2SJoe Wallwork if (restrictSizes) { 13189566063dSJacob Faibussowitsch PetscCall(DMPlexMetricGetMinimumMagnitude(dm, &h_min)); 13199566063dSJacob Faibussowitsch PetscCall(DMPlexMetricGetMaximumMagnitude(dm, &h_max)); 132016522936SJoe Wallwork h_min = PetscMax(h_min, 1.0e-30); 132116522936SJoe Wallwork h_max = PetscMin(h_max, 1.0e+30); 1322bc00d7afSJoe Wallwork PetscCheck(h_min < h_max, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Minimum metric magnitude should be smaller than maximum metric magnitude"); 132316522936SJoe Wallwork } 132416522936SJoe Wallwork if (restrictAnisotropy && !restrictAnisotropyFirst) { 13259566063dSJacob Faibussowitsch PetscCall(DMPlexMetricGetMaximumAnisotropy(dm, &a_max)); 132616522936SJoe Wallwork a_max = PetscMin(a_max, 1.0e+30); 132720282da2SJoe Wallwork } 13285241a91fSJoe Wallwork PetscCall(VecGetArray(metricOut, &met)); 13299566063dSJacob Faibussowitsch PetscCall(VecGetArray(determinant, &det)); 133093520041SJoe Wallwork if (uniform) { 133193520041SJoe Wallwork /* Uniform case */ 133293520041SJoe Wallwork met[0] *= factGlob * PetscPowReal(PetscAbsScalar(det[0]), -1.0 / (2 * p + dim)); 13339566063dSJacob Faibussowitsch if (restrictSizes) PetscCall(DMPlexMetricModify_Private(1, h_min, h_max, a_max, met, det)); 133493520041SJoe Wallwork } else { 133593520041SJoe Wallwork /* Spatially varying case */ 133693520041SJoe Wallwork PetscInt nrow; 133793520041SJoe Wallwork 133893520041SJoe Wallwork if (isotropic) nrow = 1; 133993520041SJoe Wallwork else nrow = dim; 13409566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 13415241a91fSJoe Wallwork PetscCall(VecGetDM(determinant, &dmDet)); 134220282da2SJoe Wallwork for (v = vStart; v < vEnd; ++v) { 13433f07679eSJoe Wallwork PetscScalar *Mp, *detM; 134420282da2SJoe Wallwork 13459566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRef(dm, v, met, &Mp)); 13469566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRef(dmDet, v, det, &detM)); 13473f07679eSJoe Wallwork fact = factGlob * PetscPowReal(PetscAbsScalar(detM[0]), -1.0 / (2 * p + dim)); 134820282da2SJoe Wallwork for (i = 0; i < Nd; ++i) Mp[i] *= fact; 13499566063dSJacob Faibussowitsch if (restrictSizes) PetscCall(DMPlexMetricModify_Private(nrow, h_min, h_max, a_max, Mp, detM)); 135093520041SJoe Wallwork } 135120282da2SJoe Wallwork } 13529566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(determinant, &det)); 13535241a91fSJoe Wallwork PetscCall(VecRestoreArray(metricOut, &met)); 135420282da2SJoe Wallwork 13559566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_MetricNormalize, 0, 0, 0, 0)); 13563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 135720282da2SJoe Wallwork } 135820282da2SJoe Wallwork 1359cb7bfe8cSJoe Wallwork /*@ 136020282da2SJoe Wallwork DMPlexMetricAverage - Compute the average of a list of metrics 136120282da2SJoe Wallwork 1362f1a722f8SMatthew G. Knepley Input Parameters: 13632fe279fdSBarry Smith + dm - The `DM` 136420282da2SJoe Wallwork . numMetrics - The number of metrics to be averaged 136520282da2SJoe Wallwork . weights - Weights for the average 136620282da2SJoe Wallwork - metrics - The metrics to be averaged 136720282da2SJoe Wallwork 136820282da2SJoe Wallwork Output Parameter: 136920282da2SJoe Wallwork . metricAvg - The averaged metric 137020282da2SJoe Wallwork 137120282da2SJoe Wallwork Level: beginner 137220282da2SJoe Wallwork 137320282da2SJoe Wallwork Notes: 137420282da2SJoe Wallwork The weights should sum to unity. 137520282da2SJoe Wallwork 137620282da2SJoe Wallwork If weights are not provided then an unweighted average is used. 137720282da2SJoe Wallwork 13782fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricAverage2()`, `DMPlexMetricAverage3()`, `DMPlexMetricIntersection()` 1379cb7bfe8cSJoe Wallwork @*/ 1380d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricAverage(DM dm, PetscInt numMetrics, PetscReal weights[], Vec metrics[], Vec metricAvg) 1381d71ae5a4SJacob Faibussowitsch { 138220282da2SJoe Wallwork PetscBool haveWeights = PETSC_TRUE; 138393520041SJoe Wallwork PetscInt i, m, n; 138420282da2SJoe Wallwork PetscReal sum = 0.0, tol = 1.0e-10; 138520282da2SJoe Wallwork 138620282da2SJoe Wallwork PetscFunctionBegin; 13879566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_MetricAverage, 0, 0, 0, 0)); 138863a3b9bcSJacob Faibussowitsch PetscCheck(numMetrics >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot average %" PetscInt_FMT " < 1 metrics", numMetrics); 13895241a91fSJoe Wallwork PetscCall(VecSet(metricAvg, 0.0)); 13905241a91fSJoe Wallwork PetscCall(VecGetSize(metricAvg, &m)); 139193520041SJoe Wallwork for (i = 0; i < numMetrics; ++i) { 13929566063dSJacob Faibussowitsch PetscCall(VecGetSize(metrics[i], &n)); 13935f80ce2aSJacob Faibussowitsch PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Averaging different metric types not implemented"); 139493520041SJoe Wallwork } 139520282da2SJoe Wallwork 139620282da2SJoe Wallwork /* Default to the unweighted case */ 139720282da2SJoe Wallwork if (!weights) { 13989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numMetrics, &weights)); 139920282da2SJoe Wallwork haveWeights = PETSC_FALSE; 1400ad540459SPierre Jolivet for (i = 0; i < numMetrics; ++i) weights[i] = 1.0 / numMetrics; 140120282da2SJoe Wallwork } 140220282da2SJoe Wallwork 140320282da2SJoe Wallwork /* Check weights sum to unity */ 140493520041SJoe Wallwork for (i = 0; i < numMetrics; ++i) sum += weights[i]; 14055f80ce2aSJacob Faibussowitsch PetscCheck(PetscAbsReal(sum - 1) <= tol, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Weights do not sum to unity"); 140620282da2SJoe Wallwork 140720282da2SJoe Wallwork /* Compute metric average */ 14085241a91fSJoe Wallwork for (i = 0; i < numMetrics; ++i) PetscCall(VecAXPY(metricAvg, weights[i], metrics[i])); 14099566063dSJacob Faibussowitsch if (!haveWeights) PetscCall(PetscFree(weights)); 1410fe902aceSJoe Wallwork 14119566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_MetricAverage, 0, 0, 0, 0)); 14123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 141320282da2SJoe Wallwork } 141420282da2SJoe Wallwork 1415cb7bfe8cSJoe Wallwork /*@ 141620282da2SJoe Wallwork DMPlexMetricAverage2 - Compute the unweighted average of two metrics 141720282da2SJoe Wallwork 1418f1a722f8SMatthew G. Knepley Input Parameters: 14192fe279fdSBarry Smith + dm - The `DM` 142020282da2SJoe Wallwork . metric1 - The first metric to be averaged 142120282da2SJoe Wallwork - metric2 - The second metric to be averaged 142220282da2SJoe Wallwork 142320282da2SJoe Wallwork Output Parameter: 142420282da2SJoe Wallwork . metricAvg - The averaged metric 142520282da2SJoe Wallwork 142620282da2SJoe Wallwork Level: beginner 142720282da2SJoe Wallwork 14282fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricAverage()`, `DMPlexMetricAverage3()` 1429cb7bfe8cSJoe Wallwork @*/ 1430d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricAverage2(DM dm, Vec metric1, Vec metric2, Vec metricAvg) 1431d71ae5a4SJacob Faibussowitsch { 143220282da2SJoe Wallwork PetscReal weights[2] = {0.5, 0.5}; 143320282da2SJoe Wallwork Vec metrics[2] = {metric1, metric2}; 143420282da2SJoe Wallwork 143520282da2SJoe Wallwork PetscFunctionBegin; 14369566063dSJacob Faibussowitsch PetscCall(DMPlexMetricAverage(dm, 2, weights, metrics, metricAvg)); 14373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 143820282da2SJoe Wallwork } 143920282da2SJoe Wallwork 1440cb7bfe8cSJoe Wallwork /*@ 144120282da2SJoe Wallwork DMPlexMetricAverage3 - Compute the unweighted average of three metrics 144220282da2SJoe Wallwork 1443f1a722f8SMatthew G. Knepley Input Parameters: 14442fe279fdSBarry Smith + dm - The `DM` 144520282da2SJoe Wallwork . metric1 - The first metric to be averaged 144620282da2SJoe Wallwork . metric2 - The second metric to be averaged 144720282da2SJoe Wallwork - metric3 - The third metric to be averaged 144820282da2SJoe Wallwork 144920282da2SJoe Wallwork Output Parameter: 145020282da2SJoe Wallwork . metricAvg - The averaged metric 145120282da2SJoe Wallwork 145220282da2SJoe Wallwork Level: beginner 145320282da2SJoe Wallwork 14542fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricAverage()`, `DMPlexMetricAverage2()` 1455cb7bfe8cSJoe Wallwork @*/ 1456d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricAverage3(DM dm, Vec metric1, Vec metric2, Vec metric3, Vec metricAvg) 1457d71ae5a4SJacob Faibussowitsch { 145820282da2SJoe Wallwork PetscReal weights[3] = {1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0}; 145920282da2SJoe Wallwork Vec metrics[3] = {metric1, metric2, metric3}; 146020282da2SJoe Wallwork 146120282da2SJoe Wallwork PetscFunctionBegin; 14629566063dSJacob Faibussowitsch PetscCall(DMPlexMetricAverage(dm, 3, weights, metrics, metricAvg)); 14633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 146420282da2SJoe Wallwork } 146520282da2SJoe Wallwork 1466d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMetricIntersection_Private(PetscInt dim, PetscScalar M1[], PetscScalar M2[]) 1467d71ae5a4SJacob Faibussowitsch { 146820282da2SJoe Wallwork PetscInt i, j, k, l, m; 1469e2606525SJoe Wallwork PetscReal *evals; 147020282da2SJoe Wallwork PetscScalar *evecs, *sqrtM1, *isqrtM1; 147120282da2SJoe Wallwork 147220282da2SJoe Wallwork PetscFunctionBegin; 147393520041SJoe Wallwork /* Isotropic case */ 147493520041SJoe Wallwork if (dim == 1) { 1475*835f2295SStefano Zampini M2[0] = PetscMax(PetscRealPart(M1[0]), PetscRealPart(M2[0])); 14763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 147793520041SJoe Wallwork } 147893520041SJoe Wallwork 147993520041SJoe Wallwork /* Anisotropic case */ 1480e2606525SJoe Wallwork PetscCall(PetscMalloc4(dim * dim, &evecs, dim * dim, &sqrtM1, dim * dim, &isqrtM1, dim, &evals)); 148120282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 1482ad540459SPierre Jolivet for (j = 0; j < dim; ++j) evecs[i * dim + j] = M1[i * dim + j]; 148320282da2SJoe Wallwork } 148420282da2SJoe Wallwork { 148520282da2SJoe Wallwork PetscScalar *work; 1486*835f2295SStefano Zampini PetscBLASInt lwork; 1487*835f2295SStefano Zampini 1488*835f2295SStefano Zampini PetscCall(PetscBLASIntCast(5 * dim, &lwork)); 14899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(5 * dim, &work)); 149020282da2SJoe Wallwork { 149120282da2SJoe Wallwork PetscBLASInt lierr, nb; 1492e2606525SJoe Wallwork PetscReal sqrtj; 149320282da2SJoe Wallwork 149420282da2SJoe Wallwork /* Compute eigendecomposition of M1 */ 14959566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(dim, &nb)); 14969566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 149720282da2SJoe Wallwork #if defined(PETSC_USE_COMPLEX) 149820282da2SJoe Wallwork { 149920282da2SJoe Wallwork PetscReal *rwork; 15009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3 * dim, &rwork)); 1501792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &nb, evecs, &nb, evals, work, &lwork, rwork, &lierr)); 15029566063dSJacob Faibussowitsch PetscCall(PetscFree(rwork)); 150320282da2SJoe Wallwork } 150420282da2SJoe Wallwork #else 1505792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &nb, evecs, &nb, evals, work, &lwork, &lierr)); 150620282da2SJoe Wallwork #endif 150782490253SJoe Wallwork if (lierr) { 15083ba16761SJacob Faibussowitsch PetscCall(LAPACKsyevFail(dim, M1)); 1509*835f2295SStefano Zampini SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in LAPACK routine %" PetscBLASInt_FMT, lierr); 151082490253SJoe Wallwork } 15119566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 151220282da2SJoe Wallwork 1513e2606525SJoe Wallwork /* Compute square root and the reciprocal thereof */ 151420282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 151520282da2SJoe Wallwork for (k = 0; k < dim; ++k) { 1516e2606525SJoe Wallwork sqrtM1[i * dim + k] = 0.0; 1517e2606525SJoe Wallwork isqrtM1[i * dim + k] = 0.0; 1518e2606525SJoe Wallwork for (j = 0; j < dim; ++j) { 1519e2606525SJoe Wallwork sqrtj = PetscSqrtReal(evals[j]); 1520e2606525SJoe Wallwork sqrtM1[i * dim + k] += evecs[j * dim + i] * sqrtj * evecs[j * dim + k]; 1521e2606525SJoe Wallwork isqrtM1[i * dim + k] += evecs[j * dim + i] * (1.0 / sqrtj) * evecs[j * dim + k]; 152220282da2SJoe Wallwork } 152320282da2SJoe Wallwork } 152420282da2SJoe Wallwork } 152520282da2SJoe Wallwork 1526e2606525SJoe Wallwork /* Map M2 into the space spanned by the eigenvectors of M1 */ 152720282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 152820282da2SJoe Wallwork for (l = 0; l < dim; ++l) { 1529e2606525SJoe Wallwork evecs[i * dim + l] = 0.0; 1530e2606525SJoe Wallwork for (j = 0; j < dim; ++j) { 1531ad540459SPierre Jolivet for (k = 0; k < dim; ++k) evecs[i * dim + l] += isqrtM1[j * dim + i] * M2[j * dim + k] * isqrtM1[k * dim + l]; 153220282da2SJoe Wallwork } 153320282da2SJoe Wallwork } 153420282da2SJoe Wallwork } 153520282da2SJoe Wallwork 153620282da2SJoe Wallwork /* Compute eigendecomposition */ 15379566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 153820282da2SJoe Wallwork #if defined(PETSC_USE_COMPLEX) 153920282da2SJoe Wallwork { 154020282da2SJoe Wallwork PetscReal *rwork; 15419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3 * dim, &rwork)); 1542792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &nb, evecs, &nb, evals, work, &lwork, rwork, &lierr)); 15439566063dSJacob Faibussowitsch PetscCall(PetscFree(rwork)); 154420282da2SJoe Wallwork } 154520282da2SJoe Wallwork #else 1546792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &nb, evecs, &nb, evals, work, &lwork, &lierr)); 154720282da2SJoe Wallwork #endif 154882490253SJoe Wallwork if (lierr) { 154982490253SJoe Wallwork for (i = 0; i < dim; ++i) { 155082490253SJoe Wallwork for (l = 0; l < dim; ++l) { 1551e2606525SJoe Wallwork evecs[i * dim + l] = 0.0; 1552e2606525SJoe Wallwork for (j = 0; j < dim; ++j) { 1553ad540459SPierre Jolivet for (k = 0; k < dim; ++k) evecs[i * dim + l] += isqrtM1[j * dim + i] * M2[j * dim + k] * isqrtM1[k * dim + l]; 155482490253SJoe Wallwork } 155582490253SJoe Wallwork } 155682490253SJoe Wallwork } 15573ba16761SJacob Faibussowitsch PetscCall(LAPACKsyevFail(dim, evecs)); 1558*835f2295SStefano Zampini SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in LAPACK routine %" PetscBLASInt_FMT, lierr); 155982490253SJoe Wallwork } 15609566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 156120282da2SJoe Wallwork 156220282da2SJoe Wallwork /* Modify eigenvalues */ 1563e2606525SJoe Wallwork for (i = 0; i < dim; ++i) evals[i] = PetscMax(evals[i], 1.0); 156420282da2SJoe Wallwork 156520282da2SJoe Wallwork /* Map back to get the intersection */ 156620282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 1567e2606525SJoe Wallwork for (m = 0; m < dim; ++m) { 1568e2606525SJoe Wallwork M2[i * dim + m] = 0.0; 156920282da2SJoe Wallwork for (j = 0; j < dim; ++j) { 157020282da2SJoe Wallwork for (k = 0; k < dim; ++k) { 1571ad540459SPierre Jolivet for (l = 0; l < dim; ++l) M2[i * dim + m] += sqrtM1[j * dim + i] * evecs[j * dim + k] * evals[k] * evecs[l * dim + k] * sqrtM1[l * dim + m]; 157220282da2SJoe Wallwork } 157320282da2SJoe Wallwork } 157420282da2SJoe Wallwork } 157520282da2SJoe Wallwork } 157620282da2SJoe Wallwork } 15779566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 157820282da2SJoe Wallwork } 1579e2606525SJoe Wallwork PetscCall(PetscFree4(evecs, sqrtM1, isqrtM1, evals)); 15803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 158120282da2SJoe Wallwork } 158220282da2SJoe Wallwork 1583cb7bfe8cSJoe Wallwork /*@ 158420282da2SJoe Wallwork DMPlexMetricIntersection - Compute the intersection of a list of metrics 158520282da2SJoe Wallwork 1586f1a722f8SMatthew G. Knepley Input Parameters: 15872fe279fdSBarry Smith + dm - The `DM` 158820282da2SJoe Wallwork . numMetrics - The number of metrics to be intersected 158920282da2SJoe Wallwork - metrics - The metrics to be intersected 159020282da2SJoe Wallwork 159120282da2SJoe Wallwork Output Parameter: 159220282da2SJoe Wallwork . metricInt - The intersected metric 159320282da2SJoe Wallwork 159420282da2SJoe Wallwork Level: beginner 159520282da2SJoe Wallwork 159620282da2SJoe Wallwork Notes: 1597e2606525SJoe Wallwork The intersection of a list of metrics has the minimal ellipsoid which fits within the ellipsoids of the component metrics. 159820282da2SJoe Wallwork 1599e2606525SJoe Wallwork The implementation used here is only consistent with the minimal ellipsoid definition in the case numMetrics = 2. 160020282da2SJoe Wallwork 16012fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricIntersection2()`, `DMPlexMetricIntersection3()`, `DMPlexMetricAverage()` 1602cb7bfe8cSJoe Wallwork @*/ 1603d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricIntersection(DM dm, PetscInt numMetrics, Vec metrics[], Vec metricInt) 1604d71ae5a4SJacob Faibussowitsch { 160593520041SJoe Wallwork PetscBool isotropic, uniform; 160693520041SJoe Wallwork PetscInt v, i, m, n; 160793520041SJoe Wallwork PetscScalar *met, *meti; 160820282da2SJoe Wallwork 160920282da2SJoe Wallwork PetscFunctionBegin; 16109566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_MetricIntersection, 0, 0, 0, 0)); 161163a3b9bcSJacob Faibussowitsch PetscCheck(numMetrics >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot intersect %" PetscInt_FMT " < 1 metrics", numMetrics); 161220282da2SJoe Wallwork 161320282da2SJoe Wallwork /* Copy over the first metric */ 16145241a91fSJoe Wallwork PetscCall(VecCopy(metrics[0], metricInt)); 16153ba16761SJacob Faibussowitsch if (numMetrics == 1) PetscFunctionReturn(PETSC_SUCCESS); 16165241a91fSJoe Wallwork PetscCall(VecGetSize(metricInt, &m)); 161793520041SJoe Wallwork for (i = 0; i < numMetrics; ++i) { 16189566063dSJacob Faibussowitsch PetscCall(VecGetSize(metrics[i], &n)); 161908401ef6SPierre Jolivet PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Intersecting different metric types not implemented"); 162093520041SJoe Wallwork } 162120282da2SJoe Wallwork 162220282da2SJoe Wallwork /* Intersect subsequent metrics in turn */ 16239566063dSJacob Faibussowitsch PetscCall(DMPlexMetricIsUniform(dm, &uniform)); 16249566063dSJacob Faibussowitsch PetscCall(DMPlexMetricIsIsotropic(dm, &isotropic)); 162593520041SJoe Wallwork if (uniform) { 162693520041SJoe Wallwork /* Uniform case */ 16275241a91fSJoe Wallwork PetscCall(VecGetArray(metricInt, &met)); 162893520041SJoe Wallwork for (i = 1; i < numMetrics; ++i) { 16299566063dSJacob Faibussowitsch PetscCall(VecGetArray(metrics[i], &meti)); 16309566063dSJacob Faibussowitsch PetscCall(DMPlexMetricIntersection_Private(1, meti, met)); 16319566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(metrics[i], &meti)); 163293520041SJoe Wallwork } 16335241a91fSJoe Wallwork PetscCall(VecRestoreArray(metricInt, &met)); 163493520041SJoe Wallwork } else { 163593520041SJoe Wallwork /* Spatially varying case */ 163693520041SJoe Wallwork PetscInt dim, vStart, vEnd, nrow; 163793520041SJoe Wallwork PetscScalar *M, *Mi; 163893520041SJoe Wallwork 16399566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 164093520041SJoe Wallwork if (isotropic) nrow = 1; 164193520041SJoe Wallwork else nrow = dim; 16429566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 16435241a91fSJoe Wallwork PetscCall(VecGetArray(metricInt, &met)); 164420282da2SJoe Wallwork for (i = 1; i < numMetrics; ++i) { 16459566063dSJacob Faibussowitsch PetscCall(VecGetArray(metrics[i], &meti)); 164620282da2SJoe Wallwork for (v = vStart; v < vEnd; ++v) { 16479566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRef(dm, v, met, &M)); 16489566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRef(dm, v, meti, &Mi)); 16499566063dSJacob Faibussowitsch PetscCall(DMPlexMetricIntersection_Private(nrow, Mi, M)); 165020282da2SJoe Wallwork } 16519566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(metrics[i], &meti)); 165220282da2SJoe Wallwork } 16535241a91fSJoe Wallwork PetscCall(VecRestoreArray(metricInt, &met)); 165420282da2SJoe Wallwork } 1655fe902aceSJoe Wallwork 16569566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_MetricIntersection, 0, 0, 0, 0)); 16573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 165820282da2SJoe Wallwork } 165920282da2SJoe Wallwork 1660cb7bfe8cSJoe Wallwork /*@ 166120282da2SJoe Wallwork DMPlexMetricIntersection2 - Compute the intersection of two metrics 166220282da2SJoe Wallwork 1663f1a722f8SMatthew G. Knepley Input Parameters: 16642fe279fdSBarry Smith + dm - The `DM` 166520282da2SJoe Wallwork . metric1 - The first metric to be intersected 166620282da2SJoe Wallwork - metric2 - The second metric to be intersected 166720282da2SJoe Wallwork 166820282da2SJoe Wallwork Output Parameter: 166920282da2SJoe Wallwork . metricInt - The intersected metric 167020282da2SJoe Wallwork 167120282da2SJoe Wallwork Level: beginner 167220282da2SJoe Wallwork 16732fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricIntersection()`, `DMPlexMetricIntersection3()` 1674cb7bfe8cSJoe Wallwork @*/ 1675d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricIntersection2(DM dm, Vec metric1, Vec metric2, Vec metricInt) 1676d71ae5a4SJacob Faibussowitsch { 167720282da2SJoe Wallwork Vec metrics[2] = {metric1, metric2}; 167820282da2SJoe Wallwork 167920282da2SJoe Wallwork PetscFunctionBegin; 16809566063dSJacob Faibussowitsch PetscCall(DMPlexMetricIntersection(dm, 2, metrics, metricInt)); 16813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 168220282da2SJoe Wallwork } 168320282da2SJoe Wallwork 1684cb7bfe8cSJoe Wallwork /*@ 168520282da2SJoe Wallwork DMPlexMetricIntersection3 - Compute the intersection of three metrics 168620282da2SJoe Wallwork 1687f1a722f8SMatthew G. Knepley Input Parameters: 16882fe279fdSBarry Smith + dm - The `DM` 168920282da2SJoe Wallwork . metric1 - The first metric to be intersected 169020282da2SJoe Wallwork . metric2 - The second metric to be intersected 169120282da2SJoe Wallwork - metric3 - The third metric to be intersected 169220282da2SJoe Wallwork 169320282da2SJoe Wallwork Output Parameter: 169420282da2SJoe Wallwork . metricInt - The intersected metric 169520282da2SJoe Wallwork 169620282da2SJoe Wallwork Level: beginner 169720282da2SJoe Wallwork 16982fe279fdSBarry Smith .seealso: `DMPLEX`, `DMPlexMetricIntersection()`, `DMPlexMetricIntersection2()` 1699cb7bfe8cSJoe Wallwork @*/ 1700d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMetricIntersection3(DM dm, Vec metric1, Vec metric2, Vec metric3, Vec metricInt) 1701d71ae5a4SJacob Faibussowitsch { 170220282da2SJoe Wallwork Vec metrics[3] = {metric1, metric2, metric3}; 170320282da2SJoe Wallwork 170420282da2SJoe Wallwork PetscFunctionBegin; 17059566063dSJacob Faibussowitsch PetscCall(DMPlexMetricIntersection(dm, 3, metrics, metricInt)); 17063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 170720282da2SJoe Wallwork } 1708