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 631b70465SJoe Wallwork PetscErrorCode DMPlexMetricSetFromOptions(DM dm) 731b70465SJoe Wallwork { 831b70465SJoe Wallwork MPI_Comm comm; 993520041SJoe Wallwork PetscBool isotropic = PETSC_FALSE, uniform = PETSC_FALSE, restrictAnisotropyFirst = PETSC_FALSE; 10*76f360caSJoe Wallwork PetscBool noInsert = PETSC_FALSE, noSwap = PETSC_FALSE, noMove = PETSC_FALSE, noSurf = PETSC_FALSE; 1131b70465SJoe Wallwork PetscErrorCode ierr; 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; 1631b70465SJoe Wallwork ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 1731b70465SJoe Wallwork ierr = PetscOptionsBegin(comm, "", "Riemannian metric options", "DMPlexMetric");CHKERRQ(ierr); 1831b70465SJoe Wallwork ierr = PetscOptionsBool("-dm_plex_metric_isotropic", "Is the metric isotropic?", "DMPlexMetricCreateIsotropic", isotropic, &isotropic, NULL);CHKERRQ(ierr); 19cc2eee55SJoe Wallwork ierr = DMPlexMetricSetIsotropic(dm, isotropic);CHKERRQ(ierr); 2093520041SJoe Wallwork ierr = PetscOptionsBool("-dm_plex_metric_uniform", "Is the metric uniform?", "DMPlexMetricCreateUniform", uniform, &uniform, NULL);CHKERRQ(ierr); 2193520041SJoe Wallwork ierr = DMPlexMetricSetUniform(dm, uniform);CHKERRQ(ierr); 2231b70465SJoe Wallwork ierr = PetscOptionsBool("-dm_plex_metric_restrict_anisotropy_first", "Should anisotropy be restricted before normalization?", "DMPlexNormalize", restrictAnisotropyFirst, &restrictAnisotropyFirst, NULL);CHKERRQ(ierr); 23cc2eee55SJoe Wallwork ierr = DMPlexMetricSetRestrictAnisotropyFirst(dm, restrictAnisotropyFirst);CHKERRQ(ierr); 24cc2eee55SJoe Wallwork ierr = PetscOptionsBool("-dm_plex_metric_no_insert", "Turn off node insertion and deletion", "DMAdaptMetric", noInsert, &noInsert, NULL);CHKERRQ(ierr); 25cc2eee55SJoe Wallwork ierr = DMPlexMetricSetNoInsertion(dm, noInsert);CHKERRQ(ierr); 26cc2eee55SJoe Wallwork ierr = PetscOptionsBool("-dm_plex_metric_no_swap", "Turn off facet swapping", "DMAdaptMetric", noSwap, &noSwap, NULL);CHKERRQ(ierr); 27cc2eee55SJoe Wallwork ierr = DMPlexMetricSetNoSwapping(dm, noSwap);CHKERRQ(ierr); 28cc2eee55SJoe Wallwork ierr = PetscOptionsBool("-dm_plex_metric_no_move", "Turn off facet node movement", "DMAdaptMetric", noMove, &noMove, NULL);CHKERRQ(ierr); 29cc2eee55SJoe Wallwork ierr = DMPlexMetricSetNoMovement(dm, noMove);CHKERRQ(ierr); 30*76f360caSJoe Wallwork ierr = PetscOptionsBool("-dm_plex_metric_no_surf", "Turn off surface modification", "DMAdaptMetric", noSurf, &noSurf, NULL);CHKERRQ(ierr); 31*76f360caSJoe Wallwork ierr = DMPlexMetricSetNoSurf(dm, noSurf);CHKERRQ(ierr); 32cc2eee55SJoe Wallwork ierr = PetscOptionsBoundedInt("-dm_plex_metric_num_iterations", "Number of ParMmg adaptation iterations", "DMAdaptMetric", numIter, &numIter, NULL, 0);CHKERRQ(ierr); 33cc2eee55SJoe Wallwork ierr = DMPlexMetricSetNumIterations(dm, numIter);CHKERRQ(ierr); 34cc2eee55SJoe Wallwork ierr = PetscOptionsRangeInt("-dm_plex_metric_verbosity", "Verbosity of metric-based mesh adaptation package (-1 = silent, 10 = maximum)", "DMAdaptMetric", verbosity, &verbosity, NULL, -1, 10);CHKERRQ(ierr); 35cc2eee55SJoe Wallwork ierr = DMPlexMetricSetVerbosity(dm, verbosity);CHKERRQ(ierr); 3631b70465SJoe Wallwork ierr = PetscOptionsReal("-dm_plex_metric_h_min", "Minimum tolerated metric magnitude", "DMPlexMetricEnforceSPD", h_min, &h_min, NULL);CHKERRQ(ierr); 3731b70465SJoe Wallwork ierr = DMPlexMetricSetMinimumMagnitude(dm, h_min);CHKERRQ(ierr); 3831b70465SJoe Wallwork ierr = PetscOptionsReal("-dm_plex_metric_h_max", "Maximum tolerated metric magnitude", "DMPlexMetricEnforceSPD", h_max, &h_max, NULL);CHKERRQ(ierr); 3931b70465SJoe Wallwork ierr = DMPlexMetricSetMaximumMagnitude(dm, h_max);CHKERRQ(ierr); 4031b70465SJoe Wallwork ierr = PetscOptionsReal("-dm_plex_metric_a_max", "Maximum tolerated anisotropy", "DMPlexMetricEnforceSPD", a_max, &a_max, NULL);CHKERRQ(ierr); 4131b70465SJoe Wallwork ierr = DMPlexMetricSetMaximumAnisotropy(dm, a_max);CHKERRQ(ierr); 4231b70465SJoe Wallwork ierr = PetscOptionsReal("-dm_plex_metric_p", "L-p normalization order", "DMPlexMetricNormalize", p, &p, NULL);CHKERRQ(ierr); 4331b70465SJoe Wallwork ierr = DMPlexMetricSetNormalizationOrder(dm, p);CHKERRQ(ierr); 4431b70465SJoe Wallwork ierr = PetscOptionsReal("-dm_plex_metric_target_complexity", "Target metric complexity", "DMPlexMetricNormalize", target, &target, NULL);CHKERRQ(ierr); 4531b70465SJoe Wallwork ierr = DMPlexMetricSetTargetComplexity(dm, target);CHKERRQ(ierr); 46cc2eee55SJoe Wallwork ierr = PetscOptionsReal("-dm_plex_metric_gradation_factor", "Metric gradation factor", "DMAdaptMetric", beta, &beta, NULL);CHKERRQ(ierr); 47cc2eee55SJoe Wallwork ierr = DMPlexMetricSetGradationFactor(dm, beta);CHKERRQ(ierr); 48ae8b063eSJoe Wallwork ierr = PetscOptionsReal("-dm_plex_metric_hausdorff_number", "Metric Hausdorff number", "DMAdaptMetric", hausd, &hausd, NULL);CHKERRQ(ierr); 49ae8b063eSJoe Wallwork ierr = DMPlexMetricSetHausdorffNumber(dm, hausd);CHKERRQ(ierr); 5031b70465SJoe Wallwork ierr = PetscOptionsEnd();CHKERRQ(ierr); 5131b70465SJoe Wallwork PetscFunctionReturn(0); 5231b70465SJoe Wallwork } 5331b70465SJoe Wallwork 54cb7bfe8cSJoe Wallwork /*@ 5531b70465SJoe Wallwork DMPlexMetricSetIsotropic - Record whether a metric is isotropic 5631b70465SJoe Wallwork 5731b70465SJoe Wallwork Input parameters: 5831b70465SJoe Wallwork + dm - The DM 5931b70465SJoe Wallwork - isotropic - Is the metric isotropic? 6031b70465SJoe Wallwork 6131b70465SJoe Wallwork Level: beginner 6231b70465SJoe Wallwork 6393520041SJoe Wallwork .seealso: DMPlexMetricIsIsotropic(), DMPlexMetricSetUniform(), DMPlexMetricSetRestrictAnisotropyFirst() 64cb7bfe8cSJoe Wallwork @*/ 6531b70465SJoe Wallwork PetscErrorCode DMPlexMetricSetIsotropic(DM dm, PetscBool isotropic) 6631b70465SJoe Wallwork { 6731b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 6831b70465SJoe Wallwork PetscErrorCode ierr; 6931b70465SJoe Wallwork 7031b70465SJoe Wallwork PetscFunctionBegin; 7131b70465SJoe Wallwork if (!plex->metricCtx) { 7231b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 7331b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 7431b70465SJoe Wallwork } 7531b70465SJoe Wallwork plex->metricCtx->isotropic = isotropic; 7631b70465SJoe Wallwork PetscFunctionReturn(0); 7731b70465SJoe Wallwork } 7831b70465SJoe Wallwork 79cb7bfe8cSJoe Wallwork /*@ 8093520041SJoe Wallwork DMPlexMetricIsIsotropic - Is a metric isotropic? 8131b70465SJoe Wallwork 8231b70465SJoe Wallwork Input parameters: 8331b70465SJoe Wallwork . dm - The DM 8431b70465SJoe Wallwork 8531b70465SJoe Wallwork Output parameters: 8631b70465SJoe Wallwork . isotropic - Is the metric isotropic? 8731b70465SJoe Wallwork 8831b70465SJoe Wallwork Level: beginner 8931b70465SJoe Wallwork 9093520041SJoe Wallwork .seealso: DMPlexMetricSetIsotropic(), DMPlexMetricIsUniform(), DMPlexMetricRestrictAnisotropyFirst() 91cb7bfe8cSJoe Wallwork @*/ 9231b70465SJoe Wallwork PetscErrorCode DMPlexMetricIsIsotropic(DM dm, PetscBool *isotropic) 9331b70465SJoe Wallwork { 9431b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 9531b70465SJoe Wallwork PetscErrorCode ierr; 9631b70465SJoe Wallwork 9731b70465SJoe Wallwork PetscFunctionBegin; 9831b70465SJoe Wallwork if (!plex->metricCtx) { 9931b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 10031b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 10131b70465SJoe Wallwork } 10231b70465SJoe Wallwork *isotropic = plex->metricCtx->isotropic; 10331b70465SJoe Wallwork PetscFunctionReturn(0); 10431b70465SJoe Wallwork } 10531b70465SJoe Wallwork 106cb7bfe8cSJoe Wallwork /*@ 10793520041SJoe Wallwork DMPlexMetricSetUniform - Record whether a metric is uniform 10893520041SJoe Wallwork 10993520041SJoe Wallwork Input parameters: 11093520041SJoe Wallwork + dm - The DM 11193520041SJoe Wallwork - uniform - Is the metric uniform? 11293520041SJoe Wallwork 11393520041SJoe Wallwork Level: beginner 11493520041SJoe Wallwork 11593520041SJoe Wallwork Notes: 11693520041SJoe Wallwork 11793520041SJoe Wallwork If the metric is specified as uniform then it is assumed to be isotropic, too. 11893520041SJoe Wallwork 11993520041SJoe Wallwork .seealso: DMPlexMetricIsUniform(), DMPlexMetricSetIsotropic(), DMPlexMetricSetRestrictAnisotropyFirst() 12093520041SJoe Wallwork @*/ 12193520041SJoe Wallwork PetscErrorCode DMPlexMetricSetUniform(DM dm, PetscBool uniform) 12293520041SJoe Wallwork { 12393520041SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 12493520041SJoe Wallwork PetscErrorCode ierr; 12593520041SJoe Wallwork 12693520041SJoe Wallwork PetscFunctionBegin; 12793520041SJoe Wallwork if (!plex->metricCtx) { 12893520041SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 12993520041SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 13093520041SJoe Wallwork } 13193520041SJoe Wallwork plex->metricCtx->uniform = uniform; 13293520041SJoe Wallwork if (uniform) plex->metricCtx->isotropic = uniform; 13393520041SJoe Wallwork PetscFunctionReturn(0); 13493520041SJoe Wallwork } 13593520041SJoe Wallwork 13693520041SJoe Wallwork /*@ 13793520041SJoe Wallwork DMPlexMetricIsUniform - Is a metric uniform? 13893520041SJoe Wallwork 13993520041SJoe Wallwork Input parameters: 14093520041SJoe Wallwork . dm - The DM 14193520041SJoe Wallwork 14293520041SJoe Wallwork Output parameters: 14393520041SJoe Wallwork . uniform - Is the metric uniform? 14493520041SJoe Wallwork 14593520041SJoe Wallwork Level: beginner 14693520041SJoe Wallwork 14793520041SJoe Wallwork .seealso: DMPlexMetricSetUniform(), DMPlexMetricIsIsotropic(), DMPlexMetricRestrictAnisotropyFirst() 14893520041SJoe Wallwork @*/ 14993520041SJoe Wallwork PetscErrorCode DMPlexMetricIsUniform(DM dm, PetscBool *uniform) 15093520041SJoe Wallwork { 15193520041SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 15293520041SJoe Wallwork PetscErrorCode ierr; 15393520041SJoe Wallwork 15493520041SJoe Wallwork PetscFunctionBegin; 15593520041SJoe Wallwork if (!plex->metricCtx) { 15693520041SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 15793520041SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 15893520041SJoe Wallwork } 15993520041SJoe Wallwork *uniform = plex->metricCtx->uniform; 16093520041SJoe Wallwork PetscFunctionReturn(0); 16193520041SJoe Wallwork } 16293520041SJoe Wallwork 16393520041SJoe Wallwork /*@ 16431b70465SJoe Wallwork DMPlexMetricSetRestrictAnisotropyFirst - Record whether anisotropy should be restricted before normalization 16531b70465SJoe Wallwork 16631b70465SJoe Wallwork Input parameters: 16731b70465SJoe Wallwork + dm - The DM 16831b70465SJoe Wallwork - restrictAnisotropyFirst - Should anisotropy be normalized first? 16931b70465SJoe Wallwork 17031b70465SJoe Wallwork Level: beginner 17131b70465SJoe Wallwork 17231b70465SJoe Wallwork .seealso: DMPlexMetricSetIsotropic(), DMPlexMetricRestrictAnisotropyFirst() 173cb7bfe8cSJoe Wallwork @*/ 17431b70465SJoe Wallwork PetscErrorCode DMPlexMetricSetRestrictAnisotropyFirst(DM dm, PetscBool restrictAnisotropyFirst) 17531b70465SJoe Wallwork { 17631b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 17731b70465SJoe Wallwork PetscErrorCode ierr; 17831b70465SJoe Wallwork 17931b70465SJoe Wallwork PetscFunctionBegin; 18031b70465SJoe Wallwork if (!plex->metricCtx) { 18131b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 18231b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 18331b70465SJoe Wallwork } 18431b70465SJoe Wallwork plex->metricCtx->restrictAnisotropyFirst = restrictAnisotropyFirst; 18531b70465SJoe Wallwork PetscFunctionReturn(0); 18631b70465SJoe Wallwork } 18731b70465SJoe Wallwork 188cb7bfe8cSJoe Wallwork /*@ 18931b70465SJoe Wallwork DMPlexMetricRestrictAnisotropyFirst - Is anisotropy restricted before normalization or after? 19031b70465SJoe Wallwork 19131b70465SJoe Wallwork Input parameters: 19231b70465SJoe Wallwork . dm - The DM 19331b70465SJoe Wallwork 19431b70465SJoe Wallwork Output parameters: 19531b70465SJoe Wallwork . restrictAnisotropyFirst - Is anisotropy be normalized first? 19631b70465SJoe Wallwork 19731b70465SJoe Wallwork Level: beginner 19831b70465SJoe Wallwork 19931b70465SJoe Wallwork .seealso: DMPlexMetricIsIsotropic(), DMPlexMetricSetRestrictAnisotropyFirst() 200cb7bfe8cSJoe Wallwork @*/ 20131b70465SJoe Wallwork PetscErrorCode DMPlexMetricRestrictAnisotropyFirst(DM dm, PetscBool *restrictAnisotropyFirst) 20231b70465SJoe Wallwork { 20331b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 20431b70465SJoe Wallwork PetscErrorCode ierr; 20531b70465SJoe Wallwork 20631b70465SJoe Wallwork PetscFunctionBegin; 20731b70465SJoe Wallwork if (!plex->metricCtx) { 20831b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 20931b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 21031b70465SJoe Wallwork } 21131b70465SJoe Wallwork *restrictAnisotropyFirst = plex->metricCtx->restrictAnisotropyFirst; 21231b70465SJoe Wallwork PetscFunctionReturn(0); 21331b70465SJoe Wallwork } 21431b70465SJoe Wallwork 215cb7bfe8cSJoe Wallwork /*@ 216cc2eee55SJoe Wallwork DMPlexMetricSetNoInsertion - Should node insertion and deletion be turned off? 217cc2eee55SJoe Wallwork 218cc2eee55SJoe Wallwork Input parameters: 219cc2eee55SJoe Wallwork + dm - The DM 220cc2eee55SJoe Wallwork - noInsert - Should node insertion and deletion be turned off? 221cc2eee55SJoe Wallwork 222cc2eee55SJoe Wallwork Level: beginner 223cc2eee55SJoe Wallwork 224cb7bfe8cSJoe Wallwork Notes: 225cb7bfe8cSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 226cb7bfe8cSJoe Wallwork 227*76f360caSJoe Wallwork .seealso: DMPlexMetricNoInsertion(), DMPlexMetricSetNoSwapping(), DMPlexMetricSetNoMovement(), DMPlexMetricSetNoSurf() 228cb7bfe8cSJoe Wallwork @*/ 229cc2eee55SJoe Wallwork PetscErrorCode DMPlexMetricSetNoInsertion(DM dm, PetscBool noInsert) 230cc2eee55SJoe Wallwork { 231cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 232cc2eee55SJoe Wallwork PetscErrorCode ierr; 233cc2eee55SJoe Wallwork 234cc2eee55SJoe Wallwork PetscFunctionBegin; 235cc2eee55SJoe Wallwork if (!plex->metricCtx) { 236cc2eee55SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 237cc2eee55SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 238cc2eee55SJoe Wallwork } 239cc2eee55SJoe Wallwork plex->metricCtx->noInsert = noInsert; 240cc2eee55SJoe Wallwork PetscFunctionReturn(0); 241cc2eee55SJoe Wallwork } 242cc2eee55SJoe Wallwork 243cb7bfe8cSJoe Wallwork /*@ 244cc2eee55SJoe Wallwork DMPlexMetricNoInsertion - Are node insertion and deletion turned off? 245cc2eee55SJoe Wallwork 246cc2eee55SJoe Wallwork Input parameters: 247cc2eee55SJoe Wallwork . dm - The DM 248cc2eee55SJoe Wallwork 249cc2eee55SJoe Wallwork Output parameters: 250cc2eee55SJoe Wallwork . noInsert - Are node insertion and deletion turned off? 251cc2eee55SJoe Wallwork 252cc2eee55SJoe Wallwork Level: beginner 253cc2eee55SJoe Wallwork 254cb7bfe8cSJoe Wallwork Notes: 255cb7bfe8cSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 256cb7bfe8cSJoe Wallwork 257*76f360caSJoe Wallwork .seealso: DMPlexMetricSetNoInsertion(), DMPlexMetricNoSwapping(), DMPlexMetricNoMovement(), DMPlexMetricNoSurf() 258cb7bfe8cSJoe Wallwork @*/ 259cc2eee55SJoe Wallwork PetscErrorCode DMPlexMetricNoInsertion(DM dm, PetscBool *noInsert) 260cc2eee55SJoe Wallwork { 261cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 262cc2eee55SJoe Wallwork PetscErrorCode ierr; 263cc2eee55SJoe Wallwork 264cc2eee55SJoe Wallwork PetscFunctionBegin; 265cc2eee55SJoe Wallwork if (!plex->metricCtx) { 266cc2eee55SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 267cc2eee55SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 268cc2eee55SJoe Wallwork } 269cc2eee55SJoe Wallwork *noInsert = plex->metricCtx->noInsert; 270cc2eee55SJoe Wallwork PetscFunctionReturn(0); 271cc2eee55SJoe Wallwork } 272cc2eee55SJoe Wallwork 273cb7bfe8cSJoe Wallwork /*@ 274cc2eee55SJoe Wallwork DMPlexMetricSetNoSwapping - Should facet swapping be turned off? 275cc2eee55SJoe Wallwork 276cc2eee55SJoe Wallwork Input parameters: 277cc2eee55SJoe Wallwork + dm - The DM 278cc2eee55SJoe Wallwork - noSwap - Should facet swapping be turned off? 279cc2eee55SJoe Wallwork 280cc2eee55SJoe Wallwork Level: beginner 281cc2eee55SJoe Wallwork 282cb7bfe8cSJoe Wallwork Notes: 283cb7bfe8cSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 284cb7bfe8cSJoe Wallwork 285*76f360caSJoe Wallwork .seealso: DMPlexMetricNoSwapping(), DMPlexMetricSetNoInsertion(), DMPlexMetricSetNoMovement(), DMPlexMetricSetNoSurf() 286cb7bfe8cSJoe Wallwork @*/ 287cc2eee55SJoe Wallwork PetscErrorCode DMPlexMetricSetNoSwapping(DM dm, PetscBool noSwap) 288cc2eee55SJoe Wallwork { 289cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 290cc2eee55SJoe Wallwork PetscErrorCode ierr; 291cc2eee55SJoe Wallwork 292cc2eee55SJoe Wallwork PetscFunctionBegin; 293cc2eee55SJoe Wallwork if (!plex->metricCtx) { 294cc2eee55SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 295cc2eee55SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 296cc2eee55SJoe Wallwork } 297cc2eee55SJoe Wallwork plex->metricCtx->noSwap = noSwap; 298cc2eee55SJoe Wallwork PetscFunctionReturn(0); 299cc2eee55SJoe Wallwork } 300cc2eee55SJoe Wallwork 301cb7bfe8cSJoe Wallwork /*@ 302cc2eee55SJoe Wallwork DMPlexMetricNoSwapping - Is facet swapping turned off? 303cc2eee55SJoe Wallwork 304cc2eee55SJoe Wallwork Input parameters: 305cc2eee55SJoe Wallwork . dm - The DM 306cc2eee55SJoe Wallwork 307cc2eee55SJoe Wallwork Output parameters: 308cc2eee55SJoe Wallwork . noSwap - Is facet swapping turned off? 309cc2eee55SJoe Wallwork 310cc2eee55SJoe Wallwork Level: beginner 311cc2eee55SJoe Wallwork 312cb7bfe8cSJoe Wallwork Notes: 313cb7bfe8cSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 314cb7bfe8cSJoe Wallwork 315*76f360caSJoe Wallwork .seealso: DMPlexMetricSetNoSwapping(), DMPlexMetricNoInsertion(), DMPlexMetricNoMovement(), DMPlexMetricNoSurf() 316cb7bfe8cSJoe Wallwork @*/ 317cc2eee55SJoe Wallwork PetscErrorCode DMPlexMetricNoSwapping(DM dm, PetscBool *noSwap) 318cc2eee55SJoe Wallwork { 319cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 320cc2eee55SJoe Wallwork PetscErrorCode ierr; 321cc2eee55SJoe Wallwork 322cc2eee55SJoe Wallwork PetscFunctionBegin; 323cc2eee55SJoe Wallwork if (!plex->metricCtx) { 324cc2eee55SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 325cc2eee55SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 326cc2eee55SJoe Wallwork } 327cc2eee55SJoe Wallwork *noSwap = plex->metricCtx->noSwap; 328cc2eee55SJoe Wallwork PetscFunctionReturn(0); 329cc2eee55SJoe Wallwork } 330cc2eee55SJoe Wallwork 331cb7bfe8cSJoe Wallwork /*@ 332cc2eee55SJoe Wallwork DMPlexMetricSetNoMovement - Should node movement be turned off? 333cc2eee55SJoe Wallwork 334cc2eee55SJoe Wallwork Input parameters: 335cc2eee55SJoe Wallwork + dm - The DM 336cc2eee55SJoe Wallwork - noMove - Should node movement be turned off? 337cc2eee55SJoe Wallwork 338cc2eee55SJoe Wallwork Level: beginner 339cc2eee55SJoe Wallwork 340cb7bfe8cSJoe Wallwork Notes: 341cb7bfe8cSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 342cb7bfe8cSJoe Wallwork 343*76f360caSJoe Wallwork .seealso: DMPlexMetricNoMovement(), DMPlexMetricSetNoInsertion(), DMPlexMetricSetNoSwapping(), DMPlexMetricSetNoSurf() 344cb7bfe8cSJoe Wallwork @*/ 345cc2eee55SJoe Wallwork PetscErrorCode DMPlexMetricSetNoMovement(DM dm, PetscBool noMove) 346cc2eee55SJoe Wallwork { 347cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 348cc2eee55SJoe Wallwork PetscErrorCode ierr; 349cc2eee55SJoe Wallwork 350cc2eee55SJoe Wallwork PetscFunctionBegin; 351cc2eee55SJoe Wallwork if (!plex->metricCtx) { 352cc2eee55SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 353cc2eee55SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 354cc2eee55SJoe Wallwork } 355cc2eee55SJoe Wallwork plex->metricCtx->noMove = noMove; 356cc2eee55SJoe Wallwork PetscFunctionReturn(0); 357cc2eee55SJoe Wallwork } 358cc2eee55SJoe Wallwork 359cb7bfe8cSJoe Wallwork /*@ 360cc2eee55SJoe Wallwork DMPlexMetricNoMovement - Is node movement turned off? 361cc2eee55SJoe Wallwork 362cc2eee55SJoe Wallwork Input parameters: 363cc2eee55SJoe Wallwork . dm - The DM 364cc2eee55SJoe Wallwork 365cc2eee55SJoe Wallwork Output parameters: 366cc2eee55SJoe Wallwork . noMove - Is node movement turned off? 367cc2eee55SJoe Wallwork 368cc2eee55SJoe Wallwork Level: beginner 369cc2eee55SJoe Wallwork 370cb7bfe8cSJoe Wallwork Notes: 371cb7bfe8cSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 372cb7bfe8cSJoe Wallwork 373*76f360caSJoe Wallwork .seealso: DMPlexMetricSetNoMovement(), DMPlexMetricNoInsertion(), DMPlexMetricNoSwapping(), DMPlexMetricNoSurf() 374cb7bfe8cSJoe Wallwork @*/ 375cc2eee55SJoe Wallwork PetscErrorCode DMPlexMetricNoMovement(DM dm, PetscBool *noMove) 376cc2eee55SJoe Wallwork { 377cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 378cc2eee55SJoe Wallwork PetscErrorCode ierr; 379cc2eee55SJoe Wallwork 380cc2eee55SJoe Wallwork PetscFunctionBegin; 381cc2eee55SJoe Wallwork if (!plex->metricCtx) { 382cc2eee55SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 383cc2eee55SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 384cc2eee55SJoe Wallwork } 385cc2eee55SJoe Wallwork *noMove = plex->metricCtx->noMove; 386cc2eee55SJoe Wallwork PetscFunctionReturn(0); 387cc2eee55SJoe Wallwork } 388cc2eee55SJoe Wallwork 389cb7bfe8cSJoe Wallwork /*@ 390*76f360caSJoe Wallwork DMPlexMetricSetNoSurf - Should surface modification be turned off? 391*76f360caSJoe Wallwork 392*76f360caSJoe Wallwork Input parameters: 393*76f360caSJoe Wallwork + dm - The DM 394*76f360caSJoe Wallwork - noSurf - Should surface modification be turned off? 395*76f360caSJoe Wallwork 396*76f360caSJoe Wallwork Level: beginner 397*76f360caSJoe Wallwork 398*76f360caSJoe Wallwork Notes: 399*76f360caSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 400*76f360caSJoe Wallwork 401*76f360caSJoe Wallwork .seealso: DMPlexMetricNoSurf(), DMPlexMetricSetNoMovement(), DMPlexMetricSetNoInsertion(), DMPlexMetricSetNoSwapping() 402*76f360caSJoe Wallwork @*/ 403*76f360caSJoe Wallwork PetscErrorCode DMPlexMetricSetNoSurf(DM dm, PetscBool noSurf) 404*76f360caSJoe Wallwork { 405*76f360caSJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 406*76f360caSJoe Wallwork PetscErrorCode ierr; 407*76f360caSJoe Wallwork 408*76f360caSJoe Wallwork PetscFunctionBegin; 409*76f360caSJoe Wallwork if (!plex->metricCtx) { 410*76f360caSJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 411*76f360caSJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 412*76f360caSJoe Wallwork } 413*76f360caSJoe Wallwork plex->metricCtx->noSurf = noSurf; 414*76f360caSJoe Wallwork PetscFunctionReturn(0); 415*76f360caSJoe Wallwork } 416*76f360caSJoe Wallwork 417*76f360caSJoe Wallwork /*@ 418*76f360caSJoe Wallwork DMPlexMetricNoSurf - Is surface modification turned off? 419*76f360caSJoe Wallwork 420*76f360caSJoe Wallwork Input parameters: 421*76f360caSJoe Wallwork . dm - The DM 422*76f360caSJoe Wallwork 423*76f360caSJoe Wallwork Output parameters: 424*76f360caSJoe Wallwork . noSurf - Is surface modification turned off? 425*76f360caSJoe Wallwork 426*76f360caSJoe Wallwork Level: beginner 427*76f360caSJoe Wallwork 428*76f360caSJoe Wallwork Notes: 429*76f360caSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 430*76f360caSJoe Wallwork 431*76f360caSJoe Wallwork .seealso: DMPlexMetricSetNoSurf(), DMPlexMetricNoMovement(), DMPlexMetricNoInsertion(), DMPlexMetricNoSwapping() 432*76f360caSJoe Wallwork @*/ 433*76f360caSJoe Wallwork PetscErrorCode DMPlexMetricNoSurf(DM dm, PetscBool *noSurf) 434*76f360caSJoe Wallwork { 435*76f360caSJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 436*76f360caSJoe Wallwork PetscErrorCode ierr; 437*76f360caSJoe Wallwork 438*76f360caSJoe Wallwork PetscFunctionBegin; 439*76f360caSJoe Wallwork if (!plex->metricCtx) { 440*76f360caSJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 441*76f360caSJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 442*76f360caSJoe Wallwork } 443*76f360caSJoe Wallwork *noSurf = plex->metricCtx->noSurf; 444*76f360caSJoe Wallwork PetscFunctionReturn(0); 445*76f360caSJoe Wallwork } 446*76f360caSJoe Wallwork 447*76f360caSJoe Wallwork /*@ 44831b70465SJoe Wallwork DMPlexMetricSetMinimumMagnitude - Set the minimum tolerated metric magnitude 44931b70465SJoe Wallwork 45031b70465SJoe Wallwork Input parameters: 45131b70465SJoe Wallwork + dm - The DM 45231b70465SJoe Wallwork - h_min - The minimum tolerated metric magnitude 45331b70465SJoe Wallwork 45431b70465SJoe Wallwork Level: beginner 45531b70465SJoe Wallwork 45631b70465SJoe Wallwork .seealso: DMPlexMetricGetMinimumMagnitude(), DMPlexMetricSetMaximumMagnitude() 457cb7bfe8cSJoe Wallwork @*/ 45831b70465SJoe Wallwork PetscErrorCode DMPlexMetricSetMinimumMagnitude(DM dm, PetscReal h_min) 45931b70465SJoe Wallwork { 46031b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 46131b70465SJoe Wallwork PetscErrorCode ierr; 46231b70465SJoe Wallwork 46331b70465SJoe Wallwork PetscFunctionBegin; 46431b70465SJoe Wallwork if (!plex->metricCtx) { 46531b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 46631b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 46731b70465SJoe Wallwork } 4682c71b3e2SJacob Faibussowitsch PetscCheckFalse(h_min <= 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Metric magnitudes must be positive, not %.4e", h_min); 46931b70465SJoe Wallwork plex->metricCtx->h_min = h_min; 47031b70465SJoe Wallwork PetscFunctionReturn(0); 47131b70465SJoe Wallwork } 47231b70465SJoe Wallwork 473cb7bfe8cSJoe Wallwork /*@ 47431b70465SJoe Wallwork DMPlexMetricGetMinimumMagnitude - Get the minimum tolerated metric magnitude 47531b70465SJoe Wallwork 47631b70465SJoe Wallwork Input parameters: 47731b70465SJoe Wallwork . dm - The DM 47831b70465SJoe Wallwork 479cc2eee55SJoe Wallwork Output parameters: 48031b70465SJoe Wallwork . h_min - The minimum tolerated metric magnitude 48131b70465SJoe Wallwork 48231b70465SJoe Wallwork Level: beginner 48331b70465SJoe Wallwork 48431b70465SJoe Wallwork .seealso: DMPlexMetricSetMinimumMagnitude(), DMPlexMetricGetMaximumMagnitude() 485cb7bfe8cSJoe Wallwork @*/ 48631b70465SJoe Wallwork PetscErrorCode DMPlexMetricGetMinimumMagnitude(DM dm, PetscReal *h_min) 48731b70465SJoe Wallwork { 48831b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 48931b70465SJoe Wallwork PetscErrorCode ierr; 49031b70465SJoe Wallwork 49131b70465SJoe Wallwork PetscFunctionBegin; 49231b70465SJoe Wallwork if (!plex->metricCtx) { 49331b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 49431b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 49531b70465SJoe Wallwork } 49631b70465SJoe Wallwork *h_min = plex->metricCtx->h_min; 49731b70465SJoe Wallwork PetscFunctionReturn(0); 49831b70465SJoe Wallwork } 49931b70465SJoe Wallwork 500cb7bfe8cSJoe Wallwork /*@ 50131b70465SJoe Wallwork DMPlexMetricSetMaximumMagnitude - Set the maximum tolerated metric magnitude 50231b70465SJoe Wallwork 50331b70465SJoe Wallwork Input parameters: 50431b70465SJoe Wallwork + dm - The DM 50531b70465SJoe Wallwork - h_max - The maximum tolerated metric magnitude 50631b70465SJoe Wallwork 50731b70465SJoe Wallwork Level: beginner 50831b70465SJoe Wallwork 50931b70465SJoe Wallwork .seealso: DMPlexMetricGetMaximumMagnitude(), DMPlexMetricSetMinimumMagnitude() 510cb7bfe8cSJoe Wallwork @*/ 51131b70465SJoe Wallwork PetscErrorCode DMPlexMetricSetMaximumMagnitude(DM dm, PetscReal h_max) 51231b70465SJoe Wallwork { 51331b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 51431b70465SJoe Wallwork PetscErrorCode ierr; 51531b70465SJoe Wallwork 51631b70465SJoe Wallwork PetscFunctionBegin; 51731b70465SJoe Wallwork if (!plex->metricCtx) { 51831b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 51931b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 52031b70465SJoe Wallwork } 5212c71b3e2SJacob Faibussowitsch PetscCheckFalse(h_max <= 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Metric magnitudes must be positive, not %.4e", h_max); 52231b70465SJoe Wallwork plex->metricCtx->h_max = h_max; 52331b70465SJoe Wallwork PetscFunctionReturn(0); 52431b70465SJoe Wallwork } 52531b70465SJoe Wallwork 526cb7bfe8cSJoe Wallwork /*@ 52731b70465SJoe Wallwork DMPlexMetricGetMaximumMagnitude - Get the maximum tolerated metric magnitude 52831b70465SJoe Wallwork 52931b70465SJoe Wallwork Input parameters: 53031b70465SJoe Wallwork . dm - The DM 53131b70465SJoe Wallwork 532cc2eee55SJoe Wallwork Output parameters: 53331b70465SJoe Wallwork . h_max - The maximum tolerated metric magnitude 53431b70465SJoe Wallwork 53531b70465SJoe Wallwork Level: beginner 53631b70465SJoe Wallwork 53731b70465SJoe Wallwork .seealso: DMPlexMetricSetMaximumMagnitude(), DMPlexMetricGetMinimumMagnitude() 538cb7bfe8cSJoe Wallwork @*/ 53931b70465SJoe Wallwork PetscErrorCode DMPlexMetricGetMaximumMagnitude(DM dm, PetscReal *h_max) 54031b70465SJoe Wallwork { 54131b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 54231b70465SJoe Wallwork PetscErrorCode ierr; 54331b70465SJoe Wallwork 54431b70465SJoe Wallwork PetscFunctionBegin; 54531b70465SJoe Wallwork if (!plex->metricCtx) { 54631b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 54731b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 54831b70465SJoe Wallwork } 54931b70465SJoe Wallwork *h_max = plex->metricCtx->h_max; 55031b70465SJoe Wallwork PetscFunctionReturn(0); 55131b70465SJoe Wallwork } 55231b70465SJoe Wallwork 553cb7bfe8cSJoe Wallwork /*@ 55431b70465SJoe Wallwork DMPlexMetricSetMaximumAnisotropy - Set the maximum tolerated metric anisotropy 55531b70465SJoe Wallwork 55631b70465SJoe Wallwork Input parameters: 55731b70465SJoe Wallwork + dm - The DM 55831b70465SJoe Wallwork - a_max - The maximum tolerated metric anisotropy 55931b70465SJoe Wallwork 56031b70465SJoe Wallwork Level: beginner 56131b70465SJoe Wallwork 56231b70465SJoe Wallwork Note: If the value zero is given then anisotropy will not be restricted. Otherwise, it should be at least one. 56331b70465SJoe Wallwork 56431b70465SJoe Wallwork .seealso: DMPlexMetricGetMaximumAnisotropy(), DMPlexMetricSetMaximumMagnitude() 565cb7bfe8cSJoe Wallwork @*/ 56631b70465SJoe Wallwork PetscErrorCode DMPlexMetricSetMaximumAnisotropy(DM dm, PetscReal a_max) 56731b70465SJoe Wallwork { 56831b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 56931b70465SJoe Wallwork PetscErrorCode ierr; 57031b70465SJoe Wallwork 57131b70465SJoe Wallwork PetscFunctionBegin; 57231b70465SJoe Wallwork if (!plex->metricCtx) { 57331b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 57431b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 57531b70465SJoe Wallwork } 5762c71b3e2SJacob Faibussowitsch PetscCheckFalse(a_max < 1.0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Anisotropy must be at least one, not %.4e", a_max); 57731b70465SJoe Wallwork plex->metricCtx->a_max = a_max; 57831b70465SJoe Wallwork PetscFunctionReturn(0); 57931b70465SJoe Wallwork } 58031b70465SJoe Wallwork 581cb7bfe8cSJoe Wallwork /*@ 58231b70465SJoe Wallwork DMPlexMetricGetMaximumAnisotropy - Get the maximum tolerated metric anisotropy 58331b70465SJoe Wallwork 58431b70465SJoe Wallwork Input parameters: 58531b70465SJoe Wallwork . dm - The DM 58631b70465SJoe Wallwork 587cc2eee55SJoe Wallwork Output parameters: 58831b70465SJoe Wallwork . a_max - The maximum tolerated metric anisotropy 58931b70465SJoe Wallwork 59031b70465SJoe Wallwork Level: beginner 59131b70465SJoe Wallwork 59231b70465SJoe Wallwork .seealso: DMPlexMetricSetMaximumAnisotropy(), DMPlexMetricGetMaximumMagnitude() 593cb7bfe8cSJoe Wallwork @*/ 59431b70465SJoe Wallwork PetscErrorCode DMPlexMetricGetMaximumAnisotropy(DM dm, PetscReal *a_max) 59531b70465SJoe Wallwork { 59631b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 59731b70465SJoe Wallwork PetscErrorCode ierr; 59831b70465SJoe Wallwork 59931b70465SJoe Wallwork PetscFunctionBegin; 60031b70465SJoe Wallwork if (!plex->metricCtx) { 60131b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 60231b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 60331b70465SJoe Wallwork } 60431b70465SJoe Wallwork *a_max = plex->metricCtx->a_max; 60531b70465SJoe Wallwork PetscFunctionReturn(0); 60631b70465SJoe Wallwork } 60731b70465SJoe Wallwork 608cb7bfe8cSJoe Wallwork /*@ 60931b70465SJoe Wallwork DMPlexMetricSetTargetComplexity - Set the target metric complexity 61031b70465SJoe Wallwork 61131b70465SJoe Wallwork Input parameters: 61231b70465SJoe Wallwork + dm - The DM 61331b70465SJoe Wallwork - targetComplexity - The target metric complexity 61431b70465SJoe Wallwork 61531b70465SJoe Wallwork Level: beginner 61631b70465SJoe Wallwork 61731b70465SJoe Wallwork .seealso: DMPlexMetricGetTargetComplexity(), DMPlexMetricSetNormalizationOrder() 618cb7bfe8cSJoe Wallwork @*/ 61931b70465SJoe Wallwork PetscErrorCode DMPlexMetricSetTargetComplexity(DM dm, PetscReal targetComplexity) 62031b70465SJoe Wallwork { 62131b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 62231b70465SJoe Wallwork PetscErrorCode ierr; 62331b70465SJoe Wallwork 62431b70465SJoe Wallwork PetscFunctionBegin; 62531b70465SJoe Wallwork if (!plex->metricCtx) { 62631b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 62731b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 62831b70465SJoe Wallwork } 6292c71b3e2SJacob Faibussowitsch PetscCheckFalse(targetComplexity <= 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Metric complexity must be positive"); 63031b70465SJoe Wallwork plex->metricCtx->targetComplexity = targetComplexity; 63131b70465SJoe Wallwork PetscFunctionReturn(0); 63231b70465SJoe Wallwork } 63331b70465SJoe Wallwork 634cb7bfe8cSJoe Wallwork /*@ 63531b70465SJoe Wallwork DMPlexMetricGetTargetComplexity - Get the target metric complexity 63631b70465SJoe Wallwork 63731b70465SJoe Wallwork Input parameters: 63831b70465SJoe Wallwork . dm - The DM 63931b70465SJoe Wallwork 640cc2eee55SJoe Wallwork Output parameters: 64131b70465SJoe Wallwork . targetComplexity - The target metric complexity 64231b70465SJoe Wallwork 64331b70465SJoe Wallwork Level: beginner 64431b70465SJoe Wallwork 64531b70465SJoe Wallwork .seealso: DMPlexMetricSetTargetComplexity(), DMPlexMetricGetNormalizationOrder() 646cb7bfe8cSJoe Wallwork @*/ 64731b70465SJoe Wallwork PetscErrorCode DMPlexMetricGetTargetComplexity(DM dm, PetscReal *targetComplexity) 64831b70465SJoe Wallwork { 64931b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 65031b70465SJoe Wallwork PetscErrorCode ierr; 65131b70465SJoe Wallwork 65231b70465SJoe Wallwork PetscFunctionBegin; 65331b70465SJoe Wallwork if (!plex->metricCtx) { 65431b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 65531b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 65631b70465SJoe Wallwork } 65731b70465SJoe Wallwork *targetComplexity = plex->metricCtx->targetComplexity; 65831b70465SJoe Wallwork PetscFunctionReturn(0); 65931b70465SJoe Wallwork } 66031b70465SJoe Wallwork 661cb7bfe8cSJoe Wallwork /*@ 66231b70465SJoe Wallwork DMPlexMetricSetNormalizationOrder - Set the order p for L-p normalization 66331b70465SJoe Wallwork 66431b70465SJoe Wallwork Input parameters: 66531b70465SJoe Wallwork + dm - The DM 66631b70465SJoe Wallwork - p - The normalization order 66731b70465SJoe Wallwork 66831b70465SJoe Wallwork Level: beginner 66931b70465SJoe Wallwork 67031b70465SJoe Wallwork .seealso: DMPlexMetricGetNormalizationOrder(), DMPlexMetricSetTargetComplexity() 671cb7bfe8cSJoe Wallwork @*/ 67231b70465SJoe Wallwork PetscErrorCode DMPlexMetricSetNormalizationOrder(DM dm, PetscReal p) 67331b70465SJoe Wallwork { 67431b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 67531b70465SJoe Wallwork PetscErrorCode ierr; 67631b70465SJoe Wallwork 67731b70465SJoe Wallwork PetscFunctionBegin; 67831b70465SJoe Wallwork if (!plex->metricCtx) { 67931b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 68031b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 68131b70465SJoe Wallwork } 6822c71b3e2SJacob Faibussowitsch PetscCheckFalse(p < 1.0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Normalization order must be one or greater"); 68331b70465SJoe Wallwork plex->metricCtx->p = p; 68431b70465SJoe Wallwork PetscFunctionReturn(0); 68531b70465SJoe Wallwork } 68631b70465SJoe Wallwork 687cb7bfe8cSJoe Wallwork /*@ 68831b70465SJoe Wallwork DMPlexMetricGetNormalizationOrder - Get the order p for L-p normalization 68931b70465SJoe Wallwork 69031b70465SJoe Wallwork Input parameters: 69131b70465SJoe Wallwork . dm - The DM 69231b70465SJoe Wallwork 693cc2eee55SJoe Wallwork Output parameters: 69431b70465SJoe Wallwork . p - The normalization order 69531b70465SJoe Wallwork 69631b70465SJoe Wallwork Level: beginner 69731b70465SJoe Wallwork 69831b70465SJoe Wallwork .seealso: DMPlexMetricSetNormalizationOrder(), DMPlexMetricGetTargetComplexity() 699cb7bfe8cSJoe Wallwork @*/ 70031b70465SJoe Wallwork PetscErrorCode DMPlexMetricGetNormalizationOrder(DM dm, PetscReal *p) 70131b70465SJoe Wallwork { 70231b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 70331b70465SJoe Wallwork PetscErrorCode ierr; 70431b70465SJoe Wallwork 70531b70465SJoe Wallwork PetscFunctionBegin; 70631b70465SJoe Wallwork if (!plex->metricCtx) { 70731b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 70831b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 70931b70465SJoe Wallwork } 71031b70465SJoe Wallwork *p = plex->metricCtx->p; 71131b70465SJoe Wallwork PetscFunctionReturn(0); 71231b70465SJoe Wallwork } 71331b70465SJoe Wallwork 714cb7bfe8cSJoe Wallwork /*@ 715cc2eee55SJoe Wallwork DMPlexMetricSetGradationFactor - Set the metric gradation factor 716cc2eee55SJoe Wallwork 717cc2eee55SJoe Wallwork Input parameters: 718cc2eee55SJoe Wallwork + dm - The DM 719cc2eee55SJoe Wallwork - beta - The metric gradation factor 720cc2eee55SJoe Wallwork 721cc2eee55SJoe Wallwork Level: beginner 722cc2eee55SJoe Wallwork 723cc2eee55SJoe Wallwork Notes: 724cc2eee55SJoe Wallwork 725cc2eee55SJoe Wallwork The gradation factor is the maximum tolerated length ratio between adjacent edges. 726cc2eee55SJoe Wallwork 727cc2eee55SJoe Wallwork Turn off gradation by passing the value -1. Otherwise, pass a positive value. 728cc2eee55SJoe Wallwork 729cb7bfe8cSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 730cb7bfe8cSJoe Wallwork 731ae8b063eSJoe Wallwork .seealso: DMPlexMetricGetGradationFactor(), DMPlexMetricSetHausdorffNumber() 732cb7bfe8cSJoe Wallwork @*/ 733cc2eee55SJoe Wallwork PetscErrorCode DMPlexMetricSetGradationFactor(DM dm, PetscReal beta) 734cc2eee55SJoe Wallwork { 735cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 736cc2eee55SJoe Wallwork PetscErrorCode ierr; 737cc2eee55SJoe Wallwork 738cc2eee55SJoe Wallwork PetscFunctionBegin; 739cc2eee55SJoe Wallwork if (!plex->metricCtx) { 740cc2eee55SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 741cc2eee55SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 742cc2eee55SJoe Wallwork } 743cc2eee55SJoe Wallwork plex->metricCtx->gradationFactor = beta; 744cc2eee55SJoe Wallwork PetscFunctionReturn(0); 745cc2eee55SJoe Wallwork } 746cc2eee55SJoe Wallwork 747cb7bfe8cSJoe Wallwork /*@ 748cc2eee55SJoe Wallwork DMPlexMetricGetGradationFactor - Get the metric gradation factor 749cc2eee55SJoe Wallwork 750cc2eee55SJoe Wallwork Input parameters: 751cc2eee55SJoe Wallwork . dm - The DM 752cc2eee55SJoe Wallwork 753cc2eee55SJoe Wallwork Output parameters: 754cc2eee55SJoe Wallwork . beta - The metric gradation factor 755cc2eee55SJoe Wallwork 756cc2eee55SJoe Wallwork Level: beginner 757cc2eee55SJoe Wallwork 758cb7bfe8cSJoe Wallwork Notes: 759cb7bfe8cSJoe Wallwork 760cb7bfe8cSJoe Wallwork The gradation factor is the maximum tolerated length ratio between adjacent edges. 761cb7bfe8cSJoe Wallwork 762cb7bfe8cSJoe Wallwork The value -1 implies that gradation is turned off. 763cb7bfe8cSJoe Wallwork 764cb7bfe8cSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 765cc2eee55SJoe Wallwork 766ae8b063eSJoe Wallwork .seealso: DMPlexMetricSetGradationFactor(), DMPlexMetricGetHausdorffNumber() 767cb7bfe8cSJoe Wallwork @*/ 768cc2eee55SJoe Wallwork PetscErrorCode DMPlexMetricGetGradationFactor(DM dm, PetscReal *beta) 769cc2eee55SJoe Wallwork { 770cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 771cc2eee55SJoe Wallwork PetscErrorCode ierr; 772cc2eee55SJoe Wallwork 773cc2eee55SJoe Wallwork PetscFunctionBegin; 774cc2eee55SJoe Wallwork if (!plex->metricCtx) { 775cc2eee55SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 776cc2eee55SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 777cc2eee55SJoe Wallwork } 778cc2eee55SJoe Wallwork *beta = plex->metricCtx->gradationFactor; 779cc2eee55SJoe Wallwork PetscFunctionReturn(0); 780cc2eee55SJoe Wallwork } 781cc2eee55SJoe Wallwork 782cb7bfe8cSJoe Wallwork /*@ 783ae8b063eSJoe Wallwork DMPlexMetricSetHausdorffNumber - Set the metric Hausdorff number 784ae8b063eSJoe Wallwork 785ae8b063eSJoe Wallwork Input parameters: 786ae8b063eSJoe Wallwork + dm - The DM 787ae8b063eSJoe Wallwork - hausd - The metric Hausdorff number 788ae8b063eSJoe Wallwork 789ae8b063eSJoe Wallwork Level: beginner 790ae8b063eSJoe Wallwork 791ae8b063eSJoe Wallwork Notes: 792ae8b063eSJoe Wallwork 793ae8b063eSJoe Wallwork The Hausdorff number imposes the maximal distance between the piecewise linear approximation of the 794ae8b063eSJoe Wallwork boundary and the reconstructed ideal boundary. Thus, a low Hausdorff parameter leads to refine the 795ae8b063eSJoe Wallwork high curvature areas. By default, the Hausdorff value is set to 0.01, which is a suitable value for 796ae8b063eSJoe Wallwork an object of size 1 in each direction. For smaller (resp. larger) objects, you may need to decrease 797ae8b063eSJoe Wallwork (resp. increase) the Hausdorff parameter. (Taken from 798ae8b063eSJoe Wallwork https://www.mmgtools.org/mmg-remesher-try-mmg/mmg-remesher-options/mmg-remesher-option-hausd). 799ae8b063eSJoe Wallwork 800ae8b063eSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 801ae8b063eSJoe Wallwork 802ae8b063eSJoe Wallwork .seealso: DMPlexMetricSetGradationFactor(), DMPlexMetricGetHausdorffNumber() 803ae8b063eSJoe Wallwork @*/ 804ae8b063eSJoe Wallwork PetscErrorCode DMPlexMetricSetHausdorffNumber(DM dm, PetscReal hausd) 805ae8b063eSJoe Wallwork { 806ae8b063eSJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 807ae8b063eSJoe Wallwork PetscErrorCode ierr; 808ae8b063eSJoe Wallwork 809ae8b063eSJoe Wallwork PetscFunctionBegin; 810ae8b063eSJoe Wallwork if (!plex->metricCtx) { 811ae8b063eSJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 812ae8b063eSJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 813ae8b063eSJoe Wallwork } 814ae8b063eSJoe Wallwork plex->metricCtx->hausdorffNumber = hausd; 815ae8b063eSJoe Wallwork PetscFunctionReturn(0); 816ae8b063eSJoe Wallwork } 817ae8b063eSJoe Wallwork 818ae8b063eSJoe Wallwork /*@ 819ae8b063eSJoe Wallwork DMPlexMetricGetHausdorffNumber - Get the metric Hausdorff number 820ae8b063eSJoe Wallwork 821ae8b063eSJoe Wallwork Input parameters: 822ae8b063eSJoe Wallwork . dm - The DM 823ae8b063eSJoe Wallwork 824ae8b063eSJoe Wallwork Output parameters: 825ae8b063eSJoe Wallwork . hausd - The metric Hausdorff number 826ae8b063eSJoe Wallwork 827ae8b063eSJoe Wallwork Level: beginner 828ae8b063eSJoe Wallwork 829ae8b063eSJoe Wallwork Notes: 830ae8b063eSJoe Wallwork 831ae8b063eSJoe Wallwork The Hausdorff number imposes the maximal distance between the piecewise linear approximation of the 832ae8b063eSJoe Wallwork boundary and the reconstructed ideal boundary. Thus, a low Hausdorff parameter leads to refine the 833ae8b063eSJoe Wallwork high curvature areas. By default, the Hausdorff value is set to 0.01, which is a suitable value for 834ae8b063eSJoe Wallwork an object of size 1 in each direction. For smaller (resp. larger) objects, you may need to decrease 835ae8b063eSJoe Wallwork (resp. increase) the Hausdorff parameter. (Taken from 836ae8b063eSJoe Wallwork https://www.mmgtools.org/mmg-remesher-try-mmg/mmg-remesher-options/mmg-remesher-option-hausd). 837ae8b063eSJoe Wallwork 838ae8b063eSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 839ae8b063eSJoe Wallwork 840ae8b063eSJoe Wallwork .seealso: DMPlexMetricGetGradationFactor(), DMPlexMetricSetHausdorffNumber() 841ae8b063eSJoe Wallwork @*/ 842ae8b063eSJoe Wallwork PetscErrorCode DMPlexMetricGetHausdorffNumber(DM dm, PetscReal *hausd) 843ae8b063eSJoe Wallwork { 844ae8b063eSJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 845ae8b063eSJoe Wallwork PetscErrorCode ierr; 846ae8b063eSJoe Wallwork 847ae8b063eSJoe Wallwork PetscFunctionBegin; 848ae8b063eSJoe Wallwork if (!plex->metricCtx) { 849ae8b063eSJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 850ae8b063eSJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 851ae8b063eSJoe Wallwork } 852ae8b063eSJoe Wallwork *hausd = plex->metricCtx->hausdorffNumber; 853ae8b063eSJoe Wallwork PetscFunctionReturn(0); 854ae8b063eSJoe Wallwork } 855ae8b063eSJoe Wallwork 856ae8b063eSJoe Wallwork /*@ 857cc2eee55SJoe Wallwork DMPlexMetricSetVerbosity - Set the verbosity of the mesh adaptation package 858cc2eee55SJoe Wallwork 859cc2eee55SJoe Wallwork Input parameters: 860cc2eee55SJoe Wallwork + dm - The DM 861cc2eee55SJoe Wallwork - verbosity - The verbosity, where -1 is silent and 10 is maximum 862cc2eee55SJoe Wallwork 863cb7bfe8cSJoe Wallwork Level: beginner 864cb7bfe8cSJoe Wallwork 865cb7bfe8cSJoe Wallwork Notes: 866cb7bfe8cSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 867cb7bfe8cSJoe Wallwork 868cc2eee55SJoe Wallwork .seealso: DMPlexMetricGetVerbosity(), DMPlexMetricSetNumIterations() 869cb7bfe8cSJoe Wallwork @*/ 870cc2eee55SJoe Wallwork PetscErrorCode DMPlexMetricSetVerbosity(DM dm, PetscInt verbosity) 871cc2eee55SJoe Wallwork { 872cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 873cc2eee55SJoe Wallwork PetscErrorCode ierr; 874cc2eee55SJoe Wallwork 875cc2eee55SJoe Wallwork PetscFunctionBegin; 876cc2eee55SJoe Wallwork if (!plex->metricCtx) { 877cc2eee55SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 878cc2eee55SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 879cc2eee55SJoe Wallwork } 880cc2eee55SJoe Wallwork plex->metricCtx->verbosity = verbosity; 881cc2eee55SJoe Wallwork PetscFunctionReturn(0); 882cc2eee55SJoe Wallwork } 883cc2eee55SJoe Wallwork 884cb7bfe8cSJoe Wallwork /*@ 885cc2eee55SJoe Wallwork DMPlexMetricGetVerbosity - Get the verbosity of the mesh adaptation package 886cc2eee55SJoe Wallwork 887cc2eee55SJoe Wallwork Input parameters: 888cc2eee55SJoe Wallwork . dm - The DM 889cc2eee55SJoe Wallwork 890cc2eee55SJoe Wallwork Output parameters: 891cc2eee55SJoe Wallwork . verbosity - The verbosity, where -1 is silent and 10 is maximum 892cc2eee55SJoe Wallwork 893cb7bfe8cSJoe Wallwork Level: beginner 894cb7bfe8cSJoe Wallwork 895cb7bfe8cSJoe Wallwork Notes: 896cb7bfe8cSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic). 897cb7bfe8cSJoe Wallwork 898cc2eee55SJoe Wallwork .seealso: DMPlexMetricSetVerbosity(), DMPlexMetricGetNumIterations() 899cb7bfe8cSJoe Wallwork @*/ 900cc2eee55SJoe Wallwork PetscErrorCode DMPlexMetricGetVerbosity(DM dm, PetscInt *verbosity) 901cc2eee55SJoe Wallwork { 902cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 903cc2eee55SJoe Wallwork PetscErrorCode ierr; 904cc2eee55SJoe Wallwork 905cc2eee55SJoe Wallwork PetscFunctionBegin; 906cc2eee55SJoe Wallwork if (!plex->metricCtx) { 907cc2eee55SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 908cc2eee55SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 909cc2eee55SJoe Wallwork } 910cc2eee55SJoe Wallwork *verbosity = plex->metricCtx->verbosity; 911cc2eee55SJoe Wallwork PetscFunctionReturn(0); 912cc2eee55SJoe Wallwork } 913cc2eee55SJoe Wallwork 914cb7bfe8cSJoe Wallwork /*@ 915cc2eee55SJoe Wallwork DMPlexMetricSetNumIterations - Set the number of parallel adaptation iterations 916cc2eee55SJoe Wallwork 917cc2eee55SJoe Wallwork Input parameters: 918cc2eee55SJoe Wallwork + dm - The DM 919cc2eee55SJoe Wallwork - numIter - the number of parallel adaptation iterations 920cc2eee55SJoe Wallwork 921cb7bfe8cSJoe Wallwork Level: beginner 922cb7bfe8cSJoe Wallwork 923cb7bfe8cSJoe Wallwork Notes: 924cb7bfe8cSJoe Wallwork This is only used by ParMmg (not Pragmatic or Mmg). 925cc2eee55SJoe Wallwork 926cc2eee55SJoe Wallwork .seealso: DMPlexMetricSetVerbosity(), DMPlexMetricGetNumIterations() 927cb7bfe8cSJoe Wallwork @*/ 928cc2eee55SJoe Wallwork PetscErrorCode DMPlexMetricSetNumIterations(DM dm, PetscInt numIter) 929cc2eee55SJoe Wallwork { 930cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 931cc2eee55SJoe Wallwork PetscErrorCode ierr; 932cc2eee55SJoe Wallwork 933cc2eee55SJoe Wallwork PetscFunctionBegin; 934cc2eee55SJoe Wallwork if (!plex->metricCtx) { 935cc2eee55SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 936cc2eee55SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 937cc2eee55SJoe Wallwork } 938cc2eee55SJoe Wallwork plex->metricCtx->numIter = numIter; 939cc2eee55SJoe Wallwork PetscFunctionReturn(0); 940cc2eee55SJoe Wallwork } 941cc2eee55SJoe Wallwork 942cb7bfe8cSJoe Wallwork /*@ 943cc2eee55SJoe Wallwork DMPlexMetricGetNumIterations - Get the number of parallel adaptation iterations 944cc2eee55SJoe Wallwork 945cc2eee55SJoe Wallwork Input parameters: 946cc2eee55SJoe Wallwork . dm - The DM 947cc2eee55SJoe Wallwork 948cc2eee55SJoe Wallwork Output parameters: 949cc2eee55SJoe Wallwork . numIter - the number of parallel adaptation iterations 950cc2eee55SJoe Wallwork 951cb7bfe8cSJoe Wallwork Level: beginner 952cb7bfe8cSJoe Wallwork 953cb7bfe8cSJoe Wallwork Notes: 954cb7bfe8cSJoe Wallwork This is only used by Mmg and ParMmg (not Pragmatic or Mmg). 955cc2eee55SJoe Wallwork 956cc2eee55SJoe Wallwork .seealso: DMPlexMetricSetNumIterations(), DMPlexMetricGetVerbosity() 957cb7bfe8cSJoe Wallwork @*/ 958cc2eee55SJoe Wallwork PetscErrorCode DMPlexMetricGetNumIterations(DM dm, PetscInt *numIter) 959cc2eee55SJoe Wallwork { 960cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 961cc2eee55SJoe Wallwork PetscErrorCode ierr; 962cc2eee55SJoe Wallwork 963cc2eee55SJoe Wallwork PetscFunctionBegin; 964cc2eee55SJoe Wallwork if (!plex->metricCtx) { 965cc2eee55SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 966cc2eee55SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 967cc2eee55SJoe Wallwork } 968cc2eee55SJoe Wallwork *numIter = plex->metricCtx->numIter; 969cc2eee55SJoe Wallwork PetscFunctionReturn(0); 970cc2eee55SJoe Wallwork } 971cc2eee55SJoe Wallwork 97220282da2SJoe Wallwork PetscErrorCode DMPlexP1FieldCreate_Private(DM dm, PetscInt f, PetscInt size, Vec *metric) 97320282da2SJoe Wallwork { 97420282da2SJoe Wallwork MPI_Comm comm; 97520282da2SJoe Wallwork PetscErrorCode ierr; 97620282da2SJoe Wallwork PetscFE fe; 97720282da2SJoe Wallwork PetscInt dim; 97820282da2SJoe Wallwork 97920282da2SJoe Wallwork PetscFunctionBegin; 98020282da2SJoe Wallwork 98120282da2SJoe Wallwork /* Extract metadata from dm */ 98220282da2SJoe Wallwork ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 98320282da2SJoe Wallwork ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 98420282da2SJoe Wallwork 98520282da2SJoe Wallwork /* Create a P1 field of the requested size */ 98620282da2SJoe Wallwork ierr = PetscFECreateLagrange(comm, dim, size, PETSC_TRUE, 1, PETSC_DETERMINE, &fe);CHKERRQ(ierr); 98720282da2SJoe Wallwork ierr = DMSetField(dm, f, NULL, (PetscObject)fe);CHKERRQ(ierr); 98820282da2SJoe Wallwork ierr = DMCreateDS(dm);CHKERRQ(ierr); 98920282da2SJoe Wallwork ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 99020282da2SJoe Wallwork ierr = DMCreateLocalVector(dm, metric);CHKERRQ(ierr); 99120282da2SJoe Wallwork 99220282da2SJoe Wallwork PetscFunctionReturn(0); 99320282da2SJoe Wallwork } 99420282da2SJoe Wallwork 995cb7bfe8cSJoe Wallwork /*@ 99620282da2SJoe Wallwork DMPlexMetricCreate - Create a Riemannian metric field 99720282da2SJoe Wallwork 99820282da2SJoe Wallwork Input parameters: 99920282da2SJoe Wallwork + dm - The DM 100020282da2SJoe Wallwork - f - The field number to use 100120282da2SJoe Wallwork 100220282da2SJoe Wallwork Output parameter: 100320282da2SJoe Wallwork . metric - The metric 100420282da2SJoe Wallwork 100520282da2SJoe Wallwork Level: beginner 100620282da2SJoe Wallwork 100731b70465SJoe Wallwork Notes: 100831b70465SJoe Wallwork 100931b70465SJoe Wallwork It is assumed that the DM is comprised of simplices. 101031b70465SJoe Wallwork 101131b70465SJoe Wallwork Command line options for Riemannian metrics: 101231b70465SJoe Wallwork 1013cb7bfe8cSJoe Wallwork + -dm_plex_metric_isotropic - Is the metric isotropic? 101493520041SJoe Wallwork . -dm_plex_metric_uniform - Is the metric uniform? 1015cb7bfe8cSJoe Wallwork . -dm_plex_metric_restrict_anisotropy_first - Should anisotropy be restricted before normalization? 1016cb7bfe8cSJoe Wallwork . -dm_plex_metric_h_min - Minimum tolerated metric magnitude 1017cb7bfe8cSJoe Wallwork . -dm_plex_metric_h_max - Maximum tolerated metric magnitude 1018cb7bfe8cSJoe Wallwork . -dm_plex_metric_a_max - Maximum tolerated anisotropy 1019cb7bfe8cSJoe Wallwork . -dm_plex_metric_p - L-p normalization order 102067b8a455SSatish Balay - -dm_plex_metric_target_complexity - Target metric complexity 1021cb7bfe8cSJoe Wallwork 1022cb7bfe8cSJoe Wallwork Switching between remeshers can be achieved using 1023cb7bfe8cSJoe Wallwork 102467b8a455SSatish Balay . -dm_adaptor <pragmatic/mmg/parmmg> - specify dm adaptor to use 1025cb7bfe8cSJoe Wallwork 1026cb7bfe8cSJoe Wallwork Further options that are only relevant to Mmg and ParMmg: 1027cb7bfe8cSJoe Wallwork 1028cb7bfe8cSJoe Wallwork + -dm_plex_metric_gradation_factor - Maximum ratio by which edge lengths may grow during gradation 1029cb7bfe8cSJoe Wallwork . -dm_plex_metric_num_iterations - Number of parallel mesh adaptation iterations for ParMmg 1030cb7bfe8cSJoe Wallwork . -dm_plex_metric_no_insert - Should node insertion/deletion be turned off? 1031cb7bfe8cSJoe Wallwork . -dm_plex_metric_no_swap - Should facet swapping be turned off? 1032cb7bfe8cSJoe Wallwork . -dm_plex_metric_no_move - Should node movement be turned off? 1033cb7bfe8cSJoe Wallwork - -dm_plex_metric_verbosity - Choose a verbosity level from -1 (silent) to 10 (maximum). 103420282da2SJoe Wallwork 103520282da2SJoe Wallwork .seealso: DMPlexMetricCreateUniform(), DMPlexMetricCreateIsotropic() 1036cb7bfe8cSJoe Wallwork @*/ 103720282da2SJoe Wallwork PetscErrorCode DMPlexMetricCreate(DM dm, PetscInt f, Vec *metric) 103820282da2SJoe Wallwork { 103931b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 104093520041SJoe Wallwork PetscBool isotropic, uniform; 104120282da2SJoe Wallwork PetscErrorCode ierr; 104220282da2SJoe Wallwork PetscInt coordDim, Nd; 104320282da2SJoe Wallwork 104420282da2SJoe Wallwork PetscFunctionBegin; 104531b70465SJoe Wallwork if (!plex->metricCtx) { 104631b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 104731b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 104831b70465SJoe Wallwork } 104920282da2SJoe Wallwork ierr = DMGetCoordinateDim(dm, &coordDim);CHKERRQ(ierr); 105020282da2SJoe Wallwork Nd = coordDim*coordDim; 105193520041SJoe Wallwork ierr = DMPlexMetricIsUniform(dm, &uniform);CHKERRQ(ierr); 105293520041SJoe Wallwork ierr = DMPlexMetricIsIsotropic(dm, &isotropic);CHKERRQ(ierr); 105393520041SJoe Wallwork if (uniform) { 105493520041SJoe Wallwork MPI_Comm comm; 105593520041SJoe Wallwork 105693520041SJoe Wallwork ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 10572c71b3e2SJacob Faibussowitsch PetscCheckFalse(!isotropic,comm, PETSC_ERR_ARG_WRONG, "Uniform anisotropic metrics not supported"); 105893520041SJoe Wallwork ierr = VecCreate(comm, metric);CHKERRQ(ierr); 105993520041SJoe Wallwork ierr = VecSetSizes(*metric, 1, PETSC_DECIDE);CHKERRQ(ierr); 106093520041SJoe Wallwork ierr = VecSetFromOptions(*metric);CHKERRQ(ierr); 106193520041SJoe Wallwork } else if (isotropic) { 106293520041SJoe Wallwork ierr = DMPlexP1FieldCreate_Private(dm, f, 1, metric);CHKERRQ(ierr); 106393520041SJoe Wallwork } else { 106420282da2SJoe Wallwork ierr = DMPlexP1FieldCreate_Private(dm, f, Nd, metric);CHKERRQ(ierr); 106593520041SJoe Wallwork } 106620282da2SJoe Wallwork PetscFunctionReturn(0); 106720282da2SJoe Wallwork } 106820282da2SJoe Wallwork 1069cb7bfe8cSJoe Wallwork /*@ 107020282da2SJoe Wallwork DMPlexMetricCreateUniform - Construct a uniform isotropic metric 107120282da2SJoe Wallwork 107220282da2SJoe Wallwork Input parameters: 107320282da2SJoe Wallwork + dm - The DM 107420282da2SJoe Wallwork . f - The field number to use 107520282da2SJoe Wallwork - alpha - Scaling parameter for the diagonal 107620282da2SJoe Wallwork 107720282da2SJoe Wallwork Output parameter: 107820282da2SJoe Wallwork . metric - The uniform metric 107920282da2SJoe Wallwork 108020282da2SJoe Wallwork Level: beginner 108120282da2SJoe Wallwork 108293520041SJoe Wallwork Note: In this case, the metric is constant in space and so is only specified for a single vertex. 108320282da2SJoe Wallwork 108420282da2SJoe Wallwork .seealso: DMPlexMetricCreate(), DMPlexMetricCreateIsotropic() 1085cb7bfe8cSJoe Wallwork @*/ 108620282da2SJoe Wallwork PetscErrorCode DMPlexMetricCreateUniform(DM dm, PetscInt f, PetscReal alpha, Vec *metric) 108720282da2SJoe Wallwork { 108820282da2SJoe Wallwork PetscErrorCode ierr; 108920282da2SJoe Wallwork 109020282da2SJoe Wallwork PetscFunctionBegin; 109193520041SJoe Wallwork ierr = DMPlexMetricSetUniform(dm, PETSC_TRUE);CHKERRQ(ierr); 109220282da2SJoe Wallwork ierr = DMPlexMetricCreate(dm, f, metric);CHKERRQ(ierr); 10932c71b3e2SJacob Faibussowitsch PetscCheck(alpha,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Uniform metric scaling is undefined"); 10942c71b3e2SJacob Faibussowitsch PetscCheck(alpha >= 1.0e-30,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Uniform metric scaling %e should be positive", alpha); 109593520041SJoe Wallwork ierr = VecSet(*metric, alpha);CHKERRQ(ierr); 109693520041SJoe Wallwork ierr = VecAssemblyBegin(*metric);CHKERRQ(ierr); 109793520041SJoe Wallwork ierr = VecAssemblyEnd(*metric);CHKERRQ(ierr); 109820282da2SJoe Wallwork PetscFunctionReturn(0); 109920282da2SJoe Wallwork } 110020282da2SJoe Wallwork 110193520041SJoe Wallwork static void identity(PetscInt dim, PetscInt Nf, PetscInt NfAux, 110293520041SJoe Wallwork const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 110393520041SJoe Wallwork const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 110493520041SJoe Wallwork PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 110593520041SJoe Wallwork { 110693520041SJoe Wallwork f0[0] = u[0]; 110793520041SJoe Wallwork } 110893520041SJoe Wallwork 1109cb7bfe8cSJoe Wallwork /*@ 111020282da2SJoe Wallwork DMPlexMetricCreateIsotropic - Construct an isotropic metric from an error indicator 111120282da2SJoe Wallwork 111220282da2SJoe Wallwork Input parameters: 111320282da2SJoe Wallwork + dm - The DM 111420282da2SJoe Wallwork . f - The field number to use 111520282da2SJoe Wallwork - indicator - The error indicator 111620282da2SJoe Wallwork 111720282da2SJoe Wallwork Output parameter: 111820282da2SJoe Wallwork . metric - The isotropic metric 111920282da2SJoe Wallwork 112020282da2SJoe Wallwork Level: beginner 112120282da2SJoe Wallwork 112220282da2SJoe Wallwork Notes: 112320282da2SJoe Wallwork 112420282da2SJoe Wallwork It is assumed that the DM is comprised of simplices. 112520282da2SJoe Wallwork 112693520041SJoe Wallwork The indicator needs to be a scalar field. If it is not defined vertex-wise, then it is projected appropriately. 112720282da2SJoe Wallwork 112820282da2SJoe Wallwork .seealso: DMPlexMetricCreate(), DMPlexMetricCreateUniform() 1129cb7bfe8cSJoe Wallwork @*/ 113020282da2SJoe Wallwork PetscErrorCode DMPlexMetricCreateIsotropic(DM dm, PetscInt f, Vec indicator, Vec *metric) 113120282da2SJoe Wallwork { 113220282da2SJoe Wallwork PetscErrorCode ierr; 113393520041SJoe Wallwork PetscInt m, n; 113420282da2SJoe Wallwork 113520282da2SJoe Wallwork PetscFunctionBegin; 113693520041SJoe Wallwork ierr = DMPlexMetricSetIsotropic(dm, PETSC_TRUE);CHKERRQ(ierr); 113720282da2SJoe Wallwork ierr = DMPlexMetricCreate(dm, f, metric);CHKERRQ(ierr); 113893520041SJoe Wallwork ierr = VecGetSize(indicator, &m);CHKERRQ(ierr); 113993520041SJoe Wallwork ierr = VecGetSize(*metric, &n);CHKERRQ(ierr); 114093520041SJoe Wallwork if (m == n) { ierr = VecCopy(indicator, *metric);CHKERRQ(ierr); } 114193520041SJoe Wallwork else { 114293520041SJoe Wallwork DM dmIndi; 114393520041SJoe Wallwork void (*funcs[1])(PetscInt, PetscInt, PetscInt, 114493520041SJoe Wallwork const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 114593520041SJoe Wallwork const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 114693520041SJoe Wallwork PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]); 114793520041SJoe Wallwork 114820282da2SJoe Wallwork ierr = VecGetDM(indicator, &dmIndi);CHKERRQ(ierr); 114993520041SJoe Wallwork funcs[0] = identity; 115093520041SJoe Wallwork ierr = DMProjectFieldLocal(dmIndi, 0.0, indicator, funcs, INSERT_VALUES, *metric);CHKERRQ(ierr); 115120282da2SJoe Wallwork } 115220282da2SJoe Wallwork PetscFunctionReturn(0); 115320282da2SJoe Wallwork } 115420282da2SJoe Wallwork 115582490253SJoe Wallwork static PetscErrorCode LAPACKsyevFail(PetscInt dim, PetscScalar Mpos[]) 115682490253SJoe Wallwork { 115782490253SJoe Wallwork PetscInt i, j; 115882490253SJoe Wallwork 115982490253SJoe Wallwork PetscFunctionBegin; 116082490253SJoe Wallwork PetscPrintf(PETSC_COMM_SELF, "Failed to apply LAPACKsyev to the matrix\n"); 116182490253SJoe Wallwork for (i = 0; i < dim; ++i) { 116282490253SJoe Wallwork if (i == 0) PetscPrintf(PETSC_COMM_SELF, " [["); 116382490253SJoe Wallwork else PetscPrintf(PETSC_COMM_SELF, " ["); 116482490253SJoe Wallwork for (j = 0; j < dim; ++j) { 116582490253SJoe Wallwork if (j < dim-1) PetscPrintf(PETSC_COMM_SELF, "%15.8e, ", Mpos[i*dim+j]); 116682490253SJoe Wallwork else PetscPrintf(PETSC_COMM_SELF, "%15.8e", Mpos[i*dim+j]); 116782490253SJoe Wallwork } 116882490253SJoe Wallwork if (i < dim-1) PetscPrintf(PETSC_COMM_SELF, "]\n"); 116982490253SJoe Wallwork else PetscPrintf(PETSC_COMM_SELF, "]]\n"); 117082490253SJoe Wallwork } 117182490253SJoe Wallwork PetscFunctionReturn(0); 117282490253SJoe Wallwork } 117382490253SJoe Wallwork 11743f07679eSJoe Wallwork static PetscErrorCode DMPlexMetricModify_Private(PetscInt dim, PetscReal h_min, PetscReal h_max, PetscReal a_max, PetscScalar Mp[], PetscScalar *detMp) 117520282da2SJoe Wallwork { 117620282da2SJoe Wallwork PetscErrorCode ierr; 117720282da2SJoe Wallwork PetscInt i, j, k; 117820282da2SJoe 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); 117920282da2SJoe Wallwork PetscScalar *Mpos; 118020282da2SJoe Wallwork 118120282da2SJoe Wallwork PetscFunctionBegin; 118220282da2SJoe Wallwork ierr = PetscMalloc2(dim*dim, &Mpos, dim, &eigs);CHKERRQ(ierr); 118320282da2SJoe Wallwork 118420282da2SJoe Wallwork /* Symmetrize */ 118520282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 118620282da2SJoe Wallwork Mpos[i*dim+i] = Mp[i*dim+i]; 118720282da2SJoe Wallwork for (j = i+1; j < dim; ++j) { 118820282da2SJoe Wallwork Mpos[i*dim+j] = 0.5*(Mp[i*dim+j] + Mp[j*dim+i]); 118920282da2SJoe Wallwork Mpos[j*dim+i] = Mpos[i*dim+j]; 119020282da2SJoe Wallwork } 119120282da2SJoe Wallwork } 119220282da2SJoe Wallwork 119320282da2SJoe Wallwork /* Compute eigendecomposition */ 119493520041SJoe Wallwork if (dim == 1) { 119593520041SJoe Wallwork 119693520041SJoe Wallwork /* Isotropic case */ 119793520041SJoe Wallwork eigs[0] = PetscRealPart(Mpos[0]); 119893520041SJoe Wallwork Mpos[0] = 1.0; 119993520041SJoe Wallwork } else { 120093520041SJoe Wallwork 120193520041SJoe Wallwork /* Anisotropic case */ 120220282da2SJoe Wallwork PetscScalar *work; 120320282da2SJoe Wallwork PetscBLASInt lwork; 120420282da2SJoe Wallwork 120520282da2SJoe Wallwork lwork = 5*dim; 120620282da2SJoe Wallwork ierr = PetscMalloc1(5*dim, &work);CHKERRQ(ierr); 120720282da2SJoe Wallwork { 120820282da2SJoe Wallwork PetscBLASInt lierr; 120920282da2SJoe Wallwork PetscBLASInt nb; 121020282da2SJoe Wallwork 121120282da2SJoe Wallwork ierr = PetscBLASIntCast(dim, &nb);CHKERRQ(ierr); 121220282da2SJoe Wallwork ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 121320282da2SJoe Wallwork #if defined(PETSC_USE_COMPLEX) 121420282da2SJoe Wallwork { 121520282da2SJoe Wallwork PetscReal *rwork; 121620282da2SJoe Wallwork ierr = PetscMalloc1(3*dim, &rwork);CHKERRQ(ierr); 121720282da2SJoe Wallwork PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&nb,Mpos,&nb,eigs,work,&lwork,rwork,&lierr)); 121820282da2SJoe Wallwork ierr = PetscFree(rwork);CHKERRQ(ierr); 121920282da2SJoe Wallwork } 122020282da2SJoe Wallwork #else 122120282da2SJoe Wallwork PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&nb,Mpos,&nb,eigs,work,&lwork,&lierr)); 122220282da2SJoe Wallwork #endif 122382490253SJoe Wallwork if (lierr) { 122482490253SJoe Wallwork for (i = 0; i < dim; ++i) { 122582490253SJoe Wallwork Mpos[i*dim+i] = Mp[i*dim+i]; 122682490253SJoe Wallwork for (j = i+1; j < dim; ++j) { 122782490253SJoe Wallwork Mpos[i*dim+j] = 0.5*(Mp[i*dim+j] + Mp[j*dim+i]); 122882490253SJoe Wallwork Mpos[j*dim+i] = Mpos[i*dim+j]; 122982490253SJoe Wallwork } 123082490253SJoe Wallwork } 123182490253SJoe Wallwork LAPACKsyevFail(dim, Mpos); 123298921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in LAPACK routine %d", (int) lierr); 123382490253SJoe Wallwork } 123420282da2SJoe Wallwork ierr = PetscFPTrapPop();CHKERRQ(ierr); 123520282da2SJoe Wallwork } 123620282da2SJoe Wallwork ierr = PetscFree(work);CHKERRQ(ierr); 123720282da2SJoe Wallwork } 123820282da2SJoe Wallwork 123920282da2SJoe Wallwork /* Reflect to positive orthant and enforce maximum and minimum size */ 124020282da2SJoe Wallwork max_eig = 0.0; 124120282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 124220282da2SJoe Wallwork eigs[i] = PetscMin(l_max, PetscMax(l_min, PetscAbsReal(eigs[i]))); 124320282da2SJoe Wallwork max_eig = PetscMax(eigs[i], max_eig); 124420282da2SJoe Wallwork } 124520282da2SJoe Wallwork 12463f07679eSJoe Wallwork /* Enforce maximum anisotropy and compute determinant */ 12473f07679eSJoe Wallwork *detMp = 1.0; 124820282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 124920282da2SJoe Wallwork if (a_max > 1.0) eigs[i] = PetscMax(eigs[i], max_eig*la_min); 12503f07679eSJoe Wallwork *detMp *= eigs[i]; 125120282da2SJoe Wallwork } 125220282da2SJoe Wallwork 125320282da2SJoe Wallwork /* Reconstruct Hessian */ 125420282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 125520282da2SJoe Wallwork for (j = 0; j < dim; ++j) { 125620282da2SJoe Wallwork Mp[i*dim+j] = 0.0; 125720282da2SJoe Wallwork for (k = 0; k < dim; ++k) { 125820282da2SJoe Wallwork Mp[i*dim+j] += Mpos[k*dim+i] * eigs[k] * Mpos[k*dim+j]; 125920282da2SJoe Wallwork } 126020282da2SJoe Wallwork } 126120282da2SJoe Wallwork } 126220282da2SJoe Wallwork ierr = PetscFree2(Mpos, eigs);CHKERRQ(ierr); 126320282da2SJoe Wallwork 126420282da2SJoe Wallwork PetscFunctionReturn(0); 126520282da2SJoe Wallwork } 126620282da2SJoe Wallwork 1267cb7bfe8cSJoe Wallwork /*@ 126820282da2SJoe Wallwork DMPlexMetricEnforceSPD - Enforce symmetric positive-definiteness of a metric 126920282da2SJoe Wallwork 127020282da2SJoe Wallwork Input parameters: 127120282da2SJoe Wallwork + dm - The DM 12723f07679eSJoe Wallwork . metricIn - The metric 127399abec2bSJoe Wallwork . restrictSizes - Should maximum/minimum metric magnitudes be enforced? 12743f07679eSJoe Wallwork - restrictAnisotropy - Should maximum anisotropy be enforced? 127520282da2SJoe Wallwork 127620282da2SJoe Wallwork Output parameter: 12773f07679eSJoe Wallwork + metricOut - The metric 12783f07679eSJoe Wallwork - determinant - Its determinant 127920282da2SJoe Wallwork 128020282da2SJoe Wallwork Level: beginner 128120282da2SJoe Wallwork 1282cb7bfe8cSJoe Wallwork Notes: 1283cb7bfe8cSJoe Wallwork 1284cb7bfe8cSJoe Wallwork Relevant command line options: 1285cb7bfe8cSJoe Wallwork 128693520041SJoe Wallwork + -dm_plex_metric_isotropic - Is the metric isotropic? 128793520041SJoe Wallwork . -dm_plex_metric_uniform - Is the metric uniform? 128893520041SJoe Wallwork . -dm_plex_metric_h_min - Minimum tolerated metric magnitude 1289cb7bfe8cSJoe Wallwork . -dm_plex_metric_h_max - Maximum tolerated metric magnitude 1290cb7bfe8cSJoe Wallwork - -dm_plex_metric_a_max - Maximum tolerated anisotropy 1291cb7bfe8cSJoe Wallwork 129220282da2SJoe Wallwork .seealso: DMPlexMetricNormalize(), DMPlexMetricIntersection() 1293cb7bfe8cSJoe Wallwork @*/ 12943f07679eSJoe Wallwork PetscErrorCode DMPlexMetricEnforceSPD(DM dm, Vec metricIn, PetscBool restrictSizes, PetscBool restrictAnisotropy, Vec *metricOut, Vec *determinant) 129520282da2SJoe Wallwork { 12963f07679eSJoe Wallwork DM dmDet; 129793520041SJoe Wallwork PetscBool isotropic, uniform; 129820282da2SJoe Wallwork PetscErrorCode ierr; 129920282da2SJoe Wallwork PetscInt dim, vStart, vEnd, v; 13003f07679eSJoe Wallwork PetscScalar *met, *det; 130120282da2SJoe Wallwork PetscReal h_min = 1.0e-30, h_max = 1.0e+30, a_max = 0.0; 130220282da2SJoe Wallwork 130320282da2SJoe Wallwork PetscFunctionBegin; 1304fe902aceSJoe Wallwork ierr = PetscLogEventBegin(DMPLEX_MetricEnforceSPD,0,0,0,0);CHKERRQ(ierr); 130520282da2SJoe Wallwork 130620282da2SJoe Wallwork /* Extract metadata from dm */ 130720282da2SJoe Wallwork ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 130820282da2SJoe Wallwork if (restrictSizes) { 130999abec2bSJoe Wallwork ierr = DMPlexMetricGetMinimumMagnitude(dm, &h_min);CHKERRQ(ierr); 131099abec2bSJoe Wallwork ierr = DMPlexMetricGetMaximumMagnitude(dm, &h_max);CHKERRQ(ierr); 131199abec2bSJoe Wallwork h_min = PetscMax(h_min, 1.0e-30); 131299abec2bSJoe Wallwork h_max = PetscMin(h_max, 1.0e+30); 131354c59aa7SJacob Faibussowitsch PetscCheck(h_min < h_max,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Incompatible min/max metric magnitudes (%.4e not smaller than %.4e)", h_min, h_max); 131499abec2bSJoe Wallwork } 131599abec2bSJoe Wallwork if (restrictAnisotropy) { 131699abec2bSJoe Wallwork ierr = DMPlexMetricGetMaximumAnisotropy(dm, &a_max);CHKERRQ(ierr); 131799abec2bSJoe Wallwork a_max = PetscMin(a_max, 1.0e+30); 131820282da2SJoe Wallwork } 131920282da2SJoe Wallwork 132093520041SJoe Wallwork /* Setup output metric */ 13213f07679eSJoe Wallwork ierr = DMPlexMetricCreate(dm, 0, metricOut);CHKERRQ(ierr); 13223f07679eSJoe Wallwork ierr = VecCopy(metricIn, *metricOut);CHKERRQ(ierr); 132393520041SJoe Wallwork 132493520041SJoe Wallwork /* Enforce SPD and extract determinant */ 132593520041SJoe Wallwork ierr = VecGetArray(*metricOut, &met);CHKERRQ(ierr); 132693520041SJoe Wallwork ierr = DMPlexMetricIsUniform(dm, &uniform);CHKERRQ(ierr); 132793520041SJoe Wallwork ierr = DMPlexMetricIsIsotropic(dm, &isotropic);CHKERRQ(ierr); 132893520041SJoe Wallwork if (uniform) { 1329d1a5b989SMatthew G. Knepley PetscCheck(isotropic, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Uniform anisotropic metrics cannot exist"); 133093520041SJoe Wallwork 133193520041SJoe Wallwork /* Uniform case */ 133293520041SJoe Wallwork ierr = VecDuplicate(metricIn, determinant);CHKERRQ(ierr); 133393520041SJoe Wallwork ierr = VecGetArray(*determinant, &det);CHKERRQ(ierr); 133493520041SJoe Wallwork ierr = DMPlexMetricModify_Private(1, h_min, h_max, a_max, met, det);CHKERRQ(ierr); 133593520041SJoe Wallwork ierr = VecRestoreArray(*determinant, &det);CHKERRQ(ierr); 133693520041SJoe Wallwork } else { 133793520041SJoe Wallwork 133893520041SJoe Wallwork /* Spatially varying case */ 133993520041SJoe Wallwork PetscInt nrow; 134093520041SJoe Wallwork 134193520041SJoe Wallwork if (isotropic) nrow = 1; 134293520041SJoe Wallwork else nrow = dim; 13433f07679eSJoe Wallwork ierr = DMClone(dm, &dmDet);CHKERRQ(ierr); 13443f07679eSJoe Wallwork ierr = DMPlexP1FieldCreate_Private(dmDet, 0, 1, determinant);CHKERRQ(ierr); 134520282da2SJoe Wallwork ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 13463f07679eSJoe Wallwork ierr = VecGetArray(*determinant, &det);CHKERRQ(ierr); 134720282da2SJoe Wallwork for (v = vStart; v < vEnd; ++v) { 13483f07679eSJoe Wallwork PetscScalar *vmet, *vdet; 134920282da2SJoe Wallwork ierr = DMPlexPointLocalRef(dm, v, met, &vmet);CHKERRQ(ierr); 13503f07679eSJoe Wallwork ierr = DMPlexPointLocalRef(dmDet, v, det, &vdet);CHKERRQ(ierr); 135193520041SJoe Wallwork ierr = DMPlexMetricModify_Private(nrow, h_min, h_max, a_max, vmet, vdet);CHKERRQ(ierr); 135220282da2SJoe Wallwork } 13533f07679eSJoe Wallwork ierr = VecRestoreArray(*determinant, &det);CHKERRQ(ierr); 135493520041SJoe Wallwork } 13553f07679eSJoe Wallwork ierr = VecRestoreArray(*metricOut, &met);CHKERRQ(ierr); 1356fe902aceSJoe Wallwork 1357fe902aceSJoe Wallwork ierr = PetscLogEventEnd(DMPLEX_MetricEnforceSPD,0,0,0,0);CHKERRQ(ierr); 135820282da2SJoe Wallwork PetscFunctionReturn(0); 135920282da2SJoe Wallwork } 136020282da2SJoe Wallwork 136120282da2SJoe Wallwork static void detMFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux, 136220282da2SJoe Wallwork const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 136320282da2SJoe Wallwork const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 136420282da2SJoe Wallwork PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 136520282da2SJoe Wallwork { 136620282da2SJoe Wallwork const PetscScalar p = constants[0]; 136720282da2SJoe Wallwork 13683f07679eSJoe Wallwork f0[0] = PetscPowReal(u[0], p/(2.0*p + dim)); 136920282da2SJoe Wallwork } 137020282da2SJoe Wallwork 1371cb7bfe8cSJoe Wallwork /*@ 137220282da2SJoe Wallwork DMPlexMetricNormalize - Apply L-p normalization to a metric 137320282da2SJoe Wallwork 137420282da2SJoe Wallwork Input parameters: 137520282da2SJoe Wallwork + dm - The DM 137620282da2SJoe Wallwork . metricIn - The unnormalized metric 137716522936SJoe Wallwork . restrictSizes - Should maximum/minimum metric magnitudes be enforced? 137816522936SJoe Wallwork - restrictAnisotropy - Should maximum metric anisotropy be enforced? 137920282da2SJoe Wallwork 138020282da2SJoe Wallwork Output parameter: 138120282da2SJoe Wallwork . metricOut - The normalized metric 138220282da2SJoe Wallwork 138320282da2SJoe Wallwork Level: beginner 138420282da2SJoe Wallwork 1385cb7bfe8cSJoe Wallwork Notes: 1386cb7bfe8cSJoe Wallwork 1387cb7bfe8cSJoe Wallwork Relevant command line options: 1388cb7bfe8cSJoe Wallwork 138993520041SJoe Wallwork + -dm_plex_metric_isotropic - Is the metric isotropic? 139093520041SJoe Wallwork . -dm_plex_metric_uniform - Is the metric uniform? 139193520041SJoe Wallwork . -dm_plex_metric_restrict_anisotropy_first - Should anisotropy be restricted before normalization? 1392cb7bfe8cSJoe Wallwork . -dm_plex_metric_h_min - Minimum tolerated metric magnitude 1393cb7bfe8cSJoe Wallwork . -dm_plex_metric_h_max - Maximum tolerated metric magnitude 1394cb7bfe8cSJoe Wallwork . -dm_plex_metric_a_max - Maximum tolerated anisotropy 1395cb7bfe8cSJoe Wallwork . -dm_plex_metric_p - L-p normalization order 1396cb7bfe8cSJoe Wallwork - -dm_plex_metric_target_complexity - Target metric complexity 1397cb7bfe8cSJoe Wallwork 139820282da2SJoe Wallwork .seealso: DMPlexMetricEnforceSPD(), DMPlexMetricIntersection() 1399cb7bfe8cSJoe Wallwork @*/ 140016522936SJoe Wallwork PetscErrorCode DMPlexMetricNormalize(DM dm, Vec metricIn, PetscBool restrictSizes, PetscBool restrictAnisotropy, Vec *metricOut) 140120282da2SJoe Wallwork { 14023f07679eSJoe Wallwork DM dmDet; 140320282da2SJoe Wallwork MPI_Comm comm; 140493520041SJoe Wallwork PetscBool restrictAnisotropyFirst, isotropic, uniform; 140520282da2SJoe Wallwork PetscDS ds; 140620282da2SJoe Wallwork PetscErrorCode ierr; 140720282da2SJoe Wallwork PetscInt dim, Nd, vStart, vEnd, v, i; 14083f07679eSJoe Wallwork PetscScalar *met, *det, integral, constants[1]; 140993520041SJoe Wallwork PetscReal p, h_min = 1.0e-30, h_max = 1.0e+30, a_max = 0.0, factGlob, fact, target, realIntegral; 14103f07679eSJoe Wallwork Vec determinant; 141120282da2SJoe Wallwork 141220282da2SJoe Wallwork PetscFunctionBegin; 1413fe902aceSJoe Wallwork ierr = PetscLogEventBegin(DMPLEX_MetricNormalize,0,0,0,0);CHKERRQ(ierr); 141420282da2SJoe Wallwork 141520282da2SJoe Wallwork /* Extract metadata from dm */ 141620282da2SJoe Wallwork ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 141720282da2SJoe Wallwork ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 141893520041SJoe Wallwork ierr = DMPlexMetricIsUniform(dm, &uniform);CHKERRQ(ierr); 141993520041SJoe Wallwork ierr = DMPlexMetricIsIsotropic(dm, &isotropic);CHKERRQ(ierr); 142093520041SJoe Wallwork if (isotropic) Nd = 1; 142193520041SJoe Wallwork else Nd = dim*dim; 142220282da2SJoe Wallwork 142320282da2SJoe Wallwork /* Set up metric and ensure it is SPD */ 142416522936SJoe Wallwork ierr = DMPlexMetricRestrictAnisotropyFirst(dm, &restrictAnisotropyFirst);CHKERRQ(ierr); 14253f07679eSJoe Wallwork ierr = DMPlexMetricEnforceSPD(dm, metricIn, PETSC_FALSE, (PetscBool)(restrictAnisotropy && restrictAnisotropyFirst), metricOut, &determinant);CHKERRQ(ierr); 142620282da2SJoe Wallwork 142720282da2SJoe Wallwork /* Compute global normalization factor */ 142816522936SJoe Wallwork ierr = DMPlexMetricGetTargetComplexity(dm, &target);CHKERRQ(ierr); 142916522936SJoe Wallwork ierr = DMPlexMetricGetNormalizationOrder(dm, &p);CHKERRQ(ierr); 143016522936SJoe Wallwork constants[0] = p; 143193520041SJoe Wallwork if (uniform) { 14322c71b3e2SJacob Faibussowitsch PetscCheckFalse(!isotropic,comm, PETSC_ERR_ARG_WRONG, "Uniform anisotropic metrics not supported"); 143393520041SJoe Wallwork DM dmTmp; 143493520041SJoe Wallwork Vec tmp; 143593520041SJoe Wallwork 143693520041SJoe Wallwork ierr = DMClone(dm, &dmTmp);CHKERRQ(ierr); 143793520041SJoe Wallwork ierr = DMPlexP1FieldCreate_Private(dmTmp, 0, 1, &tmp);CHKERRQ(ierr); 143893520041SJoe Wallwork ierr = VecGetArray(determinant, &det);CHKERRQ(ierr); 143993520041SJoe Wallwork ierr = VecSet(tmp, det[0]);CHKERRQ(ierr); 144093520041SJoe Wallwork ierr = VecRestoreArray(determinant, &det);CHKERRQ(ierr); 144193520041SJoe Wallwork ierr = DMGetDS(dmTmp, &ds);CHKERRQ(ierr); 144293520041SJoe Wallwork ierr = PetscDSSetConstants(ds, 1, constants);CHKERRQ(ierr); 144393520041SJoe Wallwork ierr = PetscDSSetObjective(ds, 0, detMFunc);CHKERRQ(ierr); 144493520041SJoe Wallwork ierr = DMPlexComputeIntegralFEM(dmTmp, tmp, &integral, NULL);CHKERRQ(ierr); 144593520041SJoe Wallwork ierr = VecDestroy(&tmp);CHKERRQ(ierr); 144693520041SJoe Wallwork ierr = DMDestroy(&dmTmp);CHKERRQ(ierr); 144793520041SJoe Wallwork } else { 14483f07679eSJoe Wallwork ierr = VecGetDM(determinant, &dmDet);CHKERRQ(ierr); 14493f07679eSJoe Wallwork ierr = DMGetDS(dmDet, &ds);CHKERRQ(ierr); 145020282da2SJoe Wallwork ierr = PetscDSSetConstants(ds, 1, constants);CHKERRQ(ierr); 145120282da2SJoe Wallwork ierr = PetscDSSetObjective(ds, 0, detMFunc);CHKERRQ(ierr); 14523f07679eSJoe Wallwork ierr = DMPlexComputeIntegralFEM(dmDet, determinant, &integral, NULL);CHKERRQ(ierr); 145393520041SJoe Wallwork } 14543f07679eSJoe Wallwork realIntegral = PetscRealPart(integral); 14552c71b3e2SJacob Faibussowitsch PetscCheckFalse(realIntegral < 1.0e-30,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Global metric normalization factor should be strictly positive, not %.4e Is the input metric positive-definite?", realIntegral); 14563f07679eSJoe Wallwork factGlob = PetscPowReal(target/realIntegral, 2.0/dim); 145720282da2SJoe Wallwork 145820282da2SJoe Wallwork /* Apply local scaling */ 145920282da2SJoe Wallwork if (restrictSizes) { 146016522936SJoe Wallwork ierr = DMPlexMetricGetMinimumMagnitude(dm, &h_min);CHKERRQ(ierr); 146116522936SJoe Wallwork ierr = DMPlexMetricGetMaximumMagnitude(dm, &h_max);CHKERRQ(ierr); 146216522936SJoe Wallwork h_min = PetscMax(h_min, 1.0e-30); 146316522936SJoe Wallwork h_max = PetscMin(h_max, 1.0e+30); 14642c71b3e2SJacob Faibussowitsch PetscCheckFalse(h_min >= h_max,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Incompatible min/max metric magnitudes (%.4e not smaller than %.4e)", h_min, h_max); 146516522936SJoe Wallwork } 146616522936SJoe Wallwork if (restrictAnisotropy && !restrictAnisotropyFirst) { 146716522936SJoe Wallwork ierr = DMPlexMetricGetMaximumAnisotropy(dm, &a_max);CHKERRQ(ierr); 146816522936SJoe Wallwork a_max = PetscMin(a_max, 1.0e+30); 146920282da2SJoe Wallwork } 147020282da2SJoe Wallwork ierr = VecGetArray(*metricOut, &met);CHKERRQ(ierr); 14713f07679eSJoe Wallwork ierr = VecGetArray(determinant, &det);CHKERRQ(ierr); 147293520041SJoe Wallwork if (uniform) { 147393520041SJoe Wallwork 147493520041SJoe Wallwork /* Uniform case */ 147593520041SJoe Wallwork met[0] *= factGlob * PetscPowReal(PetscAbsScalar(det[0]), -1.0/(2*p+dim)); 147693520041SJoe Wallwork if (restrictSizes) { ierr = DMPlexMetricModify_Private(1, h_min, h_max, a_max, met, det);CHKERRQ(ierr); } 147793520041SJoe Wallwork } else { 147893520041SJoe Wallwork 147993520041SJoe Wallwork /* Spatially varying case */ 148093520041SJoe Wallwork PetscInt nrow; 148193520041SJoe Wallwork 148293520041SJoe Wallwork if (isotropic) nrow = 1; 148393520041SJoe Wallwork else nrow = dim; 148416522936SJoe Wallwork ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 148520282da2SJoe Wallwork for (v = vStart; v < vEnd; ++v) { 14863f07679eSJoe Wallwork PetscScalar *Mp, *detM; 148720282da2SJoe Wallwork 148820282da2SJoe Wallwork ierr = DMPlexPointLocalRef(dm, v, met, &Mp);CHKERRQ(ierr); 14893f07679eSJoe Wallwork ierr = DMPlexPointLocalRef(dmDet, v, det, &detM);CHKERRQ(ierr); 14903f07679eSJoe Wallwork fact = factGlob * PetscPowReal(PetscAbsScalar(detM[0]), -1.0/(2*p+dim)); 149120282da2SJoe Wallwork for (i = 0; i < Nd; ++i) Mp[i] *= fact; 149293520041SJoe Wallwork if (restrictSizes) { ierr = DMPlexMetricModify_Private(nrow, h_min, h_max, a_max, Mp, detM);CHKERRQ(ierr); } 149393520041SJoe Wallwork } 149420282da2SJoe Wallwork } 14953f07679eSJoe Wallwork ierr = VecRestoreArray(determinant, &det);CHKERRQ(ierr); 149620282da2SJoe Wallwork ierr = VecRestoreArray(*metricOut, &met);CHKERRQ(ierr); 14973f07679eSJoe Wallwork ierr = VecDestroy(&determinant);CHKERRQ(ierr); 149893520041SJoe Wallwork if (!uniform) { ierr = DMDestroy(&dmDet);CHKERRQ(ierr); } 149920282da2SJoe Wallwork 1500fe902aceSJoe Wallwork ierr = PetscLogEventEnd(DMPLEX_MetricNormalize,0,0,0,0);CHKERRQ(ierr); 150120282da2SJoe Wallwork PetscFunctionReturn(0); 150220282da2SJoe Wallwork } 150320282da2SJoe Wallwork 1504cb7bfe8cSJoe Wallwork /*@ 150520282da2SJoe Wallwork DMPlexMetricAverage - Compute the average of a list of metrics 150620282da2SJoe Wallwork 1507f1a722f8SMatthew G. Knepley Input Parameters: 150820282da2SJoe Wallwork + dm - The DM 150920282da2SJoe Wallwork . numMetrics - The number of metrics to be averaged 151020282da2SJoe Wallwork . weights - Weights for the average 151120282da2SJoe Wallwork - metrics - The metrics to be averaged 151220282da2SJoe Wallwork 151320282da2SJoe Wallwork Output Parameter: 151420282da2SJoe Wallwork . metricAvg - The averaged metric 151520282da2SJoe Wallwork 151620282da2SJoe Wallwork Level: beginner 151720282da2SJoe Wallwork 151820282da2SJoe Wallwork Notes: 151920282da2SJoe Wallwork The weights should sum to unity. 152020282da2SJoe Wallwork 152120282da2SJoe Wallwork If weights are not provided then an unweighted average is used. 152220282da2SJoe Wallwork 152320282da2SJoe Wallwork .seealso: DMPlexMetricAverage2(), DMPlexMetricAverage3(), DMPlexMetricIntersection() 1524cb7bfe8cSJoe Wallwork @*/ 152520282da2SJoe Wallwork PetscErrorCode DMPlexMetricAverage(DM dm, PetscInt numMetrics, PetscReal weights[], Vec metrics[], Vec *metricAvg) 152620282da2SJoe Wallwork { 152720282da2SJoe Wallwork PetscBool haveWeights = PETSC_TRUE; 152820282da2SJoe Wallwork PetscErrorCode ierr; 152993520041SJoe Wallwork PetscInt i, m, n; 153020282da2SJoe Wallwork PetscReal sum = 0.0, tol = 1.0e-10; 153120282da2SJoe Wallwork 153220282da2SJoe Wallwork PetscFunctionBegin; 1533fe902aceSJoe Wallwork ierr = PetscLogEventBegin(DMPLEX_MetricAverage,0,0,0,0);CHKERRQ(ierr); 15342c71b3e2SJacob Faibussowitsch PetscCheck(numMetrics >= 1,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot average %d < 1 metrics", numMetrics); 153520282da2SJoe Wallwork ierr = DMPlexMetricCreate(dm, 0, metricAvg);CHKERRQ(ierr); 153620282da2SJoe Wallwork ierr = VecSet(*metricAvg, 0.0);CHKERRQ(ierr); 153793520041SJoe Wallwork ierr = VecGetSize(*metricAvg, &m);CHKERRQ(ierr); 153893520041SJoe Wallwork for (i = 0; i < numMetrics; ++i) { 153993520041SJoe Wallwork ierr = VecGetSize(metrics[i], &n);CHKERRQ(ierr); 15402c71b3e2SJacob Faibussowitsch PetscCheckFalse(m != n,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Averaging different metric types not implemented"); 154193520041SJoe Wallwork } 154220282da2SJoe Wallwork 154320282da2SJoe Wallwork /* Default to the unweighted case */ 154420282da2SJoe Wallwork if (!weights) { 154520282da2SJoe Wallwork ierr = PetscMalloc1(numMetrics, &weights);CHKERRQ(ierr); 154620282da2SJoe Wallwork haveWeights = PETSC_FALSE; 154720282da2SJoe Wallwork for (i = 0; i < numMetrics; ++i) {weights[i] = 1.0/numMetrics; } 154820282da2SJoe Wallwork } 154920282da2SJoe Wallwork 155020282da2SJoe Wallwork /* Check weights sum to unity */ 155193520041SJoe Wallwork for (i = 0; i < numMetrics; ++i) sum += weights[i]; 15522c71b3e2SJacob Faibussowitsch PetscCheckFalse(PetscAbsReal(sum - 1) > tol,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Weights do not sum to unity"); 155320282da2SJoe Wallwork 155420282da2SJoe Wallwork /* Compute metric average */ 155520282da2SJoe Wallwork for (i = 0; i < numMetrics; ++i) { ierr = VecAXPY(*metricAvg, weights[i], metrics[i]);CHKERRQ(ierr); } 155620282da2SJoe Wallwork if (!haveWeights) { ierr = PetscFree(weights); } 1557fe902aceSJoe Wallwork 1558fe902aceSJoe Wallwork ierr = PetscLogEventEnd(DMPLEX_MetricAverage,0,0,0,0);CHKERRQ(ierr); 155920282da2SJoe Wallwork PetscFunctionReturn(0); 156020282da2SJoe Wallwork } 156120282da2SJoe Wallwork 1562cb7bfe8cSJoe Wallwork /*@ 156320282da2SJoe Wallwork DMPlexMetricAverage2 - Compute the unweighted average of two metrics 156420282da2SJoe Wallwork 1565f1a722f8SMatthew G. Knepley Input Parameters: 156620282da2SJoe Wallwork + dm - The DM 156720282da2SJoe Wallwork . metric1 - The first metric to be averaged 156820282da2SJoe Wallwork - metric2 - The second metric to be averaged 156920282da2SJoe Wallwork 157020282da2SJoe Wallwork Output Parameter: 157120282da2SJoe Wallwork . metricAvg - The averaged metric 157220282da2SJoe Wallwork 157320282da2SJoe Wallwork Level: beginner 157420282da2SJoe Wallwork 157520282da2SJoe Wallwork .seealso: DMPlexMetricAverage(), DMPlexMetricAverage3() 1576cb7bfe8cSJoe Wallwork @*/ 157720282da2SJoe Wallwork PetscErrorCode DMPlexMetricAverage2(DM dm, Vec metric1, Vec metric2, Vec *metricAvg) 157820282da2SJoe Wallwork { 157920282da2SJoe Wallwork PetscErrorCode ierr; 158020282da2SJoe Wallwork PetscReal weights[2] = {0.5, 0.5}; 158120282da2SJoe Wallwork Vec metrics[2] = {metric1, metric2}; 158220282da2SJoe Wallwork 158320282da2SJoe Wallwork PetscFunctionBegin; 158420282da2SJoe Wallwork ierr = DMPlexMetricAverage(dm, 2, weights, metrics, metricAvg);CHKERRQ(ierr); 158520282da2SJoe Wallwork PetscFunctionReturn(0); 158620282da2SJoe Wallwork } 158720282da2SJoe Wallwork 1588cb7bfe8cSJoe Wallwork /*@ 158920282da2SJoe Wallwork DMPlexMetricAverage3 - Compute the unweighted average of three metrics 159020282da2SJoe Wallwork 1591f1a722f8SMatthew G. Knepley Input Parameters: 159220282da2SJoe Wallwork + dm - The DM 159320282da2SJoe Wallwork . metric1 - The first metric to be averaged 159420282da2SJoe Wallwork . metric2 - The second metric to be averaged 159520282da2SJoe Wallwork - metric3 - The third metric to be averaged 159620282da2SJoe Wallwork 159720282da2SJoe Wallwork Output Parameter: 159820282da2SJoe Wallwork . metricAvg - The averaged metric 159920282da2SJoe Wallwork 160020282da2SJoe Wallwork Level: beginner 160120282da2SJoe Wallwork 160220282da2SJoe Wallwork .seealso: DMPlexMetricAverage(), DMPlexMetricAverage2() 1603cb7bfe8cSJoe Wallwork @*/ 160420282da2SJoe Wallwork PetscErrorCode DMPlexMetricAverage3(DM dm, Vec metric1, Vec metric2, Vec metric3, Vec *metricAvg) 160520282da2SJoe Wallwork { 160620282da2SJoe Wallwork PetscErrorCode ierr; 160720282da2SJoe Wallwork PetscReal weights[3] = {1.0/3.0, 1.0/3.0, 1.0/3.0}; 160820282da2SJoe Wallwork Vec metrics[3] = {metric1, metric2, metric3}; 160920282da2SJoe Wallwork 161020282da2SJoe Wallwork PetscFunctionBegin; 161120282da2SJoe Wallwork ierr = DMPlexMetricAverage(dm, 3, weights, metrics, metricAvg);CHKERRQ(ierr); 161220282da2SJoe Wallwork PetscFunctionReturn(0); 161320282da2SJoe Wallwork } 161420282da2SJoe Wallwork 161520282da2SJoe Wallwork static PetscErrorCode DMPlexMetricIntersection_Private(PetscInt dim, PetscScalar M1[], PetscScalar M2[]) 161620282da2SJoe Wallwork { 161720282da2SJoe Wallwork PetscErrorCode ierr; 161820282da2SJoe Wallwork PetscInt i, j, k, l, m; 161920282da2SJoe Wallwork PetscReal *evals, *evals1; 162020282da2SJoe Wallwork PetscScalar *evecs, *sqrtM1, *isqrtM1; 162120282da2SJoe Wallwork 162220282da2SJoe Wallwork PetscFunctionBegin; 162393520041SJoe Wallwork 162493520041SJoe Wallwork /* Isotropic case */ 162593520041SJoe Wallwork if (dim == 1) { 162693520041SJoe Wallwork M2[0] = (PetscScalar)PetscMin(PetscRealPart(M1[0]), PetscRealPart(M2[0])); 162793520041SJoe Wallwork PetscFunctionReturn(0); 162893520041SJoe Wallwork } 162993520041SJoe Wallwork 163093520041SJoe Wallwork /* Anisotropic case */ 163120282da2SJoe Wallwork ierr = PetscMalloc5(dim*dim, &evecs, dim*dim, &sqrtM1, dim*dim, &isqrtM1, dim, &evals, dim, &evals1);CHKERRQ(ierr); 163220282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 163320282da2SJoe Wallwork for (j = 0; j < dim; ++j) { 163420282da2SJoe Wallwork evecs[i*dim+j] = M1[i*dim+j]; 163520282da2SJoe Wallwork } 163620282da2SJoe Wallwork } 163720282da2SJoe Wallwork { 163820282da2SJoe Wallwork PetscScalar *work; 163920282da2SJoe Wallwork PetscBLASInt lwork; 164020282da2SJoe Wallwork 164120282da2SJoe Wallwork lwork = 5*dim; 164220282da2SJoe Wallwork ierr = PetscMalloc1(5*dim, &work);CHKERRQ(ierr); 164320282da2SJoe Wallwork { 164420282da2SJoe Wallwork PetscBLASInt lierr, nb; 164520282da2SJoe Wallwork PetscReal sqrtk; 164620282da2SJoe Wallwork 164720282da2SJoe Wallwork /* Compute eigendecomposition of M1 */ 164820282da2SJoe Wallwork ierr = PetscBLASIntCast(dim, &nb);CHKERRQ(ierr); 164920282da2SJoe Wallwork ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 165020282da2SJoe Wallwork #if defined(PETSC_USE_COMPLEX) 165120282da2SJoe Wallwork { 165220282da2SJoe Wallwork PetscReal *rwork; 165320282da2SJoe Wallwork ierr = PetscMalloc1(3*dim, &rwork);CHKERRQ(ierr); 165420282da2SJoe Wallwork PetscStackCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &nb, evecs, &nb, evals1, work, &lwork, rwork, &lierr)); 165520282da2SJoe Wallwork ierr = PetscFree(rwork);CHKERRQ(ierr); 165620282da2SJoe Wallwork } 165720282da2SJoe Wallwork #else 165820282da2SJoe Wallwork PetscStackCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &nb, evecs, &nb, evals1, work, &lwork, &lierr)); 165920282da2SJoe Wallwork #endif 166082490253SJoe Wallwork if (lierr) { 166182490253SJoe Wallwork LAPACKsyevFail(dim, M1); 166298921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in LAPACK routine %d", (int) lierr); 166382490253SJoe Wallwork } 166420282da2SJoe Wallwork ierr = PetscFPTrapPop(); 166520282da2SJoe Wallwork 166620282da2SJoe Wallwork /* Compute square root and reciprocal */ 166720282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 166820282da2SJoe Wallwork for (j = 0; j < dim; ++j) { 166920282da2SJoe Wallwork sqrtM1[i*dim+j] = 0.0; 167020282da2SJoe Wallwork isqrtM1[i*dim+j] = 0.0; 167120282da2SJoe Wallwork for (k = 0; k < dim; ++k) { 167220282da2SJoe Wallwork sqrtk = PetscSqrtReal(evals1[k]); 167320282da2SJoe Wallwork sqrtM1[i*dim+j] += evecs[k*dim+i] * sqrtk * evecs[k*dim+j]; 167420282da2SJoe Wallwork isqrtM1[i*dim+j] += evecs[k*dim+i] * (1.0/sqrtk) * evecs[k*dim+j]; 167520282da2SJoe Wallwork } 167620282da2SJoe Wallwork } 167720282da2SJoe Wallwork } 167820282da2SJoe Wallwork 167920282da2SJoe Wallwork /* Map into the space spanned by the eigenvectors of M1 */ 168020282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 168120282da2SJoe Wallwork for (j = 0; j < dim; ++j) { 168220282da2SJoe Wallwork evecs[i*dim+j] = 0.0; 168320282da2SJoe Wallwork for (k = 0; k < dim; ++k) { 168420282da2SJoe Wallwork for (l = 0; l < dim; ++l) { 168520282da2SJoe Wallwork evecs[i*dim+j] += isqrtM1[i*dim+k] * M2[l*dim+k] * isqrtM1[j*dim+l]; 168620282da2SJoe Wallwork } 168720282da2SJoe Wallwork } 168820282da2SJoe Wallwork } 168920282da2SJoe Wallwork } 169020282da2SJoe Wallwork 169120282da2SJoe Wallwork /* Compute eigendecomposition */ 169220282da2SJoe Wallwork ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 169320282da2SJoe Wallwork #if defined(PETSC_USE_COMPLEX) 169420282da2SJoe Wallwork { 169520282da2SJoe Wallwork PetscReal *rwork; 169620282da2SJoe Wallwork ierr = PetscMalloc1(3*dim, &rwork);CHKERRQ(ierr); 169720282da2SJoe Wallwork PetscStackCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &nb, evecs, &nb, evals, work, &lwork, rwork, &lierr)); 169820282da2SJoe Wallwork ierr = PetscFree(rwork);CHKERRQ(ierr); 169920282da2SJoe Wallwork } 170020282da2SJoe Wallwork #else 170120282da2SJoe Wallwork PetscStackCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &nb, evecs, &nb, evals, work, &lwork, &lierr)); 170220282da2SJoe Wallwork #endif 170382490253SJoe Wallwork if (lierr) { 170482490253SJoe Wallwork for (i = 0; i < dim; ++i) { 170582490253SJoe Wallwork for (j = 0; j < dim; ++j) { 170682490253SJoe Wallwork evecs[i*dim+j] = 0.0; 170782490253SJoe Wallwork for (k = 0; k < dim; ++k) { 170882490253SJoe Wallwork for (l = 0; l < dim; ++l) { 170982490253SJoe Wallwork evecs[i*dim+j] += isqrtM1[i*dim+k] * M2[l*dim+k] * isqrtM1[j*dim+l]; 171082490253SJoe Wallwork } 171182490253SJoe Wallwork } 171282490253SJoe Wallwork } 171382490253SJoe Wallwork } 171482490253SJoe Wallwork LAPACKsyevFail(dim, evecs); 171598921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in LAPACK routine %d", (int) lierr); 171682490253SJoe Wallwork } 171720282da2SJoe Wallwork ierr = PetscFPTrapPop(); 171820282da2SJoe Wallwork 171920282da2SJoe Wallwork /* Modify eigenvalues */ 172020282da2SJoe Wallwork for (i = 0; i < dim; ++i) evals[i] = PetscMin(evals[i], evals1[i]); 172120282da2SJoe Wallwork 172220282da2SJoe Wallwork /* Map back to get the intersection */ 172320282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 172420282da2SJoe Wallwork for (j = 0; j < dim; ++j) { 172520282da2SJoe Wallwork M2[i*dim+j] = 0.0; 172620282da2SJoe Wallwork for (k = 0; k < dim; ++k) { 172720282da2SJoe Wallwork for (l = 0; l < dim; ++l) { 172820282da2SJoe Wallwork for (m = 0; m < dim; ++m) { 172920282da2SJoe Wallwork M2[i*dim+j] += sqrtM1[i*dim+k] * evecs[l*dim+k] * evals[l] * evecs[l*dim+m] * sqrtM1[j*dim+m]; 173020282da2SJoe Wallwork } 173120282da2SJoe Wallwork } 173220282da2SJoe Wallwork } 173320282da2SJoe Wallwork } 173420282da2SJoe Wallwork } 173520282da2SJoe Wallwork } 173620282da2SJoe Wallwork ierr = PetscFree(work);CHKERRQ(ierr); 173720282da2SJoe Wallwork } 173820282da2SJoe Wallwork ierr = PetscFree5(evecs, sqrtM1, isqrtM1, evals, evals1);CHKERRQ(ierr); 173920282da2SJoe Wallwork PetscFunctionReturn(0); 174020282da2SJoe Wallwork } 174120282da2SJoe Wallwork 1742cb7bfe8cSJoe Wallwork /*@ 174320282da2SJoe Wallwork DMPlexMetricIntersection - Compute the intersection of a list of metrics 174420282da2SJoe Wallwork 1745f1a722f8SMatthew G. Knepley Input Parameters: 174620282da2SJoe Wallwork + dm - The DM 174720282da2SJoe Wallwork . numMetrics - The number of metrics to be intersected 174820282da2SJoe Wallwork - metrics - The metrics to be intersected 174920282da2SJoe Wallwork 175020282da2SJoe Wallwork Output Parameter: 175120282da2SJoe Wallwork . metricInt - The intersected metric 175220282da2SJoe Wallwork 175320282da2SJoe Wallwork Level: beginner 175420282da2SJoe Wallwork 175520282da2SJoe Wallwork Notes: 175620282da2SJoe Wallwork 175720282da2SJoe Wallwork The intersection of a list of metrics has the maximal ellipsoid which fits within the ellipsoids of the component metrics. 175820282da2SJoe Wallwork 175920282da2SJoe Wallwork The implementation used here is only consistent with the maximal ellipsoid definition in the case numMetrics = 2. 176020282da2SJoe Wallwork 176120282da2SJoe Wallwork .seealso: DMPlexMetricIntersection2(), DMPlexMetricIntersection3(), DMPlexMetricAverage() 1762cb7bfe8cSJoe Wallwork @*/ 176320282da2SJoe Wallwork PetscErrorCode DMPlexMetricIntersection(DM dm, PetscInt numMetrics, Vec metrics[], Vec *metricInt) 176420282da2SJoe Wallwork { 176593520041SJoe Wallwork PetscBool isotropic, uniform; 176620282da2SJoe Wallwork PetscErrorCode ierr; 176793520041SJoe Wallwork PetscInt v, i, m, n; 176893520041SJoe Wallwork PetscScalar *met, *meti; 176920282da2SJoe Wallwork 177020282da2SJoe Wallwork PetscFunctionBegin; 1771fe902aceSJoe Wallwork ierr = PetscLogEventBegin(DMPLEX_MetricIntersection,0,0,0,0);CHKERRQ(ierr); 17722c71b3e2SJacob Faibussowitsch PetscCheck(numMetrics >= 1,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot intersect %d < 1 metrics", numMetrics); 177320282da2SJoe Wallwork 177420282da2SJoe Wallwork /* Copy over the first metric */ 177593520041SJoe Wallwork ierr = DMPlexMetricCreate(dm, 0, metricInt);CHKERRQ(ierr); 177620282da2SJoe Wallwork ierr = VecCopy(metrics[0], *metricInt);CHKERRQ(ierr); 177793520041SJoe Wallwork if (numMetrics == 1) PetscFunctionReturn(0); 177893520041SJoe Wallwork ierr = VecGetSize(*metricInt, &m);CHKERRQ(ierr); 177993520041SJoe Wallwork for (i = 0; i < numMetrics; ++i) { 178093520041SJoe Wallwork ierr = VecGetSize(metrics[i], &n);CHKERRQ(ierr); 17812c71b3e2SJacob Faibussowitsch PetscCheckFalse(m != n,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Intersecting different metric types not implemented"); 178293520041SJoe Wallwork } 178320282da2SJoe Wallwork 178420282da2SJoe Wallwork /* Intersect subsequent metrics in turn */ 178593520041SJoe Wallwork ierr = DMPlexMetricIsUniform(dm, &uniform);CHKERRQ(ierr); 178693520041SJoe Wallwork ierr = DMPlexMetricIsIsotropic(dm, &isotropic);CHKERRQ(ierr); 178793520041SJoe Wallwork if (uniform) { 178893520041SJoe Wallwork 178993520041SJoe Wallwork /* Uniform case */ 179093520041SJoe Wallwork ierr = VecGetArray(*metricInt, &met);CHKERRQ(ierr); 179193520041SJoe Wallwork for (i = 1; i < numMetrics; ++i) { 179293520041SJoe Wallwork ierr = VecGetArray(metrics[i], &meti);CHKERRQ(ierr); 179393520041SJoe Wallwork ierr = DMPlexMetricIntersection_Private(1, meti, met);CHKERRQ(ierr); 179493520041SJoe Wallwork ierr = VecRestoreArray(metrics[i], &meti);CHKERRQ(ierr); 179593520041SJoe Wallwork } 179693520041SJoe Wallwork ierr = VecRestoreArray(*metricInt, &met);CHKERRQ(ierr); 179793520041SJoe Wallwork } else { 179893520041SJoe Wallwork 179993520041SJoe Wallwork /* Spatially varying case */ 180093520041SJoe Wallwork PetscInt dim, vStart, vEnd, nrow; 180193520041SJoe Wallwork PetscScalar *M, *Mi; 180293520041SJoe Wallwork 180393520041SJoe Wallwork ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 180493520041SJoe Wallwork if (isotropic) nrow = 1; 180593520041SJoe Wallwork else nrow = dim; 180693520041SJoe Wallwork ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 180720282da2SJoe Wallwork ierr = VecGetArray(*metricInt, &met);CHKERRQ(ierr); 180820282da2SJoe Wallwork for (i = 1; i < numMetrics; ++i) { 180920282da2SJoe Wallwork ierr = VecGetArray(metrics[i], &meti);CHKERRQ(ierr); 181020282da2SJoe Wallwork for (v = vStart; v < vEnd; ++v) { 181120282da2SJoe Wallwork ierr = DMPlexPointLocalRef(dm, v, met, &M);CHKERRQ(ierr); 181220282da2SJoe Wallwork ierr = DMPlexPointLocalRef(dm, v, meti, &Mi);CHKERRQ(ierr); 181393520041SJoe Wallwork ierr = DMPlexMetricIntersection_Private(nrow, Mi, M);CHKERRQ(ierr); 181420282da2SJoe Wallwork } 181520282da2SJoe Wallwork ierr = VecRestoreArray(metrics[i], &meti);CHKERRQ(ierr); 181620282da2SJoe Wallwork } 181720282da2SJoe Wallwork ierr = VecRestoreArray(*metricInt, &met);CHKERRQ(ierr); 181820282da2SJoe Wallwork } 1819fe902aceSJoe Wallwork 1820fe902aceSJoe Wallwork ierr = PetscLogEventEnd(DMPLEX_MetricIntersection,0,0,0,0);CHKERRQ(ierr); 182120282da2SJoe Wallwork PetscFunctionReturn(0); 182220282da2SJoe Wallwork } 182320282da2SJoe Wallwork 1824cb7bfe8cSJoe Wallwork /*@ 182520282da2SJoe Wallwork DMPlexMetricIntersection2 - Compute the intersection of two metrics 182620282da2SJoe Wallwork 1827f1a722f8SMatthew G. Knepley Input Parameters: 182820282da2SJoe Wallwork + dm - The DM 182920282da2SJoe Wallwork . metric1 - The first metric to be intersected 183020282da2SJoe Wallwork - metric2 - The second metric to be intersected 183120282da2SJoe Wallwork 183220282da2SJoe Wallwork Output Parameter: 183320282da2SJoe Wallwork . metricInt - The intersected metric 183420282da2SJoe Wallwork 183520282da2SJoe Wallwork Level: beginner 183620282da2SJoe Wallwork 183720282da2SJoe Wallwork .seealso: DMPlexMetricIntersection(), DMPlexMetricIntersection3() 1838cb7bfe8cSJoe Wallwork @*/ 183920282da2SJoe Wallwork PetscErrorCode DMPlexMetricIntersection2(DM dm, Vec metric1, Vec metric2, Vec *metricInt) 184020282da2SJoe Wallwork { 184120282da2SJoe Wallwork PetscErrorCode ierr; 184220282da2SJoe Wallwork Vec metrics[2] = {metric1, metric2}; 184320282da2SJoe Wallwork 184420282da2SJoe Wallwork PetscFunctionBegin; 184520282da2SJoe Wallwork ierr = DMPlexMetricIntersection(dm, 2, metrics, metricInt);CHKERRQ(ierr); 184620282da2SJoe Wallwork PetscFunctionReturn(0); 184720282da2SJoe Wallwork } 184820282da2SJoe Wallwork 1849cb7bfe8cSJoe Wallwork /*@ 185020282da2SJoe Wallwork DMPlexMetricIntersection3 - Compute the intersection of three metrics 185120282da2SJoe Wallwork 1852f1a722f8SMatthew G. Knepley Input Parameters: 185320282da2SJoe Wallwork + dm - The DM 185420282da2SJoe Wallwork . metric1 - The first metric to be intersected 185520282da2SJoe Wallwork . metric2 - The second metric to be intersected 185620282da2SJoe Wallwork - metric3 - The third metric to be intersected 185720282da2SJoe Wallwork 185820282da2SJoe Wallwork Output Parameter: 185920282da2SJoe Wallwork . metricInt - The intersected metric 186020282da2SJoe Wallwork 186120282da2SJoe Wallwork Level: beginner 186220282da2SJoe Wallwork 186320282da2SJoe Wallwork .seealso: DMPlexMetricIntersection(), DMPlexMetricIntersection2() 1864cb7bfe8cSJoe Wallwork @*/ 186520282da2SJoe Wallwork PetscErrorCode DMPlexMetricIntersection3(DM dm, Vec metric1, Vec metric2, Vec metric3, Vec *metricInt) 186620282da2SJoe Wallwork { 186720282da2SJoe Wallwork PetscErrorCode ierr; 186820282da2SJoe Wallwork Vec metrics[3] = {metric1, metric2, metric3}; 186920282da2SJoe Wallwork 187020282da2SJoe Wallwork PetscFunctionBegin; 187120282da2SJoe Wallwork ierr = DMPlexMetricIntersection(dm, 3, metrics, metricInt);CHKERRQ(ierr); 187220282da2SJoe Wallwork PetscFunctionReturn(0); 187320282da2SJoe Wallwork } 1874