120282da2SJoe Wallwork #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 220282da2SJoe Wallwork #include <petscblaslapack.h> 320282da2SJoe Wallwork 431b70465SJoe Wallwork PetscErrorCode DMPlexMetricSetFromOptions(DM dm) 531b70465SJoe Wallwork { 631b70465SJoe Wallwork MPI_Comm comm; 731b70465SJoe Wallwork PetscBool isotropic = PETSC_FALSE, restrictAnisotropyFirst = PETSC_FALSE; 8*cc2eee55SJoe Wallwork PetscBool noInsert = PETSC_FALSE, noSwap = PETSC_FALSE, noMove = PETSC_FALSE; 931b70465SJoe Wallwork PetscErrorCode ierr; 10*cc2eee55SJoe Wallwork PetscInt verbosity = -1, numIter = 3; 11*cc2eee55SJoe 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; 1231b70465SJoe Wallwork 1331b70465SJoe Wallwork PetscFunctionBegin; 1431b70465SJoe Wallwork ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 1531b70465SJoe Wallwork ierr = PetscOptionsBegin(comm, "", "Riemannian metric options", "DMPlexMetric");CHKERRQ(ierr); 1631b70465SJoe Wallwork ierr = PetscOptionsBool("-dm_plex_metric_isotropic", "Is the metric isotropic?", "DMPlexMetricCreateIsotropic", isotropic, &isotropic, NULL);CHKERRQ(ierr); 17*cc2eee55SJoe Wallwork ierr = DMPlexMetricSetIsotropic(dm, isotropic);CHKERRQ(ierr); 1831b70465SJoe Wallwork ierr = PetscOptionsBool("-dm_plex_metric_restrict_anisotropy_first", "Should anisotropy be restricted before normalization?", "DMPlexNormalize", restrictAnisotropyFirst, &restrictAnisotropyFirst, NULL);CHKERRQ(ierr); 19*cc2eee55SJoe Wallwork ierr = DMPlexMetricSetRestrictAnisotropyFirst(dm, restrictAnisotropyFirst);CHKERRQ(ierr); 20*cc2eee55SJoe Wallwork ierr = PetscOptionsBool("-dm_plex_metric_no_insert", "Turn off node insertion and deletion", "DMAdaptMetric", noInsert, &noInsert, NULL);CHKERRQ(ierr); 21*cc2eee55SJoe Wallwork ierr = DMPlexMetricSetNoInsertion(dm, noInsert);CHKERRQ(ierr); 22*cc2eee55SJoe Wallwork ierr = PetscOptionsBool("-dm_plex_metric_no_swap", "Turn off facet swapping", "DMAdaptMetric", noSwap, &noSwap, NULL);CHKERRQ(ierr); 23*cc2eee55SJoe Wallwork ierr = DMPlexMetricSetNoSwapping(dm, noSwap);CHKERRQ(ierr); 24*cc2eee55SJoe Wallwork ierr = PetscOptionsBool("-dm_plex_metric_no_move", "Turn off facet node movement", "DMAdaptMetric", noMove, &noMove, NULL);CHKERRQ(ierr); 25*cc2eee55SJoe Wallwork ierr = DMPlexMetricSetNoMovement(dm, noMove);CHKERRQ(ierr); 26*cc2eee55SJoe Wallwork ierr = PetscOptionsBoundedInt("-dm_plex_metric_num_iterations", "Number of ParMmg adaptation iterations", "DMAdaptMetric", numIter, &numIter, NULL, 0);CHKERRQ(ierr); 27*cc2eee55SJoe Wallwork ierr = DMPlexMetricSetNumIterations(dm, numIter);CHKERRQ(ierr); 28*cc2eee55SJoe 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); 29*cc2eee55SJoe Wallwork ierr = DMPlexMetricSetVerbosity(dm, verbosity);CHKERRQ(ierr); 3031b70465SJoe Wallwork ierr = PetscOptionsReal("-dm_plex_metric_h_min", "Minimum tolerated metric magnitude", "DMPlexMetricEnforceSPD", h_min, &h_min, NULL);CHKERRQ(ierr); 3131b70465SJoe Wallwork ierr = DMPlexMetricSetMinimumMagnitude(dm, h_min);CHKERRQ(ierr); 3231b70465SJoe Wallwork ierr = PetscOptionsReal("-dm_plex_metric_h_max", "Maximum tolerated metric magnitude", "DMPlexMetricEnforceSPD", h_max, &h_max, NULL);CHKERRQ(ierr); 3331b70465SJoe Wallwork ierr = DMPlexMetricSetMaximumMagnitude(dm, h_max);CHKERRQ(ierr); 3431b70465SJoe Wallwork ierr = PetscOptionsReal("-dm_plex_metric_a_max", "Maximum tolerated anisotropy", "DMPlexMetricEnforceSPD", a_max, &a_max, NULL);CHKERRQ(ierr); 3531b70465SJoe Wallwork ierr = DMPlexMetricSetMaximumAnisotropy(dm, a_max);CHKERRQ(ierr); 3631b70465SJoe Wallwork ierr = PetscOptionsReal("-dm_plex_metric_p", "L-p normalization order", "DMPlexMetricNormalize", p, &p, NULL);CHKERRQ(ierr); 3731b70465SJoe Wallwork ierr = DMPlexMetricSetNormalizationOrder(dm, p);CHKERRQ(ierr); 3831b70465SJoe Wallwork ierr = PetscOptionsReal("-dm_plex_metric_target_complexity", "Target metric complexity", "DMPlexMetricNormalize", target, &target, NULL);CHKERRQ(ierr); 3931b70465SJoe Wallwork ierr = DMPlexMetricSetTargetComplexity(dm, target);CHKERRQ(ierr); 40*cc2eee55SJoe Wallwork ierr = PetscOptionsReal("-dm_plex_metric_gradation_factor", "Metric gradation factor", "DMAdaptMetric", beta, &beta, NULL);CHKERRQ(ierr); 41*cc2eee55SJoe Wallwork ierr = DMPlexMetricSetGradationFactor(dm, beta);CHKERRQ(ierr); 4231b70465SJoe Wallwork ierr = PetscOptionsEnd();CHKERRQ(ierr); 4331b70465SJoe Wallwork PetscFunctionReturn(0); 4431b70465SJoe Wallwork } 4531b70465SJoe Wallwork 4631b70465SJoe Wallwork /* 4731b70465SJoe Wallwork DMPlexMetricSetIsotropic - Record whether a metric is isotropic 4831b70465SJoe Wallwork 4931b70465SJoe Wallwork Input parameters: 5031b70465SJoe Wallwork + dm - The DM 5131b70465SJoe Wallwork - isotropic - Is the metric isotropic? 5231b70465SJoe Wallwork 5331b70465SJoe Wallwork Level: beginner 5431b70465SJoe Wallwork 5531b70465SJoe Wallwork .seealso: DMPlexMetricIsIsotropic(), DMPlexMetricSetRestrictAnisotropyFirst() 5631b70465SJoe Wallwork */ 5731b70465SJoe Wallwork PetscErrorCode DMPlexMetricSetIsotropic(DM dm, PetscBool isotropic) 5831b70465SJoe Wallwork { 5931b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 6031b70465SJoe Wallwork PetscErrorCode ierr; 6131b70465SJoe Wallwork 6231b70465SJoe Wallwork PetscFunctionBegin; 6331b70465SJoe Wallwork if (!plex->metricCtx) { 6431b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 6531b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 6631b70465SJoe Wallwork } 6731b70465SJoe Wallwork plex->metricCtx->isotropic = isotropic; 6831b70465SJoe Wallwork PetscFunctionReturn(0); 6931b70465SJoe Wallwork } 7031b70465SJoe Wallwork 7131b70465SJoe Wallwork /* 7231b70465SJoe Wallwork DMPlexMetricIsIsotropic - Is a metric is isotropic? 7331b70465SJoe Wallwork 7431b70465SJoe Wallwork Input parameters: 7531b70465SJoe Wallwork . dm - The DM 7631b70465SJoe Wallwork 7731b70465SJoe Wallwork Output parameters: 7831b70465SJoe Wallwork . isotropic - Is the metric isotropic? 7931b70465SJoe Wallwork 8031b70465SJoe Wallwork Level: beginner 8131b70465SJoe Wallwork 8231b70465SJoe Wallwork .seealso: DMPlexMetricSetIsotropic(), DMPlexMetricRestrictAnisotropyFirst() 8331b70465SJoe Wallwork */ 8431b70465SJoe Wallwork PetscErrorCode DMPlexMetricIsIsotropic(DM dm, PetscBool *isotropic) 8531b70465SJoe Wallwork { 8631b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 8731b70465SJoe Wallwork PetscErrorCode ierr; 8831b70465SJoe Wallwork 8931b70465SJoe Wallwork PetscFunctionBegin; 9031b70465SJoe Wallwork if (!plex->metricCtx) { 9131b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 9231b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 9331b70465SJoe Wallwork } 9431b70465SJoe Wallwork *isotropic = plex->metricCtx->isotropic; 9531b70465SJoe Wallwork PetscFunctionReturn(0); 9631b70465SJoe Wallwork } 9731b70465SJoe Wallwork 9831b70465SJoe Wallwork /* 9931b70465SJoe Wallwork DMPlexMetricSetRestrictAnisotropyFirst - Record whether anisotropy should be restricted before normalization 10031b70465SJoe Wallwork 10131b70465SJoe Wallwork Input parameters: 10231b70465SJoe Wallwork + dm - The DM 10331b70465SJoe Wallwork - restrictAnisotropyFirst - Should anisotropy be normalized first? 10431b70465SJoe Wallwork 10531b70465SJoe Wallwork Level: beginner 10631b70465SJoe Wallwork 10731b70465SJoe Wallwork .seealso: DMPlexMetricSetIsotropic(), DMPlexMetricRestrictAnisotropyFirst() 10831b70465SJoe Wallwork */ 10931b70465SJoe Wallwork PetscErrorCode DMPlexMetricSetRestrictAnisotropyFirst(DM dm, PetscBool restrictAnisotropyFirst) 11031b70465SJoe Wallwork { 11131b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 11231b70465SJoe Wallwork PetscErrorCode ierr; 11331b70465SJoe Wallwork 11431b70465SJoe Wallwork PetscFunctionBegin; 11531b70465SJoe Wallwork if (!plex->metricCtx) { 11631b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 11731b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 11831b70465SJoe Wallwork } 11931b70465SJoe Wallwork plex->metricCtx->restrictAnisotropyFirst = restrictAnisotropyFirst; 12031b70465SJoe Wallwork PetscFunctionReturn(0); 12131b70465SJoe Wallwork } 12231b70465SJoe Wallwork 12331b70465SJoe Wallwork /* 12431b70465SJoe Wallwork DMPlexMetricRestrictAnisotropyFirst - Is anisotropy restricted before normalization or after? 12531b70465SJoe Wallwork 12631b70465SJoe Wallwork Input parameters: 12731b70465SJoe Wallwork . dm - The DM 12831b70465SJoe Wallwork 12931b70465SJoe Wallwork Output parameters: 13031b70465SJoe Wallwork . restrictAnisotropyFirst - Is anisotropy be normalized first? 13131b70465SJoe Wallwork 13231b70465SJoe Wallwork Level: beginner 13331b70465SJoe Wallwork 13431b70465SJoe Wallwork .seealso: DMPlexMetricIsIsotropic(), DMPlexMetricSetRestrictAnisotropyFirst() 13531b70465SJoe Wallwork */ 13631b70465SJoe Wallwork PetscErrorCode DMPlexMetricRestrictAnisotropyFirst(DM dm, PetscBool *restrictAnisotropyFirst) 13731b70465SJoe Wallwork { 13831b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 13931b70465SJoe Wallwork PetscErrorCode ierr; 14031b70465SJoe Wallwork 14131b70465SJoe Wallwork PetscFunctionBegin; 14231b70465SJoe Wallwork if (!plex->metricCtx) { 14331b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 14431b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 14531b70465SJoe Wallwork } 14631b70465SJoe Wallwork *restrictAnisotropyFirst = plex->metricCtx->restrictAnisotropyFirst; 14731b70465SJoe Wallwork PetscFunctionReturn(0); 14831b70465SJoe Wallwork } 14931b70465SJoe Wallwork 15031b70465SJoe Wallwork /* 151*cc2eee55SJoe Wallwork DMPlexMetricSetNoInsertion - Should node insertion and deletion be turned off? 152*cc2eee55SJoe Wallwork 153*cc2eee55SJoe Wallwork Input parameters: 154*cc2eee55SJoe Wallwork + dm - The DM 155*cc2eee55SJoe Wallwork - noInsert - Should node insertion and deletion be turned off? 156*cc2eee55SJoe Wallwork 157*cc2eee55SJoe Wallwork Level: beginner 158*cc2eee55SJoe Wallwork 159*cc2eee55SJoe Wallwork .seealso: DMPlexMetricNoInsertion(), DMPlexMetricSetNoSwapping(), DMPlexMetricSetNoMovement() 160*cc2eee55SJoe Wallwork */ 161*cc2eee55SJoe Wallwork PetscErrorCode DMPlexMetricSetNoInsertion(DM dm, PetscBool noInsert) 162*cc2eee55SJoe Wallwork { 163*cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 164*cc2eee55SJoe Wallwork PetscErrorCode ierr; 165*cc2eee55SJoe Wallwork 166*cc2eee55SJoe Wallwork PetscFunctionBegin; 167*cc2eee55SJoe Wallwork if (!plex->metricCtx) { 168*cc2eee55SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 169*cc2eee55SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 170*cc2eee55SJoe Wallwork } 171*cc2eee55SJoe Wallwork plex->metricCtx->noInsert = noInsert; 172*cc2eee55SJoe Wallwork PetscFunctionReturn(0); 173*cc2eee55SJoe Wallwork } 174*cc2eee55SJoe Wallwork 175*cc2eee55SJoe Wallwork /* 176*cc2eee55SJoe Wallwork DMPlexMetricNoInsertion - Are node insertion and deletion turned off? 177*cc2eee55SJoe Wallwork 178*cc2eee55SJoe Wallwork Input parameters: 179*cc2eee55SJoe Wallwork . dm - The DM 180*cc2eee55SJoe Wallwork 181*cc2eee55SJoe Wallwork Output parameters: 182*cc2eee55SJoe Wallwork . noInsert - Are node insertion and deletion turned off? 183*cc2eee55SJoe Wallwork 184*cc2eee55SJoe Wallwork Level: beginner 185*cc2eee55SJoe Wallwork 186*cc2eee55SJoe Wallwork .seealso: DMPlexMetricSetNoInsertion(), DMPlexMetricNoSwapping(), DMPlexMetricNoMovement() 187*cc2eee55SJoe Wallwork */ 188*cc2eee55SJoe Wallwork PetscErrorCode DMPlexMetricNoInsertion(DM dm, PetscBool *noInsert) 189*cc2eee55SJoe Wallwork { 190*cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 191*cc2eee55SJoe Wallwork PetscErrorCode ierr; 192*cc2eee55SJoe Wallwork 193*cc2eee55SJoe Wallwork PetscFunctionBegin; 194*cc2eee55SJoe Wallwork if (!plex->metricCtx) { 195*cc2eee55SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 196*cc2eee55SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 197*cc2eee55SJoe Wallwork } 198*cc2eee55SJoe Wallwork *noInsert = plex->metricCtx->noInsert; 199*cc2eee55SJoe Wallwork PetscFunctionReturn(0); 200*cc2eee55SJoe Wallwork } 201*cc2eee55SJoe Wallwork 202*cc2eee55SJoe Wallwork /* 203*cc2eee55SJoe Wallwork DMPlexMetricSetNoSwapping - Should facet swapping be turned off? 204*cc2eee55SJoe Wallwork 205*cc2eee55SJoe Wallwork Input parameters: 206*cc2eee55SJoe Wallwork + dm - The DM 207*cc2eee55SJoe Wallwork - noSwap - Should facet swapping be turned off? 208*cc2eee55SJoe Wallwork 209*cc2eee55SJoe Wallwork Level: beginner 210*cc2eee55SJoe Wallwork 211*cc2eee55SJoe Wallwork .seealso: DMPlexMetricNoSwapping(), DMPlexMetricSetNoInsertion(), DMPlexMetricSetNoMovement() 212*cc2eee55SJoe Wallwork */ 213*cc2eee55SJoe Wallwork PetscErrorCode DMPlexMetricSetNoSwapping(DM dm, PetscBool noSwap) 214*cc2eee55SJoe Wallwork { 215*cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 216*cc2eee55SJoe Wallwork PetscErrorCode ierr; 217*cc2eee55SJoe Wallwork 218*cc2eee55SJoe Wallwork PetscFunctionBegin; 219*cc2eee55SJoe Wallwork if (!plex->metricCtx) { 220*cc2eee55SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 221*cc2eee55SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 222*cc2eee55SJoe Wallwork } 223*cc2eee55SJoe Wallwork plex->metricCtx->noSwap = noSwap; 224*cc2eee55SJoe Wallwork PetscFunctionReturn(0); 225*cc2eee55SJoe Wallwork } 226*cc2eee55SJoe Wallwork 227*cc2eee55SJoe Wallwork /* 228*cc2eee55SJoe Wallwork DMPlexMetricNoSwapping - Is facet swapping turned off? 229*cc2eee55SJoe Wallwork 230*cc2eee55SJoe Wallwork Input parameters: 231*cc2eee55SJoe Wallwork . dm - The DM 232*cc2eee55SJoe Wallwork 233*cc2eee55SJoe Wallwork Output parameters: 234*cc2eee55SJoe Wallwork . noSwap - Is facet swapping turned off? 235*cc2eee55SJoe Wallwork 236*cc2eee55SJoe Wallwork Level: beginner 237*cc2eee55SJoe Wallwork 238*cc2eee55SJoe Wallwork .seealso: DMPlexMetricSetNoSwapping(), DMPlexMetricNoInsertion(), DMPlexMetricNoMovement() 239*cc2eee55SJoe Wallwork */ 240*cc2eee55SJoe Wallwork PetscErrorCode DMPlexMetricNoSwapping(DM dm, PetscBool *noSwap) 241*cc2eee55SJoe Wallwork { 242*cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 243*cc2eee55SJoe Wallwork PetscErrorCode ierr; 244*cc2eee55SJoe Wallwork 245*cc2eee55SJoe Wallwork PetscFunctionBegin; 246*cc2eee55SJoe Wallwork if (!plex->metricCtx) { 247*cc2eee55SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 248*cc2eee55SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 249*cc2eee55SJoe Wallwork } 250*cc2eee55SJoe Wallwork *noSwap = plex->metricCtx->noSwap; 251*cc2eee55SJoe Wallwork PetscFunctionReturn(0); 252*cc2eee55SJoe Wallwork } 253*cc2eee55SJoe Wallwork 254*cc2eee55SJoe Wallwork /* 255*cc2eee55SJoe Wallwork DMPlexMetricSetNoMovement - Should node movement be turned off? 256*cc2eee55SJoe Wallwork 257*cc2eee55SJoe Wallwork Input parameters: 258*cc2eee55SJoe Wallwork + dm - The DM 259*cc2eee55SJoe Wallwork - noMove - Should node movement be turned off? 260*cc2eee55SJoe Wallwork 261*cc2eee55SJoe Wallwork Level: beginner 262*cc2eee55SJoe Wallwork 263*cc2eee55SJoe Wallwork .seealso: DMPlexMetricNoMovement(), DMPlexMetricSetNoInsertion(), DMPlexMetricSetNoSwapping() 264*cc2eee55SJoe Wallwork */ 265*cc2eee55SJoe Wallwork PetscErrorCode DMPlexMetricSetNoMovement(DM dm, PetscBool noMove) 266*cc2eee55SJoe Wallwork { 267*cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 268*cc2eee55SJoe Wallwork PetscErrorCode ierr; 269*cc2eee55SJoe Wallwork 270*cc2eee55SJoe Wallwork PetscFunctionBegin; 271*cc2eee55SJoe Wallwork if (!plex->metricCtx) { 272*cc2eee55SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 273*cc2eee55SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 274*cc2eee55SJoe Wallwork } 275*cc2eee55SJoe Wallwork plex->metricCtx->noMove = noMove; 276*cc2eee55SJoe Wallwork PetscFunctionReturn(0); 277*cc2eee55SJoe Wallwork } 278*cc2eee55SJoe Wallwork 279*cc2eee55SJoe Wallwork /* 280*cc2eee55SJoe Wallwork DMPlexMetricNoMovement - Is node movement turned off? 281*cc2eee55SJoe Wallwork 282*cc2eee55SJoe Wallwork Input parameters: 283*cc2eee55SJoe Wallwork . dm - The DM 284*cc2eee55SJoe Wallwork 285*cc2eee55SJoe Wallwork Output parameters: 286*cc2eee55SJoe Wallwork . noMove - Is node movement turned off? 287*cc2eee55SJoe Wallwork 288*cc2eee55SJoe Wallwork Level: beginner 289*cc2eee55SJoe Wallwork 290*cc2eee55SJoe Wallwork .seealso: DMPlexMetricSetNoMovement(), DMPlexMetricNoInsertion(), DMPlexMetricNoSwapping() 291*cc2eee55SJoe Wallwork */ 292*cc2eee55SJoe Wallwork PetscErrorCode DMPlexMetricNoMovement(DM dm, PetscBool *noMove) 293*cc2eee55SJoe Wallwork { 294*cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 295*cc2eee55SJoe Wallwork PetscErrorCode ierr; 296*cc2eee55SJoe Wallwork 297*cc2eee55SJoe Wallwork PetscFunctionBegin; 298*cc2eee55SJoe Wallwork if (!plex->metricCtx) { 299*cc2eee55SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 300*cc2eee55SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 301*cc2eee55SJoe Wallwork } 302*cc2eee55SJoe Wallwork *noMove = plex->metricCtx->noMove; 303*cc2eee55SJoe Wallwork PetscFunctionReturn(0); 304*cc2eee55SJoe Wallwork } 305*cc2eee55SJoe Wallwork 306*cc2eee55SJoe Wallwork /* 30731b70465SJoe Wallwork DMPlexMetricSetMinimumMagnitude - Set the minimum tolerated metric magnitude 30831b70465SJoe Wallwork 30931b70465SJoe Wallwork Input parameters: 31031b70465SJoe Wallwork + dm - The DM 31131b70465SJoe Wallwork - h_min - The minimum tolerated metric magnitude 31231b70465SJoe Wallwork 31331b70465SJoe Wallwork Level: beginner 31431b70465SJoe Wallwork 31531b70465SJoe Wallwork .seealso: DMPlexMetricGetMinimumMagnitude(), DMPlexMetricSetMaximumMagnitude() 31631b70465SJoe Wallwork */ 31731b70465SJoe Wallwork PetscErrorCode DMPlexMetricSetMinimumMagnitude(DM dm, PetscReal h_min) 31831b70465SJoe Wallwork { 31931b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 32031b70465SJoe Wallwork PetscErrorCode ierr; 32131b70465SJoe Wallwork 32231b70465SJoe Wallwork PetscFunctionBegin; 32331b70465SJoe Wallwork if (!plex->metricCtx) { 32431b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 32531b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 32631b70465SJoe Wallwork } 32731b70465SJoe Wallwork if (h_min <= 0.0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Metric magnitudes must be positive, not %.4e", h_min); 32831b70465SJoe Wallwork plex->metricCtx->h_min = h_min; 32931b70465SJoe Wallwork PetscFunctionReturn(0); 33031b70465SJoe Wallwork } 33131b70465SJoe Wallwork 33231b70465SJoe Wallwork /* 33331b70465SJoe Wallwork DMPlexMetricGetMinimumMagnitude - Get the minimum tolerated metric magnitude 33431b70465SJoe Wallwork 33531b70465SJoe Wallwork Input parameters: 33631b70465SJoe Wallwork . dm - The DM 33731b70465SJoe Wallwork 338*cc2eee55SJoe Wallwork Output parameters: 33931b70465SJoe Wallwork . h_min - The minimum tolerated metric magnitude 34031b70465SJoe Wallwork 34131b70465SJoe Wallwork Level: beginner 34231b70465SJoe Wallwork 34331b70465SJoe Wallwork .seealso: DMPlexMetricSetMinimumMagnitude(), DMPlexMetricGetMaximumMagnitude() 34431b70465SJoe Wallwork */ 34531b70465SJoe Wallwork PetscErrorCode DMPlexMetricGetMinimumMagnitude(DM dm, PetscReal *h_min) 34631b70465SJoe Wallwork { 34731b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 34831b70465SJoe Wallwork PetscErrorCode ierr; 34931b70465SJoe Wallwork 35031b70465SJoe Wallwork PetscFunctionBegin; 35131b70465SJoe Wallwork if (!plex->metricCtx) { 35231b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 35331b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 35431b70465SJoe Wallwork } 35531b70465SJoe Wallwork *h_min = plex->metricCtx->h_min; 35631b70465SJoe Wallwork PetscFunctionReturn(0); 35731b70465SJoe Wallwork } 35831b70465SJoe Wallwork 35931b70465SJoe Wallwork /* 36031b70465SJoe Wallwork DMPlexMetricSetMaximumMagnitude - Set the maximum tolerated metric magnitude 36131b70465SJoe Wallwork 36231b70465SJoe Wallwork Input parameters: 36331b70465SJoe Wallwork + dm - The DM 36431b70465SJoe Wallwork - h_max - The maximum tolerated metric magnitude 36531b70465SJoe Wallwork 36631b70465SJoe Wallwork Level: beginner 36731b70465SJoe Wallwork 36831b70465SJoe Wallwork .seealso: DMPlexMetricGetMaximumMagnitude(), DMPlexMetricSetMinimumMagnitude() 36931b70465SJoe Wallwork */ 37031b70465SJoe Wallwork PetscErrorCode DMPlexMetricSetMaximumMagnitude(DM dm, PetscReal h_max) 37131b70465SJoe Wallwork { 37231b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 37331b70465SJoe Wallwork PetscErrorCode ierr; 37431b70465SJoe Wallwork 37531b70465SJoe Wallwork PetscFunctionBegin; 37631b70465SJoe Wallwork if (!plex->metricCtx) { 37731b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 37831b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 37931b70465SJoe Wallwork } 38031b70465SJoe Wallwork if (h_max <= 0.0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Metric magnitudes must be positive, not %.4e", h_max); 38131b70465SJoe Wallwork plex->metricCtx->h_max = h_max; 38231b70465SJoe Wallwork PetscFunctionReturn(0); 38331b70465SJoe Wallwork } 38431b70465SJoe Wallwork 38531b70465SJoe Wallwork /* 38631b70465SJoe Wallwork DMPlexMetricGetMaximumMagnitude - Get the maximum tolerated metric magnitude 38731b70465SJoe Wallwork 38831b70465SJoe Wallwork Input parameters: 38931b70465SJoe Wallwork . dm - The DM 39031b70465SJoe Wallwork 391*cc2eee55SJoe Wallwork Output parameters: 39231b70465SJoe Wallwork . h_max - The maximum tolerated metric magnitude 39331b70465SJoe Wallwork 39431b70465SJoe Wallwork Level: beginner 39531b70465SJoe Wallwork 39631b70465SJoe Wallwork .seealso: DMPlexMetricSetMaximumMagnitude(), DMPlexMetricGetMinimumMagnitude() 39731b70465SJoe Wallwork */ 39831b70465SJoe Wallwork PetscErrorCode DMPlexMetricGetMaximumMagnitude(DM dm, PetscReal *h_max) 39931b70465SJoe Wallwork { 40031b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 40131b70465SJoe Wallwork PetscErrorCode ierr; 40231b70465SJoe Wallwork 40331b70465SJoe Wallwork PetscFunctionBegin; 40431b70465SJoe Wallwork if (!plex->metricCtx) { 40531b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 40631b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 40731b70465SJoe Wallwork } 40831b70465SJoe Wallwork *h_max = plex->metricCtx->h_max; 40931b70465SJoe Wallwork PetscFunctionReturn(0); 41031b70465SJoe Wallwork } 41131b70465SJoe Wallwork 41231b70465SJoe Wallwork /* 41331b70465SJoe Wallwork DMPlexMetricSetMaximumAnisotropy - Set the maximum tolerated metric anisotropy 41431b70465SJoe Wallwork 41531b70465SJoe Wallwork Input parameters: 41631b70465SJoe Wallwork + dm - The DM 41731b70465SJoe Wallwork - a_max - The maximum tolerated metric anisotropy 41831b70465SJoe Wallwork 41931b70465SJoe Wallwork Level: beginner 42031b70465SJoe Wallwork 42131b70465SJoe Wallwork Note: If the value zero is given then anisotropy will not be restricted. Otherwise, it should be at least one. 42231b70465SJoe Wallwork 42331b70465SJoe Wallwork .seealso: DMPlexMetricGetMaximumAnisotropy(), DMPlexMetricSetMaximumMagnitude() 42431b70465SJoe Wallwork */ 42531b70465SJoe Wallwork PetscErrorCode DMPlexMetricSetMaximumAnisotropy(DM dm, PetscReal a_max) 42631b70465SJoe Wallwork { 42731b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 42831b70465SJoe Wallwork PetscErrorCode ierr; 42931b70465SJoe Wallwork 43031b70465SJoe Wallwork PetscFunctionBegin; 43131b70465SJoe Wallwork if (!plex->metricCtx) { 43231b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 43331b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 43431b70465SJoe Wallwork } 43531b70465SJoe Wallwork if (a_max < 1.0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Anisotropy must be at least one, not %.4e", a_max); 43631b70465SJoe Wallwork plex->metricCtx->a_max = a_max; 43731b70465SJoe Wallwork PetscFunctionReturn(0); 43831b70465SJoe Wallwork } 43931b70465SJoe Wallwork 44031b70465SJoe Wallwork /* 44131b70465SJoe Wallwork DMPlexMetricGetMaximumAnisotropy - Get the maximum tolerated metric anisotropy 44231b70465SJoe Wallwork 44331b70465SJoe Wallwork Input parameters: 44431b70465SJoe Wallwork . dm - The DM 44531b70465SJoe Wallwork 446*cc2eee55SJoe Wallwork Output parameters: 44731b70465SJoe Wallwork . a_max - The maximum tolerated metric anisotropy 44831b70465SJoe Wallwork 44931b70465SJoe Wallwork Level: beginner 45031b70465SJoe Wallwork 45131b70465SJoe Wallwork .seealso: DMPlexMetricSetMaximumAnisotropy(), DMPlexMetricGetMaximumMagnitude() 45231b70465SJoe Wallwork */ 45331b70465SJoe Wallwork PetscErrorCode DMPlexMetricGetMaximumAnisotropy(DM dm, PetscReal *a_max) 45431b70465SJoe Wallwork { 45531b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 45631b70465SJoe Wallwork PetscErrorCode ierr; 45731b70465SJoe Wallwork 45831b70465SJoe Wallwork PetscFunctionBegin; 45931b70465SJoe Wallwork if (!plex->metricCtx) { 46031b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 46131b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 46231b70465SJoe Wallwork } 46331b70465SJoe Wallwork *a_max = plex->metricCtx->a_max; 46431b70465SJoe Wallwork PetscFunctionReturn(0); 46531b70465SJoe Wallwork } 46631b70465SJoe Wallwork 46731b70465SJoe Wallwork /* 46831b70465SJoe Wallwork DMPlexMetricSetTargetComplexity - Set the target metric complexity 46931b70465SJoe Wallwork 47031b70465SJoe Wallwork Input parameters: 47131b70465SJoe Wallwork + dm - The DM 47231b70465SJoe Wallwork - targetComplexity - The target metric complexity 47331b70465SJoe Wallwork 47431b70465SJoe Wallwork Level: beginner 47531b70465SJoe Wallwork 47631b70465SJoe Wallwork .seealso: DMPlexMetricGetTargetComplexity(), DMPlexMetricSetNormalizationOrder() 47731b70465SJoe Wallwork */ 47831b70465SJoe Wallwork PetscErrorCode DMPlexMetricSetTargetComplexity(DM dm, PetscReal targetComplexity) 47931b70465SJoe Wallwork { 48031b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 48131b70465SJoe Wallwork PetscErrorCode ierr; 48231b70465SJoe Wallwork 48331b70465SJoe Wallwork PetscFunctionBegin; 48431b70465SJoe Wallwork if (!plex->metricCtx) { 48531b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 48631b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 48731b70465SJoe Wallwork } 48831b70465SJoe Wallwork if (targetComplexity <= 0.0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Metric complexity must be positive"); 48931b70465SJoe Wallwork plex->metricCtx->targetComplexity = targetComplexity; 49031b70465SJoe Wallwork PetscFunctionReturn(0); 49131b70465SJoe Wallwork } 49231b70465SJoe Wallwork 49331b70465SJoe Wallwork /* 49431b70465SJoe Wallwork DMPlexMetricGetTargetComplexity - Get the target metric complexity 49531b70465SJoe Wallwork 49631b70465SJoe Wallwork Input parameters: 49731b70465SJoe Wallwork . dm - The DM 49831b70465SJoe Wallwork 499*cc2eee55SJoe Wallwork Output parameters: 50031b70465SJoe Wallwork . targetComplexity - The target metric complexity 50131b70465SJoe Wallwork 50231b70465SJoe Wallwork Level: beginner 50331b70465SJoe Wallwork 50431b70465SJoe Wallwork .seealso: DMPlexMetricSetTargetComplexity(), DMPlexMetricGetNormalizationOrder() 50531b70465SJoe Wallwork */ 50631b70465SJoe Wallwork PetscErrorCode DMPlexMetricGetTargetComplexity(DM dm, PetscReal *targetComplexity) 50731b70465SJoe Wallwork { 50831b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 50931b70465SJoe Wallwork PetscErrorCode ierr; 51031b70465SJoe Wallwork 51131b70465SJoe Wallwork PetscFunctionBegin; 51231b70465SJoe Wallwork if (!plex->metricCtx) { 51331b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 51431b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 51531b70465SJoe Wallwork } 51631b70465SJoe Wallwork *targetComplexity = plex->metricCtx->targetComplexity; 51731b70465SJoe Wallwork PetscFunctionReturn(0); 51831b70465SJoe Wallwork } 51931b70465SJoe Wallwork 52031b70465SJoe Wallwork /* 52131b70465SJoe Wallwork DMPlexMetricSetNormalizationOrder - Set the order p for L-p normalization 52231b70465SJoe Wallwork 52331b70465SJoe Wallwork Input parameters: 52431b70465SJoe Wallwork + dm - The DM 52531b70465SJoe Wallwork - p - The normalization order 52631b70465SJoe Wallwork 52731b70465SJoe Wallwork Level: beginner 52831b70465SJoe Wallwork 52931b70465SJoe Wallwork .seealso: DMPlexMetricGetNormalizationOrder(), DMPlexMetricSetTargetComplexity() 53031b70465SJoe Wallwork */ 53131b70465SJoe Wallwork PetscErrorCode DMPlexMetricSetNormalizationOrder(DM dm, PetscReal p) 53231b70465SJoe Wallwork { 53331b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 53431b70465SJoe Wallwork PetscErrorCode ierr; 53531b70465SJoe Wallwork 53631b70465SJoe Wallwork PetscFunctionBegin; 53731b70465SJoe Wallwork if (!plex->metricCtx) { 53831b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 53931b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 54031b70465SJoe Wallwork } 54131b70465SJoe Wallwork if (p < 1.0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Normalization order must be one or greater"); 54231b70465SJoe Wallwork plex->metricCtx->p = p; 54331b70465SJoe Wallwork PetscFunctionReturn(0); 54431b70465SJoe Wallwork } 54531b70465SJoe Wallwork 54631b70465SJoe Wallwork /* 54731b70465SJoe Wallwork DMPlexMetricGetNormalizationOrder - Get the order p for L-p normalization 54831b70465SJoe Wallwork 54931b70465SJoe Wallwork Input parameters: 55031b70465SJoe Wallwork . dm - The DM 55131b70465SJoe Wallwork 552*cc2eee55SJoe Wallwork Output parameters: 55331b70465SJoe Wallwork . p - The normalization order 55431b70465SJoe Wallwork 55531b70465SJoe Wallwork Level: beginner 55631b70465SJoe Wallwork 55731b70465SJoe Wallwork .seealso: DMPlexMetricSetNormalizationOrder(), DMPlexMetricGetTargetComplexity() 55831b70465SJoe Wallwork */ 55931b70465SJoe Wallwork PetscErrorCode DMPlexMetricGetNormalizationOrder(DM dm, PetscReal *p) 56031b70465SJoe Wallwork { 56131b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 56231b70465SJoe Wallwork PetscErrorCode ierr; 56331b70465SJoe Wallwork 56431b70465SJoe Wallwork PetscFunctionBegin; 56531b70465SJoe Wallwork if (!plex->metricCtx) { 56631b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 56731b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 56831b70465SJoe Wallwork } 56931b70465SJoe Wallwork *p = plex->metricCtx->p; 57031b70465SJoe Wallwork PetscFunctionReturn(0); 57131b70465SJoe Wallwork } 57231b70465SJoe Wallwork 573*cc2eee55SJoe Wallwork /* 574*cc2eee55SJoe Wallwork DMPlexMetricSetGradationFactor - Set the metric gradation factor 575*cc2eee55SJoe Wallwork 576*cc2eee55SJoe Wallwork Input parameters: 577*cc2eee55SJoe Wallwork + dm - The DM 578*cc2eee55SJoe Wallwork - beta - The metric gradation factor 579*cc2eee55SJoe Wallwork 580*cc2eee55SJoe Wallwork Level: beginner 581*cc2eee55SJoe Wallwork 582*cc2eee55SJoe Wallwork Notes: 583*cc2eee55SJoe Wallwork 584*cc2eee55SJoe Wallwork The gradation factor is the maximum tolerated length ratio between adjacent edges. 585*cc2eee55SJoe Wallwork 586*cc2eee55SJoe Wallwork Turn off gradation by passing the value -1. Otherwise, pass a positive value. 587*cc2eee55SJoe Wallwork 588*cc2eee55SJoe Wallwork .seealso: DMPlexMetricGetGradationFactor() 589*cc2eee55SJoe Wallwork */ 590*cc2eee55SJoe Wallwork PetscErrorCode DMPlexMetricSetGradationFactor(DM dm, PetscReal beta) 591*cc2eee55SJoe Wallwork { 592*cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 593*cc2eee55SJoe Wallwork PetscErrorCode ierr; 594*cc2eee55SJoe Wallwork 595*cc2eee55SJoe Wallwork PetscFunctionBegin; 596*cc2eee55SJoe Wallwork if (!plex->metricCtx) { 597*cc2eee55SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 598*cc2eee55SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 599*cc2eee55SJoe Wallwork } 600*cc2eee55SJoe Wallwork plex->metricCtx->gradationFactor = beta; 601*cc2eee55SJoe Wallwork PetscFunctionReturn(0); 602*cc2eee55SJoe Wallwork } 603*cc2eee55SJoe Wallwork 604*cc2eee55SJoe Wallwork /* 605*cc2eee55SJoe Wallwork DMPlexMetricGetGradationFactor - Get the metric gradation factor 606*cc2eee55SJoe Wallwork 607*cc2eee55SJoe Wallwork Input parameters: 608*cc2eee55SJoe Wallwork . dm - The DM 609*cc2eee55SJoe Wallwork 610*cc2eee55SJoe Wallwork Output parameters: 611*cc2eee55SJoe Wallwork . beta - The metric gradation factor 612*cc2eee55SJoe Wallwork 613*cc2eee55SJoe Wallwork Level: beginner 614*cc2eee55SJoe Wallwork 615*cc2eee55SJoe Wallwork Note: The gradation factor is the maximum tolerated length ratio between adjacent edges. 616*cc2eee55SJoe Wallwork 617*cc2eee55SJoe Wallwork .seealso: DMPlexMetricSetGradationFactor() 618*cc2eee55SJoe Wallwork */ 619*cc2eee55SJoe Wallwork PetscErrorCode DMPlexMetricGetGradationFactor(DM dm, PetscReal *beta) 620*cc2eee55SJoe Wallwork { 621*cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 622*cc2eee55SJoe Wallwork PetscErrorCode ierr; 623*cc2eee55SJoe Wallwork 624*cc2eee55SJoe Wallwork PetscFunctionBegin; 625*cc2eee55SJoe Wallwork if (!plex->metricCtx) { 626*cc2eee55SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 627*cc2eee55SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 628*cc2eee55SJoe Wallwork } 629*cc2eee55SJoe Wallwork *beta = plex->metricCtx->gradationFactor; 630*cc2eee55SJoe Wallwork PetscFunctionReturn(0); 631*cc2eee55SJoe Wallwork } 632*cc2eee55SJoe Wallwork 633*cc2eee55SJoe Wallwork /* 634*cc2eee55SJoe Wallwork DMPlexMetricSetVerbosity - Set the verbosity of the mesh adaptation package 635*cc2eee55SJoe Wallwork 636*cc2eee55SJoe Wallwork Input parameters: 637*cc2eee55SJoe Wallwork + dm - The DM 638*cc2eee55SJoe Wallwork - verbosity - The verbosity, where -1 is silent and 10 is maximum 639*cc2eee55SJoe Wallwork 640*cc2eee55SJoe Wallwork .seealso: DMPlexMetricGetVerbosity(), DMPlexMetricSetNumIterations() 641*cc2eee55SJoe Wallwork */ 642*cc2eee55SJoe Wallwork PetscErrorCode DMPlexMetricSetVerbosity(DM dm, PetscInt verbosity) 643*cc2eee55SJoe Wallwork { 644*cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 645*cc2eee55SJoe Wallwork PetscErrorCode ierr; 646*cc2eee55SJoe Wallwork 647*cc2eee55SJoe Wallwork PetscFunctionBegin; 648*cc2eee55SJoe Wallwork if (!plex->metricCtx) { 649*cc2eee55SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 650*cc2eee55SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 651*cc2eee55SJoe Wallwork } 652*cc2eee55SJoe Wallwork plex->metricCtx->verbosity = verbosity; 653*cc2eee55SJoe Wallwork PetscFunctionReturn(0); 654*cc2eee55SJoe Wallwork } 655*cc2eee55SJoe Wallwork 656*cc2eee55SJoe Wallwork /* 657*cc2eee55SJoe Wallwork DMPlexMetricGetVerbosity - Get the verbosity of the mesh adaptation package 658*cc2eee55SJoe Wallwork 659*cc2eee55SJoe Wallwork Input parameters: 660*cc2eee55SJoe Wallwork . dm - The DM 661*cc2eee55SJoe Wallwork 662*cc2eee55SJoe Wallwork Output parameters: 663*cc2eee55SJoe Wallwork . verbosity - The verbosity, where -1 is silent and 10 is maximum 664*cc2eee55SJoe Wallwork 665*cc2eee55SJoe Wallwork .seealso: DMPlexMetricSetVerbosity(), DMPlexMetricGetNumIterations() 666*cc2eee55SJoe Wallwork */ 667*cc2eee55SJoe Wallwork PetscErrorCode DMPlexMetricGetVerbosity(DM dm, PetscInt *verbosity) 668*cc2eee55SJoe Wallwork { 669*cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 670*cc2eee55SJoe Wallwork PetscErrorCode ierr; 671*cc2eee55SJoe Wallwork 672*cc2eee55SJoe Wallwork PetscFunctionBegin; 673*cc2eee55SJoe Wallwork if (!plex->metricCtx) { 674*cc2eee55SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 675*cc2eee55SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 676*cc2eee55SJoe Wallwork } 677*cc2eee55SJoe Wallwork *verbosity = plex->metricCtx->verbosity; 678*cc2eee55SJoe Wallwork PetscFunctionReturn(0); 679*cc2eee55SJoe Wallwork } 680*cc2eee55SJoe Wallwork 681*cc2eee55SJoe Wallwork /* 682*cc2eee55SJoe Wallwork DMPlexMetricSetNumIterations - Set the number of parallel adaptation iterations 683*cc2eee55SJoe Wallwork 684*cc2eee55SJoe Wallwork Input parameters: 685*cc2eee55SJoe Wallwork + dm - The DM 686*cc2eee55SJoe Wallwork - numIter - the number of parallel adaptation iterations 687*cc2eee55SJoe Wallwork 688*cc2eee55SJoe Wallwork Note: This option is only used by ParMmg, not Mmg or Pragmatic. 689*cc2eee55SJoe Wallwork 690*cc2eee55SJoe Wallwork .seealso: DMPlexMetricSetVerbosity(), DMPlexMetricGetNumIterations() 691*cc2eee55SJoe Wallwork */ 692*cc2eee55SJoe Wallwork PetscErrorCode DMPlexMetricSetNumIterations(DM dm, PetscInt numIter) 693*cc2eee55SJoe Wallwork { 694*cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 695*cc2eee55SJoe Wallwork PetscErrorCode ierr; 696*cc2eee55SJoe Wallwork 697*cc2eee55SJoe Wallwork PetscFunctionBegin; 698*cc2eee55SJoe Wallwork if (!plex->metricCtx) { 699*cc2eee55SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 700*cc2eee55SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 701*cc2eee55SJoe Wallwork } 702*cc2eee55SJoe Wallwork plex->metricCtx->numIter = numIter; 703*cc2eee55SJoe Wallwork PetscFunctionReturn(0); 704*cc2eee55SJoe Wallwork } 705*cc2eee55SJoe Wallwork 706*cc2eee55SJoe Wallwork /* 707*cc2eee55SJoe Wallwork DMPlexMetricGetNumIterations - Get the number of parallel adaptation iterations 708*cc2eee55SJoe Wallwork 709*cc2eee55SJoe Wallwork Input parameters: 710*cc2eee55SJoe Wallwork . dm - The DM 711*cc2eee55SJoe Wallwork 712*cc2eee55SJoe Wallwork Output parameters: 713*cc2eee55SJoe Wallwork . numIter - the number of parallel adaptation iterations 714*cc2eee55SJoe Wallwork 715*cc2eee55SJoe Wallwork Note: This option is only used by ParMmg, not Mmg or Pragmatic. 716*cc2eee55SJoe Wallwork 717*cc2eee55SJoe Wallwork .seealso: DMPlexMetricSetNumIterations(), DMPlexMetricGetVerbosity() 718*cc2eee55SJoe Wallwork */ 719*cc2eee55SJoe Wallwork PetscErrorCode DMPlexMetricGetNumIterations(DM dm, PetscInt *numIter) 720*cc2eee55SJoe Wallwork { 721*cc2eee55SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 722*cc2eee55SJoe Wallwork PetscErrorCode ierr; 723*cc2eee55SJoe Wallwork 724*cc2eee55SJoe Wallwork PetscFunctionBegin; 725*cc2eee55SJoe Wallwork if (!plex->metricCtx) { 726*cc2eee55SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 727*cc2eee55SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 728*cc2eee55SJoe Wallwork } 729*cc2eee55SJoe Wallwork *numIter = plex->metricCtx->numIter; 730*cc2eee55SJoe Wallwork PetscFunctionReturn(0); 731*cc2eee55SJoe Wallwork } 732*cc2eee55SJoe Wallwork 73320282da2SJoe Wallwork PetscErrorCode DMPlexP1FieldCreate_Private(DM dm, PetscInt f, PetscInt size, Vec *metric) 73420282da2SJoe Wallwork { 73520282da2SJoe Wallwork MPI_Comm comm; 73620282da2SJoe Wallwork PetscErrorCode ierr; 73720282da2SJoe Wallwork PetscFE fe; 73820282da2SJoe Wallwork PetscInt dim; 73920282da2SJoe Wallwork 74020282da2SJoe Wallwork PetscFunctionBegin; 74120282da2SJoe Wallwork 74220282da2SJoe Wallwork /* Extract metadata from dm */ 74320282da2SJoe Wallwork ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 74420282da2SJoe Wallwork ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 74520282da2SJoe Wallwork 74620282da2SJoe Wallwork /* Create a P1 field of the requested size */ 74720282da2SJoe Wallwork ierr = PetscFECreateLagrange(comm, dim, size, PETSC_TRUE, 1, PETSC_DETERMINE, &fe);CHKERRQ(ierr); 74820282da2SJoe Wallwork ierr = DMSetField(dm, f, NULL, (PetscObject)fe);CHKERRQ(ierr); 74920282da2SJoe Wallwork ierr = DMCreateDS(dm);CHKERRQ(ierr); 75020282da2SJoe Wallwork ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 75120282da2SJoe Wallwork ierr = DMCreateLocalVector(dm, metric);CHKERRQ(ierr); 75220282da2SJoe Wallwork 75320282da2SJoe Wallwork PetscFunctionReturn(0); 75420282da2SJoe Wallwork } 75520282da2SJoe Wallwork 75620282da2SJoe Wallwork /* 75720282da2SJoe Wallwork DMPlexMetricCreate - Create a Riemannian metric field 75820282da2SJoe Wallwork 75920282da2SJoe Wallwork Input parameters: 76020282da2SJoe Wallwork + dm - The DM 76120282da2SJoe Wallwork - f - The field number to use 76220282da2SJoe Wallwork 76320282da2SJoe Wallwork Output parameter: 76420282da2SJoe Wallwork . metric - The metric 76520282da2SJoe Wallwork 76620282da2SJoe Wallwork Level: beginner 76720282da2SJoe Wallwork 76831b70465SJoe Wallwork Notes: 76931b70465SJoe Wallwork 77031b70465SJoe Wallwork It is assumed that the DM is comprised of simplices. 77131b70465SJoe Wallwork 77231b70465SJoe Wallwork Command line options for Riemannian metrics: 77331b70465SJoe Wallwork 77431b70465SJoe Wallwork -dm_plex_metric_isotropic - Is the metric isotropic? 77531b70465SJoe Wallwork -dm_plex_metric_restrict_anisotropy_first - Should anisotropy be restricted before normalization? 77631b70465SJoe Wallwork -dm_plex_metric_h_min - Minimum tolerated metric magnitude 77731b70465SJoe Wallwork -dm_plex_metric_h_max - Maximum tolerated metric magnitude 77831b70465SJoe Wallwork -dm_plex_metric_a_max - Maximum tolerated anisotropy 77931b70465SJoe Wallwork -dm_plex_metric_p - L-p normalization order 78031b70465SJoe Wallwork -dm_plex_metric_target_complexity - Target metric complexity 78120282da2SJoe Wallwork 78220282da2SJoe Wallwork .seealso: DMPlexMetricCreateUniform(), DMPlexMetricCreateIsotropic() 78320282da2SJoe Wallwork */ 78420282da2SJoe Wallwork PetscErrorCode DMPlexMetricCreate(DM dm, PetscInt f, Vec *metric) 78520282da2SJoe Wallwork { 78631b70465SJoe Wallwork DM_Plex *plex = (DM_Plex *) dm->data; 78720282da2SJoe Wallwork PetscErrorCode ierr; 78820282da2SJoe Wallwork PetscInt coordDim, Nd; 78920282da2SJoe Wallwork 79020282da2SJoe Wallwork PetscFunctionBegin; 79131b70465SJoe Wallwork if (!plex->metricCtx) { 79231b70465SJoe Wallwork ierr = PetscNew(&plex->metricCtx);CHKERRQ(ierr); 79331b70465SJoe Wallwork ierr = DMPlexMetricSetFromOptions(dm);CHKERRQ(ierr); 79431b70465SJoe Wallwork } 79520282da2SJoe Wallwork ierr = DMGetCoordinateDim(dm, &coordDim);CHKERRQ(ierr); 79620282da2SJoe Wallwork Nd = coordDim*coordDim; 79720282da2SJoe Wallwork ierr = DMPlexP1FieldCreate_Private(dm, f, Nd, metric);CHKERRQ(ierr); 79820282da2SJoe Wallwork PetscFunctionReturn(0); 79920282da2SJoe Wallwork } 80020282da2SJoe Wallwork 80120282da2SJoe Wallwork typedef struct { 80220282da2SJoe Wallwork PetscReal scaling; /* Scaling for uniform metric diagonal */ 80320282da2SJoe Wallwork } DMPlexMetricUniformCtx; 80420282da2SJoe Wallwork 80520282da2SJoe Wallwork static PetscErrorCode diagonal(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx) 80620282da2SJoe Wallwork { 80720282da2SJoe Wallwork DMPlexMetricUniformCtx *user = (DMPlexMetricUniformCtx*)ctx; 80820282da2SJoe Wallwork PetscInt i, j; 80920282da2SJoe Wallwork 81020282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 81120282da2SJoe Wallwork for (j = 0; j < dim; ++j) { 81220282da2SJoe Wallwork if (i == j) u[i+dim*j] = user->scaling; 81320282da2SJoe Wallwork else u[i+dim*j] = 0.0; 81420282da2SJoe Wallwork } 81520282da2SJoe Wallwork } 81620282da2SJoe Wallwork return 0; 81720282da2SJoe Wallwork } 81820282da2SJoe Wallwork 81920282da2SJoe Wallwork /* 82020282da2SJoe Wallwork DMPlexMetricCreateUniform - Construct a uniform isotropic metric 82120282da2SJoe Wallwork 82220282da2SJoe Wallwork Input parameters: 82320282da2SJoe Wallwork + dm - The DM 82420282da2SJoe Wallwork . f - The field number to use 82520282da2SJoe Wallwork - alpha - Scaling parameter for the diagonal 82620282da2SJoe Wallwork 82720282da2SJoe Wallwork Output parameter: 82820282da2SJoe Wallwork . metric - The uniform metric 82920282da2SJoe Wallwork 83020282da2SJoe Wallwork Level: beginner 83120282da2SJoe Wallwork 83220282da2SJoe Wallwork Note: It is assumed that the DM is comprised of simplices. 83320282da2SJoe Wallwork 83420282da2SJoe Wallwork .seealso: DMPlexMetricCreate(), DMPlexMetricCreateIsotropic() 83520282da2SJoe Wallwork */ 83620282da2SJoe Wallwork PetscErrorCode DMPlexMetricCreateUniform(DM dm, PetscInt f, PetscReal alpha, Vec *metric) 83720282da2SJoe Wallwork { 83820282da2SJoe Wallwork DMPlexMetricUniformCtx user; 83920282da2SJoe Wallwork PetscErrorCode (*funcs[1])(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *); 84020282da2SJoe Wallwork PetscErrorCode ierr; 84120282da2SJoe Wallwork void *ctxs[1]; 84220282da2SJoe Wallwork 84320282da2SJoe Wallwork PetscFunctionBegin; 84420282da2SJoe Wallwork ierr = DMPlexMetricCreate(dm, f, metric);CHKERRQ(ierr); 84520282da2SJoe Wallwork if (!alpha) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Uniform metric scaling is undefined"); 84620282da2SJoe Wallwork if (alpha < 1.0e-30) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Uniform metric scaling %e should be positive", alpha); 84720282da2SJoe Wallwork else user.scaling = alpha; 84820282da2SJoe Wallwork funcs[0] = diagonal; 84920282da2SJoe Wallwork ctxs[0] = &user; 85020282da2SJoe Wallwork ierr = DMProjectFunctionLocal(dm, 0.0, funcs, ctxs, INSERT_ALL_VALUES, *metric);CHKERRQ(ierr); 85120282da2SJoe Wallwork PetscFunctionReturn(0); 85220282da2SJoe Wallwork } 85320282da2SJoe Wallwork 85420282da2SJoe Wallwork /* 85520282da2SJoe Wallwork DMPlexMetricCreateIsotropic - Construct an isotropic metric from an error indicator 85620282da2SJoe Wallwork 85720282da2SJoe Wallwork Input parameters: 85820282da2SJoe Wallwork + dm - The DM 85920282da2SJoe Wallwork . f - The field number to use 86020282da2SJoe Wallwork - indicator - The error indicator 86120282da2SJoe Wallwork 86220282da2SJoe Wallwork Output parameter: 86320282da2SJoe Wallwork . metric - The isotropic metric 86420282da2SJoe Wallwork 86520282da2SJoe Wallwork Level: beginner 86620282da2SJoe Wallwork 86720282da2SJoe Wallwork Notes: 86820282da2SJoe Wallwork 86920282da2SJoe Wallwork It is assumed that the DM is comprised of simplices. 87020282da2SJoe Wallwork 87120282da2SJoe Wallwork The indicator needs to be a scalar field defined at *vertices*. 87220282da2SJoe Wallwork 87320282da2SJoe Wallwork .seealso: DMPlexMetricCreate(), DMPlexMetricCreateUniform() 87420282da2SJoe Wallwork */ 87520282da2SJoe Wallwork PetscErrorCode DMPlexMetricCreateIsotropic(DM dm, PetscInt f, Vec indicator, Vec *metric) 87620282da2SJoe Wallwork { 87720282da2SJoe Wallwork DM dmIndi; 87820282da2SJoe Wallwork PetscErrorCode ierr; 87920282da2SJoe Wallwork PetscInt dim, d, vStart, vEnd, v; 88020282da2SJoe Wallwork const PetscScalar *indi; 88120282da2SJoe Wallwork PetscScalar *met; 88220282da2SJoe Wallwork 88320282da2SJoe Wallwork PetscFunctionBegin; 88420282da2SJoe Wallwork ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 88520282da2SJoe Wallwork ierr = DMPlexMetricCreate(dm, f, metric);CHKERRQ(ierr); 88620282da2SJoe Wallwork ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 88720282da2SJoe Wallwork ierr = VecGetArrayRead(indicator, &indi);CHKERRQ(ierr); 88820282da2SJoe Wallwork ierr = VecGetArrayWrite(*metric, &met);CHKERRQ(ierr); 88920282da2SJoe Wallwork ierr = VecGetDM(indicator, &dmIndi);CHKERRQ(ierr); 89020282da2SJoe Wallwork for (v = vStart; v < vEnd; ++v) { 89120282da2SJoe Wallwork PetscScalar *vindi, *vmet; 89220282da2SJoe Wallwork ierr = DMPlexPointLocalRead(dmIndi, v, indi, &vindi);CHKERRQ(ierr); 89320282da2SJoe Wallwork ierr = DMPlexPointLocalRef(dm, v, met, &vmet);CHKERRQ(ierr); 89420282da2SJoe Wallwork for (d = 0; d < dim; ++d) vmet[d*(dim+1)] = vindi[0]; 89520282da2SJoe Wallwork } 89620282da2SJoe Wallwork ierr = VecRestoreArrayWrite(*metric, &met);CHKERRQ(ierr); 89720282da2SJoe Wallwork ierr = VecRestoreArrayRead(indicator, &indi);CHKERRQ(ierr); 89820282da2SJoe Wallwork PetscFunctionReturn(0); 89920282da2SJoe Wallwork } 90020282da2SJoe Wallwork 90120282da2SJoe Wallwork static PetscErrorCode DMPlexMetricModify_Private(PetscInt dim, PetscReal h_min, PetscReal h_max, PetscReal a_max, PetscScalar Mp[]) 90220282da2SJoe Wallwork { 90320282da2SJoe Wallwork PetscErrorCode ierr; 90420282da2SJoe Wallwork PetscInt i, j, k; 90520282da2SJoe 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); 90620282da2SJoe Wallwork PetscScalar *Mpos; 90720282da2SJoe Wallwork 90820282da2SJoe Wallwork PetscFunctionBegin; 90920282da2SJoe Wallwork ierr = PetscMalloc2(dim*dim, &Mpos, dim, &eigs);CHKERRQ(ierr); 91020282da2SJoe Wallwork 91120282da2SJoe Wallwork /* Symmetrize */ 91220282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 91320282da2SJoe Wallwork Mpos[i*dim+i] = Mp[i*dim+i]; 91420282da2SJoe Wallwork for (j = i+1; j < dim; ++j) { 91520282da2SJoe Wallwork Mpos[i*dim+j] = 0.5*(Mp[i*dim+j] + Mp[j*dim+i]); 91620282da2SJoe Wallwork Mpos[j*dim+i] = Mpos[i*dim+j]; 91720282da2SJoe Wallwork } 91820282da2SJoe Wallwork } 91920282da2SJoe Wallwork 92020282da2SJoe Wallwork /* Compute eigendecomposition */ 92120282da2SJoe Wallwork { 92220282da2SJoe Wallwork PetscScalar *work; 92320282da2SJoe Wallwork PetscBLASInt lwork; 92420282da2SJoe Wallwork 92520282da2SJoe Wallwork lwork = 5*dim; 92620282da2SJoe Wallwork ierr = PetscMalloc1(5*dim, &work);CHKERRQ(ierr); 92720282da2SJoe Wallwork { 92820282da2SJoe Wallwork PetscBLASInt lierr; 92920282da2SJoe Wallwork PetscBLASInt nb; 93020282da2SJoe Wallwork 93120282da2SJoe Wallwork ierr = PetscBLASIntCast(dim, &nb);CHKERRQ(ierr); 93220282da2SJoe Wallwork ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 93320282da2SJoe Wallwork #if defined(PETSC_USE_COMPLEX) 93420282da2SJoe Wallwork { 93520282da2SJoe Wallwork PetscReal *rwork; 93620282da2SJoe Wallwork ierr = PetscMalloc1(3*dim, &rwork);CHKERRQ(ierr); 93720282da2SJoe Wallwork PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&nb,Mpos,&nb,eigs,work,&lwork,rwork,&lierr)); 93820282da2SJoe Wallwork ierr = PetscFree(rwork);CHKERRQ(ierr); 93920282da2SJoe Wallwork } 94020282da2SJoe Wallwork #else 94120282da2SJoe Wallwork PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&nb,Mpos,&nb,eigs,work,&lwork,&lierr)); 94220282da2SJoe Wallwork #endif 94320282da2SJoe Wallwork if (lierr) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in LAPACK routine %d", (int) lierr); 94420282da2SJoe Wallwork ierr = PetscFPTrapPop();CHKERRQ(ierr); 94520282da2SJoe Wallwork } 94620282da2SJoe Wallwork ierr = PetscFree(work);CHKERRQ(ierr); 94720282da2SJoe Wallwork } 94820282da2SJoe Wallwork 94920282da2SJoe Wallwork /* Reflect to positive orthant and enforce maximum and minimum size */ 95020282da2SJoe Wallwork max_eig = 0.0; 95120282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 95220282da2SJoe Wallwork eigs[i] = PetscMin(l_max, PetscMax(l_min, PetscAbsReal(eigs[i]))); 95320282da2SJoe Wallwork max_eig = PetscMax(eigs[i], max_eig); 95420282da2SJoe Wallwork } 95520282da2SJoe Wallwork 95620282da2SJoe Wallwork /* Enforce maximum anisotropy */ 95720282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 95820282da2SJoe Wallwork if (a_max > 1.0) eigs[i] = PetscMax(eigs[i], max_eig*la_min); 95920282da2SJoe Wallwork } 96020282da2SJoe Wallwork 96120282da2SJoe Wallwork /* Reconstruct Hessian */ 96220282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 96320282da2SJoe Wallwork for (j = 0; j < dim; ++j) { 96420282da2SJoe Wallwork Mp[i*dim+j] = 0.0; 96520282da2SJoe Wallwork for (k = 0; k < dim; ++k) { 96620282da2SJoe Wallwork Mp[i*dim+j] += Mpos[k*dim+i] * eigs[k] * Mpos[k*dim+j]; 96720282da2SJoe Wallwork } 96820282da2SJoe Wallwork } 96920282da2SJoe Wallwork } 97020282da2SJoe Wallwork ierr = PetscFree2(Mpos, eigs);CHKERRQ(ierr); 97120282da2SJoe Wallwork 97220282da2SJoe Wallwork PetscFunctionReturn(0); 97320282da2SJoe Wallwork } 97420282da2SJoe Wallwork 97520282da2SJoe Wallwork /* 97620282da2SJoe Wallwork DMPlexMetricEnforceSPD - Enforce symmetric positive-definiteness of a metric 97720282da2SJoe Wallwork 97820282da2SJoe Wallwork Input parameters: 97920282da2SJoe Wallwork + dm - The DM 98099abec2bSJoe Wallwork . restrictSizes - Should maximum/minimum metric magnitudes be enforced? 98199abec2bSJoe Wallwork . restrictAnisotropy - Should maximum anisotropy be enforced? 98220282da2SJoe Wallwork - metric - The metric 98320282da2SJoe Wallwork 98420282da2SJoe Wallwork Output parameter: 98520282da2SJoe Wallwork . metric - The metric 98620282da2SJoe Wallwork 98720282da2SJoe Wallwork Level: beginner 98820282da2SJoe Wallwork 98920282da2SJoe Wallwork .seealso: DMPlexMetricNormalize(), DMPlexMetricIntersection() 99020282da2SJoe Wallwork */ 99199abec2bSJoe Wallwork PetscErrorCode DMPlexMetricEnforceSPD(DM dm, PetscBool restrictSizes, PetscBool restrictAnisotropy, Vec metric) 99220282da2SJoe Wallwork { 99320282da2SJoe Wallwork PetscErrorCode ierr; 99420282da2SJoe Wallwork PetscInt dim, vStart, vEnd, v; 99520282da2SJoe Wallwork PetscScalar *met; 99620282da2SJoe Wallwork PetscReal h_min = 1.0e-30, h_max = 1.0e+30, a_max = 0.0; 99720282da2SJoe Wallwork 99820282da2SJoe Wallwork PetscFunctionBegin; 99920282da2SJoe Wallwork 100020282da2SJoe Wallwork /* Extract metadata from dm */ 100120282da2SJoe Wallwork ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 100220282da2SJoe Wallwork if (restrictSizes) { 100399abec2bSJoe Wallwork ierr = DMPlexMetricGetMinimumMagnitude(dm, &h_min);CHKERRQ(ierr); 100499abec2bSJoe Wallwork ierr = DMPlexMetricGetMaximumMagnitude(dm, &h_max);CHKERRQ(ierr); 100599abec2bSJoe Wallwork h_min = PetscMax(h_min, 1.0e-30); 100699abec2bSJoe Wallwork h_max = PetscMin(h_max, 1.0e+30); 100799abec2bSJoe Wallwork if (h_min >= h_max) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Incompatible min/max metric magnitudes (%.4e not smaller than %.4e)", h_min, h_max); 100899abec2bSJoe Wallwork } 100999abec2bSJoe Wallwork if (restrictAnisotropy) { 101099abec2bSJoe Wallwork ierr = DMPlexMetricGetMaximumAnisotropy(dm, &a_max);CHKERRQ(ierr); 101199abec2bSJoe Wallwork a_max = PetscMin(a_max, 1.0e+30); 101220282da2SJoe Wallwork } 101320282da2SJoe Wallwork 101420282da2SJoe Wallwork /* Enforce SPD */ 101520282da2SJoe Wallwork ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 101620282da2SJoe Wallwork ierr = VecGetArray(metric, &met);CHKERRQ(ierr); 101720282da2SJoe Wallwork for (v = vStart; v < vEnd; ++v) { 101820282da2SJoe Wallwork PetscScalar *vmet; 101920282da2SJoe Wallwork ierr = DMPlexPointLocalRef(dm, v, met, &vmet);CHKERRQ(ierr); 102020282da2SJoe Wallwork ierr = DMPlexMetricModify_Private(dim, h_min, h_max, a_max, vmet);CHKERRQ(ierr); 102120282da2SJoe Wallwork } 102220282da2SJoe Wallwork ierr = VecRestoreArray(metric, &met);CHKERRQ(ierr); 102320282da2SJoe Wallwork 102420282da2SJoe Wallwork PetscFunctionReturn(0); 102520282da2SJoe Wallwork } 102620282da2SJoe Wallwork 102720282da2SJoe Wallwork static void detMFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux, 102820282da2SJoe Wallwork const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 102920282da2SJoe Wallwork const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 103020282da2SJoe Wallwork PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 103120282da2SJoe Wallwork { 103220282da2SJoe Wallwork const PetscScalar p = constants[0]; 103320282da2SJoe Wallwork PetscReal detH = 0.0; 103420282da2SJoe Wallwork 103520282da2SJoe Wallwork if (dim == 2) DMPlex_Det2D_Scalar_Internal(&detH, u); 103620282da2SJoe Wallwork else if (dim == 3) DMPlex_Det3D_Scalar_Internal(&detH, u); 103720282da2SJoe Wallwork f0[0] = PetscPowReal(detH, p/(2.0*p + dim)); 103820282da2SJoe Wallwork } 103920282da2SJoe Wallwork 104020282da2SJoe Wallwork /* 104120282da2SJoe Wallwork DMPlexMetricNormalize - Apply L-p normalization to a metric 104220282da2SJoe Wallwork 104320282da2SJoe Wallwork Input parameters: 104420282da2SJoe Wallwork + dm - The DM 104520282da2SJoe Wallwork . metricIn - The unnormalized metric 104616522936SJoe Wallwork . restrictSizes - Should maximum/minimum metric magnitudes be enforced? 104716522936SJoe Wallwork - restrictAnisotropy - Should maximum metric anisotropy be enforced? 104820282da2SJoe Wallwork 104920282da2SJoe Wallwork Output parameter: 105020282da2SJoe Wallwork . metricOut - The normalized metric 105120282da2SJoe Wallwork 105220282da2SJoe Wallwork Level: beginner 105320282da2SJoe Wallwork 105420282da2SJoe Wallwork .seealso: DMPlexMetricEnforceSPD(), DMPlexMetricIntersection() 105520282da2SJoe Wallwork */ 105616522936SJoe Wallwork PetscErrorCode DMPlexMetricNormalize(DM dm, Vec metricIn, PetscBool restrictSizes, PetscBool restrictAnisotropy, Vec *metricOut) 105720282da2SJoe Wallwork { 105820282da2SJoe Wallwork MPI_Comm comm; 105916522936SJoe Wallwork PetscBool restrictAnisotropyFirst; 106020282da2SJoe Wallwork PetscDS ds; 106120282da2SJoe Wallwork PetscErrorCode ierr; 106220282da2SJoe Wallwork PetscInt dim, Nd, vStart, vEnd, v, i; 106320282da2SJoe Wallwork PetscScalar *met, integral, constants[1]; 106420282da2SJoe Wallwork PetscReal p, h_min = 1.0e-30, h_max = 1.0e+30, a_max = 0.0, factGlob, target; 106520282da2SJoe Wallwork 106620282da2SJoe Wallwork PetscFunctionBegin; 106720282da2SJoe Wallwork 106820282da2SJoe Wallwork /* Extract metadata from dm */ 106920282da2SJoe Wallwork ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 107020282da2SJoe Wallwork ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 107120282da2SJoe Wallwork Nd = dim*dim; 107220282da2SJoe Wallwork 107320282da2SJoe Wallwork /* Set up metric and ensure it is SPD */ 107420282da2SJoe Wallwork ierr = DMPlexMetricCreate(dm, 0, metricOut);CHKERRQ(ierr); 107520282da2SJoe Wallwork ierr = VecCopy(metricIn, *metricOut);CHKERRQ(ierr); 107616522936SJoe Wallwork ierr = DMPlexMetricRestrictAnisotropyFirst(dm, &restrictAnisotropyFirst);CHKERRQ(ierr); 107716522936SJoe Wallwork ierr = DMPlexMetricEnforceSPD(dm, PETSC_FALSE, (PetscBool)(restrictAnisotropy && restrictAnisotropyFirst), *metricOut);CHKERRQ(ierr); 107820282da2SJoe Wallwork 107920282da2SJoe Wallwork /* Compute global normalization factor */ 108016522936SJoe Wallwork ierr = DMPlexMetricGetTargetComplexity(dm, &target);CHKERRQ(ierr); 108116522936SJoe Wallwork ierr = DMPlexMetricGetNormalizationOrder(dm, &p);CHKERRQ(ierr); 108216522936SJoe Wallwork constants[0] = p; 108320282da2SJoe Wallwork ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 108420282da2SJoe Wallwork ierr = PetscDSSetConstants(ds, 1, constants);CHKERRQ(ierr); 108520282da2SJoe Wallwork ierr = PetscDSSetObjective(ds, 0, detMFunc);CHKERRQ(ierr); 108620282da2SJoe Wallwork ierr = DMPlexComputeIntegralFEM(dm, *metricOut, &integral, NULL);CHKERRQ(ierr); 108720282da2SJoe Wallwork factGlob = PetscPowReal(target/PetscRealPart(integral), 2.0/dim); 108820282da2SJoe Wallwork 108920282da2SJoe Wallwork /* Apply local scaling */ 109020282da2SJoe Wallwork if (restrictSizes) { 109116522936SJoe Wallwork ierr = DMPlexMetricGetMinimumMagnitude(dm, &h_min);CHKERRQ(ierr); 109216522936SJoe Wallwork ierr = DMPlexMetricGetMaximumMagnitude(dm, &h_max);CHKERRQ(ierr); 109316522936SJoe Wallwork h_min = PetscMax(h_min, 1.0e-30); 109416522936SJoe Wallwork h_max = PetscMin(h_max, 1.0e+30); 109516522936SJoe Wallwork if (h_min >= h_max) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Incompatible min/max metric magnitudes (%.4e not smaller than %.4e)", h_min, h_max); 109616522936SJoe Wallwork } 109716522936SJoe Wallwork if (restrictAnisotropy && !restrictAnisotropyFirst) { 109816522936SJoe Wallwork ierr = DMPlexMetricGetMaximumAnisotropy(dm, &a_max);CHKERRQ(ierr); 109916522936SJoe Wallwork a_max = PetscMin(a_max, 1.0e+30); 110020282da2SJoe Wallwork } 110120282da2SJoe Wallwork ierr = VecGetArray(*metricOut, &met);CHKERRQ(ierr); 110216522936SJoe Wallwork ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 110320282da2SJoe Wallwork for (v = vStart; v < vEnd; ++v) { 110420282da2SJoe Wallwork PetscScalar *Mp; 110520282da2SJoe Wallwork PetscReal detM, fact; 110620282da2SJoe Wallwork 110720282da2SJoe Wallwork ierr = DMPlexPointLocalRef(dm, v, met, &Mp);CHKERRQ(ierr); 110820282da2SJoe Wallwork if (dim == 2) DMPlex_Det2D_Scalar_Internal(&detM, Mp); 110920282da2SJoe Wallwork else if (dim == 3) DMPlex_Det3D_Scalar_Internal(&detM, Mp); 111020282da2SJoe Wallwork else SETERRQ1(comm, PETSC_ERR_SUP, "Dimension %d not supported", dim); 111120282da2SJoe Wallwork fact = factGlob * PetscPowReal(PetscAbsReal(detM), -1.0/(2*p+dim)); 111220282da2SJoe Wallwork for (i = 0; i < Nd; ++i) Mp[i] *= fact; 111320282da2SJoe Wallwork if (restrictSizes) { ierr = DMPlexMetricModify_Private(dim, h_min, h_max, a_max, Mp);CHKERRQ(ierr); } 111420282da2SJoe Wallwork } 111520282da2SJoe Wallwork ierr = VecRestoreArray(*metricOut, &met);CHKERRQ(ierr); 111620282da2SJoe Wallwork 111720282da2SJoe Wallwork PetscFunctionReturn(0); 111820282da2SJoe Wallwork } 111920282da2SJoe Wallwork 112020282da2SJoe Wallwork /* 112120282da2SJoe Wallwork DMPlexMetricAverage - Compute the average of a list of metrics 112220282da2SJoe Wallwork 112320282da2SJoe Wallwork Input Parameter: 112420282da2SJoe Wallwork + dm - The DM 112520282da2SJoe Wallwork . numMetrics - The number of metrics to be averaged 112620282da2SJoe Wallwork . weights - Weights for the average 112720282da2SJoe Wallwork - metrics - The metrics to be averaged 112820282da2SJoe Wallwork 112920282da2SJoe Wallwork Output Parameter: 113020282da2SJoe Wallwork . metricAvg - The averaged metric 113120282da2SJoe Wallwork 113220282da2SJoe Wallwork Level: beginner 113320282da2SJoe Wallwork 113420282da2SJoe Wallwork Notes: 113520282da2SJoe Wallwork The weights should sum to unity. 113620282da2SJoe Wallwork 113720282da2SJoe Wallwork If weights are not provided then an unweighted average is used. 113820282da2SJoe Wallwork 113920282da2SJoe Wallwork .seealso: DMPlexMetricAverage2(), DMPlexMetricAverage3(), DMPlexMetricIntersection() 114020282da2SJoe Wallwork */ 114120282da2SJoe Wallwork PetscErrorCode DMPlexMetricAverage(DM dm, PetscInt numMetrics, PetscReal weights[], Vec metrics[], Vec *metricAvg) 114220282da2SJoe Wallwork { 114320282da2SJoe Wallwork PetscBool haveWeights = PETSC_TRUE; 114420282da2SJoe Wallwork PetscErrorCode ierr; 114520282da2SJoe Wallwork PetscInt i; 114620282da2SJoe Wallwork PetscReal sum = 0.0, tol = 1.0e-10; 114720282da2SJoe Wallwork 114820282da2SJoe Wallwork PetscFunctionBegin; 114920282da2SJoe Wallwork if (numMetrics < 1) { SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot average %d < 1 metrics", numMetrics); } 115020282da2SJoe Wallwork ierr = DMPlexMetricCreate(dm, 0, metricAvg);CHKERRQ(ierr); 115120282da2SJoe Wallwork ierr = VecSet(*metricAvg, 0.0);CHKERRQ(ierr); 115220282da2SJoe Wallwork 115320282da2SJoe Wallwork /* Default to the unweighted case */ 115420282da2SJoe Wallwork if (!weights) { 115520282da2SJoe Wallwork ierr = PetscMalloc1(numMetrics, &weights);CHKERRQ(ierr); 115620282da2SJoe Wallwork haveWeights = PETSC_FALSE; 115720282da2SJoe Wallwork for (i = 0; i < numMetrics; ++i) {weights[i] = 1.0/numMetrics; } 115820282da2SJoe Wallwork } 115920282da2SJoe Wallwork 116020282da2SJoe Wallwork /* Check weights sum to unity */ 116120282da2SJoe Wallwork for (i = 0; i < numMetrics; ++i) { sum += weights[i]; } 116220282da2SJoe Wallwork if (PetscAbsReal(sum - 1) > tol) { SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Weights do not sum to unity"); } 116320282da2SJoe Wallwork 116420282da2SJoe Wallwork /* Compute metric average */ 116520282da2SJoe Wallwork for (i = 0; i < numMetrics; ++i) { ierr = VecAXPY(*metricAvg, weights[i], metrics[i]);CHKERRQ(ierr); } 116620282da2SJoe Wallwork if (!haveWeights) {ierr = PetscFree(weights); } 116720282da2SJoe Wallwork PetscFunctionReturn(0); 116820282da2SJoe Wallwork } 116920282da2SJoe Wallwork 117020282da2SJoe Wallwork /* 117120282da2SJoe Wallwork DMPlexMetricAverage2 - Compute the unweighted average of two metrics 117220282da2SJoe Wallwork 117320282da2SJoe Wallwork Input Parameter: 117420282da2SJoe Wallwork + dm - The DM 117520282da2SJoe Wallwork . metric1 - The first metric to be averaged 117620282da2SJoe Wallwork - metric2 - The second metric to be averaged 117720282da2SJoe Wallwork 117820282da2SJoe Wallwork Output Parameter: 117920282da2SJoe Wallwork . metricAvg - The averaged metric 118020282da2SJoe Wallwork 118120282da2SJoe Wallwork Level: beginner 118220282da2SJoe Wallwork 118320282da2SJoe Wallwork .seealso: DMPlexMetricAverage(), DMPlexMetricAverage3() 118420282da2SJoe Wallwork */ 118520282da2SJoe Wallwork PetscErrorCode DMPlexMetricAverage2(DM dm, Vec metric1, Vec metric2, Vec *metricAvg) 118620282da2SJoe Wallwork { 118720282da2SJoe Wallwork PetscErrorCode ierr; 118820282da2SJoe Wallwork PetscReal weights[2] = {0.5, 0.5}; 118920282da2SJoe Wallwork Vec metrics[2] = {metric1, metric2}; 119020282da2SJoe Wallwork 119120282da2SJoe Wallwork PetscFunctionBegin; 119220282da2SJoe Wallwork ierr = DMPlexMetricAverage(dm, 2, weights, metrics, metricAvg);CHKERRQ(ierr); 119320282da2SJoe Wallwork PetscFunctionReturn(0); 119420282da2SJoe Wallwork } 119520282da2SJoe Wallwork 119620282da2SJoe Wallwork /* 119720282da2SJoe Wallwork DMPlexMetricAverage3 - Compute the unweighted average of three metrics 119820282da2SJoe Wallwork 119920282da2SJoe Wallwork Input Parameter: 120020282da2SJoe Wallwork + dm - The DM 120120282da2SJoe Wallwork . metric1 - The first metric to be averaged 120220282da2SJoe Wallwork . metric2 - The second metric to be averaged 120320282da2SJoe Wallwork - metric3 - The third metric to be averaged 120420282da2SJoe Wallwork 120520282da2SJoe Wallwork Output Parameter: 120620282da2SJoe Wallwork . metricAvg - The averaged metric 120720282da2SJoe Wallwork 120820282da2SJoe Wallwork Level: beginner 120920282da2SJoe Wallwork 121020282da2SJoe Wallwork .seealso: DMPlexMetricAverage(), DMPlexMetricAverage2() 121120282da2SJoe Wallwork */ 121220282da2SJoe Wallwork PetscErrorCode DMPlexMetricAverage3(DM dm, Vec metric1, Vec metric2, Vec metric3, Vec *metricAvg) 121320282da2SJoe Wallwork { 121420282da2SJoe Wallwork PetscErrorCode ierr; 121520282da2SJoe Wallwork PetscReal weights[3] = {1.0/3.0, 1.0/3.0, 1.0/3.0}; 121620282da2SJoe Wallwork Vec metrics[3] = {metric1, metric2, metric3}; 121720282da2SJoe Wallwork 121820282da2SJoe Wallwork PetscFunctionBegin; 121920282da2SJoe Wallwork ierr = DMPlexMetricAverage(dm, 3, weights, metrics, metricAvg);CHKERRQ(ierr); 122020282da2SJoe Wallwork PetscFunctionReturn(0); 122120282da2SJoe Wallwork } 122220282da2SJoe Wallwork 122320282da2SJoe Wallwork static PetscErrorCode DMPlexMetricIntersection_Private(PetscInt dim, PetscScalar M1[], PetscScalar M2[]) 122420282da2SJoe Wallwork { 122520282da2SJoe Wallwork PetscErrorCode ierr; 122620282da2SJoe Wallwork PetscInt i, j, k, l, m; 122720282da2SJoe Wallwork PetscReal *evals, *evals1; 122820282da2SJoe Wallwork PetscScalar *evecs, *sqrtM1, *isqrtM1; 122920282da2SJoe Wallwork 123020282da2SJoe Wallwork PetscFunctionBegin; 123120282da2SJoe Wallwork ierr = PetscMalloc5(dim*dim, &evecs, dim*dim, &sqrtM1, dim*dim, &isqrtM1, dim, &evals, dim, &evals1);CHKERRQ(ierr); 123220282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 123320282da2SJoe Wallwork for (j = 0; j < dim; ++j) { 123420282da2SJoe Wallwork evecs[i*dim+j] = M1[i*dim+j]; 123520282da2SJoe Wallwork } 123620282da2SJoe Wallwork } 123720282da2SJoe Wallwork { 123820282da2SJoe Wallwork PetscScalar *work; 123920282da2SJoe Wallwork PetscBLASInt lwork; 124020282da2SJoe Wallwork 124120282da2SJoe Wallwork lwork = 5*dim; 124220282da2SJoe Wallwork ierr = PetscMalloc1(5*dim, &work);CHKERRQ(ierr); 124320282da2SJoe Wallwork { 124420282da2SJoe Wallwork PetscBLASInt lierr, nb; 124520282da2SJoe Wallwork PetscReal sqrtk; 124620282da2SJoe Wallwork 124720282da2SJoe Wallwork /* Compute eigendecomposition of M1 */ 124820282da2SJoe Wallwork ierr = PetscBLASIntCast(dim, &nb);CHKERRQ(ierr); 124920282da2SJoe Wallwork ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 125020282da2SJoe Wallwork #if defined(PETSC_USE_COMPLEX) 125120282da2SJoe Wallwork { 125220282da2SJoe Wallwork PetscReal *rwork; 125320282da2SJoe Wallwork ierr = PetscMalloc1(3*dim, &rwork);CHKERRQ(ierr); 125420282da2SJoe Wallwork PetscStackCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &nb, evecs, &nb, evals1, work, &lwork, rwork, &lierr)); 125520282da2SJoe Wallwork ierr = PetscFree(rwork);CHKERRQ(ierr); 125620282da2SJoe Wallwork } 125720282da2SJoe Wallwork #else 125820282da2SJoe Wallwork PetscStackCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &nb, evecs, &nb, evals1, work, &lwork, &lierr)); 125920282da2SJoe Wallwork #endif 126020282da2SJoe Wallwork if (lierr) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in LAPACK routine %d", (int) lierr); 126120282da2SJoe Wallwork ierr = PetscFPTrapPop(); 126220282da2SJoe Wallwork 126320282da2SJoe Wallwork /* Compute square root and reciprocal */ 126420282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 126520282da2SJoe Wallwork for (j = 0; j < dim; ++j) { 126620282da2SJoe Wallwork sqrtM1[i*dim+j] = 0.0; 126720282da2SJoe Wallwork isqrtM1[i*dim+j] = 0.0; 126820282da2SJoe Wallwork for (k = 0; k < dim; ++k) { 126920282da2SJoe Wallwork sqrtk = PetscSqrtReal(evals1[k]); 127020282da2SJoe Wallwork sqrtM1[i*dim+j] += evecs[k*dim+i] * sqrtk * evecs[k*dim+j]; 127120282da2SJoe Wallwork isqrtM1[i*dim+j] += evecs[k*dim+i] * (1.0/sqrtk) * evecs[k*dim+j]; 127220282da2SJoe Wallwork } 127320282da2SJoe Wallwork } 127420282da2SJoe Wallwork } 127520282da2SJoe Wallwork 127620282da2SJoe Wallwork /* Map into the space spanned by the eigenvectors of M1 */ 127720282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 127820282da2SJoe Wallwork for (j = 0; j < dim; ++j) { 127920282da2SJoe Wallwork evecs[i*dim+j] = 0.0; 128020282da2SJoe Wallwork for (k = 0; k < dim; ++k) { 128120282da2SJoe Wallwork for (l = 0; l < dim; ++l) { 128220282da2SJoe Wallwork evecs[i*dim+j] += isqrtM1[i*dim+k] * M2[l*dim+k] * isqrtM1[j*dim+l]; 128320282da2SJoe Wallwork } 128420282da2SJoe Wallwork } 128520282da2SJoe Wallwork } 128620282da2SJoe Wallwork } 128720282da2SJoe Wallwork 128820282da2SJoe Wallwork /* Compute eigendecomposition */ 128920282da2SJoe Wallwork ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 129020282da2SJoe Wallwork #if defined(PETSC_USE_COMPLEX) 129120282da2SJoe Wallwork { 129220282da2SJoe Wallwork PetscReal *rwork; 129320282da2SJoe Wallwork ierr = PetscMalloc1(3*dim, &rwork);CHKERRQ(ierr); 129420282da2SJoe Wallwork PetscStackCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &nb, evecs, &nb, evals, work, &lwork, rwork, &lierr)); 129520282da2SJoe Wallwork ierr = PetscFree(rwork);CHKERRQ(ierr); 129620282da2SJoe Wallwork } 129720282da2SJoe Wallwork #else 129820282da2SJoe Wallwork PetscStackCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &nb, evecs, &nb, evals, work, &lwork, &lierr)); 129920282da2SJoe Wallwork #endif 130020282da2SJoe Wallwork if (lierr) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in LAPACK routine %d", (int) lierr); 130120282da2SJoe Wallwork ierr = PetscFPTrapPop(); 130220282da2SJoe Wallwork 130320282da2SJoe Wallwork /* Modify eigenvalues */ 130420282da2SJoe Wallwork for (i = 0; i < dim; ++i) evals[i] = PetscMin(evals[i], evals1[i]); 130520282da2SJoe Wallwork 130620282da2SJoe Wallwork /* Map back to get the intersection */ 130720282da2SJoe Wallwork for (i = 0; i < dim; ++i) { 130820282da2SJoe Wallwork for (j = 0; j < dim; ++j) { 130920282da2SJoe Wallwork M2[i*dim+j] = 0.0; 131020282da2SJoe Wallwork for (k = 0; k < dim; ++k) { 131120282da2SJoe Wallwork for (l = 0; l < dim; ++l) { 131220282da2SJoe Wallwork for (m = 0; m < dim; ++m) { 131320282da2SJoe Wallwork M2[i*dim+j] += sqrtM1[i*dim+k] * evecs[l*dim+k] * evals[l] * evecs[l*dim+m] * sqrtM1[j*dim+m]; 131420282da2SJoe Wallwork } 131520282da2SJoe Wallwork } 131620282da2SJoe Wallwork } 131720282da2SJoe Wallwork } 131820282da2SJoe Wallwork } 131920282da2SJoe Wallwork } 132020282da2SJoe Wallwork ierr = PetscFree(work);CHKERRQ(ierr); 132120282da2SJoe Wallwork } 132220282da2SJoe Wallwork ierr = PetscFree5(evecs, sqrtM1, isqrtM1, evals, evals1);CHKERRQ(ierr); 132320282da2SJoe Wallwork PetscFunctionReturn(0); 132420282da2SJoe Wallwork } 132520282da2SJoe Wallwork 132620282da2SJoe Wallwork /* 132720282da2SJoe Wallwork DMPlexMetricIntersection - Compute the intersection of a list of metrics 132820282da2SJoe Wallwork 132920282da2SJoe Wallwork Input Parameter: 133020282da2SJoe Wallwork + dm - The DM 133120282da2SJoe Wallwork . numMetrics - The number of metrics to be intersected 133220282da2SJoe Wallwork - metrics - The metrics to be intersected 133320282da2SJoe Wallwork 133420282da2SJoe Wallwork Output Parameter: 133520282da2SJoe Wallwork . metricInt - The intersected metric 133620282da2SJoe Wallwork 133720282da2SJoe Wallwork Level: beginner 133820282da2SJoe Wallwork 133920282da2SJoe Wallwork Notes: 134020282da2SJoe Wallwork 134120282da2SJoe Wallwork The intersection of a list of metrics has the maximal ellipsoid which fits within the ellipsoids of the component metrics. 134220282da2SJoe Wallwork 134320282da2SJoe Wallwork The implementation used here is only consistent with the maximal ellipsoid definition in the case numMetrics = 2. 134420282da2SJoe Wallwork 134520282da2SJoe Wallwork .seealso: DMPlexMetricIntersection2(), DMPlexMetricIntersection3(), DMPlexMetricAverage() 134620282da2SJoe Wallwork */ 134720282da2SJoe Wallwork PetscErrorCode DMPlexMetricIntersection(DM dm, PetscInt numMetrics, Vec metrics[], Vec *metricInt) 134820282da2SJoe Wallwork { 134920282da2SJoe Wallwork PetscErrorCode ierr; 135020282da2SJoe Wallwork PetscInt dim, vStart, vEnd, v, i; 135120282da2SJoe Wallwork PetscScalar *met, *meti, *M, *Mi; 135220282da2SJoe Wallwork 135320282da2SJoe Wallwork PetscFunctionBegin; 135420282da2SJoe Wallwork if (numMetrics < 1) { SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot intersect %d < 1 metrics", numMetrics); } 135520282da2SJoe Wallwork 135620282da2SJoe Wallwork /* Extract metadata from dm */ 135720282da2SJoe Wallwork ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 135820282da2SJoe Wallwork ierr = DMPlexMetricCreate(dm, 0, metricInt);CHKERRQ(ierr); 135920282da2SJoe Wallwork ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 136020282da2SJoe Wallwork 136120282da2SJoe Wallwork /* Copy over the first metric */ 136220282da2SJoe Wallwork ierr = VecCopy(metrics[0], *metricInt);CHKERRQ(ierr); 136320282da2SJoe Wallwork 136420282da2SJoe Wallwork /* Intersect subsequent metrics in turn */ 136520282da2SJoe Wallwork if (numMetrics > 1) { 136620282da2SJoe Wallwork ierr = VecGetArray(*metricInt, &met);CHKERRQ(ierr); 136720282da2SJoe Wallwork for (i = 1; i < numMetrics; ++i) { 136820282da2SJoe Wallwork ierr = VecGetArray(metrics[i], &meti);CHKERRQ(ierr); 136920282da2SJoe Wallwork for (v = vStart; v < vEnd; ++v) { 137020282da2SJoe Wallwork ierr = DMPlexPointLocalRef(dm, v, met, &M);CHKERRQ(ierr); 137120282da2SJoe Wallwork ierr = DMPlexPointLocalRef(dm, v, meti, &Mi);CHKERRQ(ierr); 137220282da2SJoe Wallwork ierr = DMPlexMetricIntersection_Private(dim, Mi, M);CHKERRQ(ierr); 137320282da2SJoe Wallwork } 137420282da2SJoe Wallwork ierr = VecRestoreArray(metrics[i], &meti);CHKERRQ(ierr); 137520282da2SJoe Wallwork } 137620282da2SJoe Wallwork ierr = VecRestoreArray(*metricInt, &met);CHKERRQ(ierr); 137720282da2SJoe Wallwork } 137820282da2SJoe Wallwork 137920282da2SJoe Wallwork PetscFunctionReturn(0); 138020282da2SJoe Wallwork } 138120282da2SJoe Wallwork 138220282da2SJoe Wallwork /* 138320282da2SJoe Wallwork DMPlexMetricIntersection2 - Compute the intersection of two metrics 138420282da2SJoe Wallwork 138520282da2SJoe Wallwork Input Parameter: 138620282da2SJoe Wallwork + dm - The DM 138720282da2SJoe Wallwork . metric1 - The first metric to be intersected 138820282da2SJoe Wallwork - metric2 - The second metric to be intersected 138920282da2SJoe Wallwork 139020282da2SJoe Wallwork Output Parameter: 139120282da2SJoe Wallwork . metricInt - The intersected metric 139220282da2SJoe Wallwork 139320282da2SJoe Wallwork Level: beginner 139420282da2SJoe Wallwork 139520282da2SJoe Wallwork .seealso: DMPlexMetricIntersection(), DMPlexMetricIntersection3() 139620282da2SJoe Wallwork */ 139720282da2SJoe Wallwork PetscErrorCode DMPlexMetricIntersection2(DM dm, Vec metric1, Vec metric2, Vec *metricInt) 139820282da2SJoe Wallwork { 139920282da2SJoe Wallwork PetscErrorCode ierr; 140020282da2SJoe Wallwork Vec metrics[2] = {metric1, metric2}; 140120282da2SJoe Wallwork 140220282da2SJoe Wallwork PetscFunctionBegin; 140320282da2SJoe Wallwork ierr = DMPlexMetricIntersection(dm, 2, metrics, metricInt);CHKERRQ(ierr); 140420282da2SJoe Wallwork PetscFunctionReturn(0); 140520282da2SJoe Wallwork } 140620282da2SJoe Wallwork 140720282da2SJoe Wallwork /* 140820282da2SJoe Wallwork DMPlexMetricIntersection3 - Compute the intersection of three metrics 140920282da2SJoe Wallwork 141020282da2SJoe Wallwork Input Parameter: 141120282da2SJoe Wallwork + dm - The DM 141220282da2SJoe Wallwork . metric1 - The first metric to be intersected 141320282da2SJoe Wallwork . metric2 - The second metric to be intersected 141420282da2SJoe Wallwork - metric3 - The third metric to be intersected 141520282da2SJoe Wallwork 141620282da2SJoe Wallwork Output Parameter: 141720282da2SJoe Wallwork . metricInt - The intersected metric 141820282da2SJoe Wallwork 141920282da2SJoe Wallwork Level: beginner 142020282da2SJoe Wallwork 142120282da2SJoe Wallwork .seealso: DMPlexMetricIntersection(), DMPlexMetricIntersection2() 142220282da2SJoe Wallwork */ 142320282da2SJoe Wallwork PetscErrorCode DMPlexMetricIntersection3(DM dm, Vec metric1, Vec metric2, Vec metric3, Vec *metricInt) 142420282da2SJoe Wallwork { 142520282da2SJoe Wallwork PetscErrorCode ierr; 142620282da2SJoe Wallwork Vec metrics[3] = {metric1, metric2, metric3}; 142720282da2SJoe Wallwork 142820282da2SJoe Wallwork PetscFunctionBegin; 142920282da2SJoe Wallwork ierr = DMPlexMetricIntersection(dm, 3, metrics, metricInt);CHKERRQ(ierr); 143020282da2SJoe Wallwork PetscFunctionReturn(0); 143120282da2SJoe Wallwork } 1432