1 #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/ 2 /*@ 3 PetscSpaceSumGetNumSubspaces - Get the number of spaces in the sum 4 5 Input Parameter: 6 . sp - the function space object 7 8 Output Parameter: 9 . numSumSpaces - the number of spaces 10 11 Level: intermediate 12 13 .seealso: `PetscSpaceSumSetNumSubspaces()`, `PetscSpaceSetDegree()`, `PetscSpaceSetNumVariables()` 14 @*/ 15 PetscErrorCode PetscSpaceSumGetNumSubspaces(PetscSpace sp, PetscInt *numSumSpaces) { 16 PetscFunctionBegin; 17 PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1); 18 PetscValidIntPointer(numSumSpaces, 2); 19 PetscTryMethod(sp, "PetscSpaceSumGetNumSubspaces_C", (PetscSpace, PetscInt *), (sp, numSumSpaces)); 20 PetscFunctionReturn(0); 21 } 22 23 /*@ 24 PetscSpaceSumSetNumSubspaces - Set the number of spaces in the sum 25 26 Input Parameters: 27 + sp - the function space object 28 - numSumSpaces - the number of spaces 29 30 Level: intermediate 31 32 .seealso: `PetscSpaceSumGetNumSubspaces()`, `PetscSpaceSetDegree()`, `PetscSpaceSetNumVariables()` 33 @*/ 34 PetscErrorCode PetscSpaceSumSetNumSubspaces(PetscSpace sp, PetscInt numSumSpaces) { 35 PetscFunctionBegin; 36 PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1); 37 PetscTryMethod(sp, "PetscSpaceSumSetNumSubspaces_C", (PetscSpace, PetscInt), (sp, numSumSpaces)); 38 PetscFunctionReturn(0); 39 } 40 41 /*@ 42 PetscSpaceSumGetConcatenate - Get the concatenate flag for this space. 43 A concatenated sum space will have number of components equal to the sum of the number of components of all subspaces.A non-concatenated, 44 or direct sum space will have the same number of components as its subspaces . 45 46 Input Parameters: 47 . sp - the function space object 48 49 Output Parameters: 50 . concatenate - flag indicating whether subspaces are concatenated. 51 52 Level: intermediate 53 54 .seealso: `PetscSpaceSumSetConcatenate()` 55 @*/ 56 PetscErrorCode PetscSpaceSumGetConcatenate(PetscSpace sp, PetscBool *concatenate) { 57 PetscFunctionBegin; 58 PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1); 59 PetscTryMethod(sp, "PetscSpaceSumGetConcatenate_C", (PetscSpace, PetscBool *), (sp, concatenate)); 60 PetscFunctionReturn(0); 61 } 62 63 /*@ 64 PetscSpaceSumSetConcatenate - Sets the concatenate flag for this space. 65 A concatenated sum space will have number of components equal to the sum of the number of components of all subspaces.A non-concatenated, 66 or direct sum space will have the same number of components as its subspaces . 67 68 Input Parameters: 69 + sp - the function space object 70 - concatenate - are subspaces concatenated components (true) or direct summands (false) 71 72 Level: intermediate 73 .seealso: `PetscSpaceSumGetConcatenate()` 74 @*/ 75 PetscErrorCode PetscSpaceSumSetConcatenate(PetscSpace sp, PetscBool concatenate) { 76 PetscFunctionBegin; 77 PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1); 78 PetscTryMethod(sp, "PetscSpaceSumSetConcatenate_C", (PetscSpace, PetscBool), (sp, concatenate)); 79 PetscFunctionReturn(0); 80 } 81 82 /*@ 83 PetscSpaceSumGetSubspace - Get a space in the sum 84 85 Input Parameters: 86 + sp - the function space object 87 - s - The space number 88 89 Output Parameter: 90 . subsp - the PetscSpace 91 92 Level: intermediate 93 94 .seealso: `PetscSpaceSumSetSubspace()`, `PetscSpaceSetDegree()`, `PetscSpaceSetNumVariables()` 95 @*/ 96 PetscErrorCode PetscSpaceSumGetSubspace(PetscSpace sp, PetscInt s, PetscSpace *subsp) { 97 PetscFunctionBegin; 98 PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1); 99 PetscValidPointer(subsp, 3); 100 PetscTryMethod(sp, "PetscSpaceSumGetSubspace_C", (PetscSpace, PetscInt, PetscSpace *), (sp, s, subsp)); 101 PetscFunctionReturn(0); 102 } 103 104 /*@ 105 PetscSpaceSumSetSubspace - Set a space in the sum 106 107 Input Parameters: 108 + sp - the function space object 109 . s - The space number 110 - subsp - the number of spaces 111 112 Level: intermediate 113 114 .seealso: `PetscSpaceSumGetSubspace()`, `PetscSpaceSetDegree()`, `PetscSpaceSetNumVariables()` 115 @*/ 116 PetscErrorCode PetscSpaceSumSetSubspace(PetscSpace sp, PetscInt s, PetscSpace subsp) { 117 PetscFunctionBegin; 118 PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1); 119 if (subsp) PetscValidHeaderSpecific(subsp, PETSCSPACE_CLASSID, 3); 120 PetscTryMethod(sp, "PetscSpaceSumSetSubspace_C", (PetscSpace, PetscInt, PetscSpace), (sp, s, subsp)); 121 PetscFunctionReturn(0); 122 } 123 124 static PetscErrorCode PetscSpaceSumGetNumSubspaces_Sum(PetscSpace space, PetscInt *numSumSpaces) { 125 PetscSpace_Sum *sum = (PetscSpace_Sum *)space->data; 126 127 PetscFunctionBegin; 128 *numSumSpaces = sum->numSumSpaces; 129 PetscFunctionReturn(0); 130 } 131 132 static PetscErrorCode PetscSpaceSumSetNumSubspaces_Sum(PetscSpace space, PetscInt numSumSpaces) { 133 PetscSpace_Sum *sum = (PetscSpace_Sum *)space->data; 134 PetscInt Ns = sum->numSumSpaces; 135 136 PetscFunctionBegin; 137 PetscCheck(!sum->setupCalled, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_WRONGSTATE, "Cannot change number of subspaces after setup called"); 138 if (numSumSpaces == Ns) PetscFunctionReturn(0); 139 if (Ns >= 0) { 140 PetscInt s; 141 for (s = 0; s < Ns; ++s) { PetscCall(PetscSpaceDestroy(&sum->sumspaces[s])); } 142 PetscCall(PetscFree(sum->sumspaces)); 143 } 144 145 Ns = sum->numSumSpaces = numSumSpaces; 146 PetscCall(PetscCalloc1(Ns, &sum->sumspaces)); 147 PetscFunctionReturn(0); 148 } 149 150 static PetscErrorCode PetscSpaceSumGetConcatenate_Sum(PetscSpace sp, PetscBool *concatenate) { 151 PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data; 152 153 PetscFunctionBegin; 154 *concatenate = sum->concatenate; 155 PetscFunctionReturn(0); 156 } 157 158 static PetscErrorCode PetscSpaceSumSetConcatenate_Sum(PetscSpace sp, PetscBool concatenate) { 159 PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data; 160 161 PetscFunctionBegin; 162 PetscCheck(!sum->setupCalled, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change space concatenation after setup called."); 163 164 sum->concatenate = concatenate; 165 PetscFunctionReturn(0); 166 } 167 168 static PetscErrorCode PetscSpaceSumGetSubspace_Sum(PetscSpace space, PetscInt s, PetscSpace *subspace) { 169 PetscSpace_Sum *sum = (PetscSpace_Sum *)space->data; 170 PetscInt Ns = sum->numSumSpaces; 171 172 PetscFunctionBegin; 173 PetscCheck(Ns >= 0, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_WRONGSTATE, "Must call PetscSpaceSumSetNumSubspaces() first"); 174 PetscCheck(s >= 0 && s < Ns, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_OUTOFRANGE, "Invalid subspace number %" PetscInt_FMT, s); 175 176 *subspace = sum->sumspaces[s]; 177 PetscFunctionReturn(0); 178 } 179 180 static PetscErrorCode PetscSpaceSumSetSubspace_Sum(PetscSpace space, PetscInt s, PetscSpace subspace) { 181 PetscSpace_Sum *sum = (PetscSpace_Sum *)space->data; 182 PetscInt Ns = sum->numSumSpaces; 183 184 PetscFunctionBegin; 185 PetscCheck(!sum->setupCalled, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_WRONGSTATE, "Cannot change subspace after setup called"); 186 PetscCheck(Ns >= 0, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_WRONGSTATE, "Must call PetscSpaceSumSetNumSubspaces() first"); 187 PetscCheck(s >= 0 && s < Ns, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_OUTOFRANGE, "Invalid subspace number %" PetscInt_FMT, s); 188 189 PetscCall(PetscObjectReference((PetscObject)subspace)); 190 PetscCall(PetscSpaceDestroy(&sum->sumspaces[s])); 191 sum->sumspaces[s] = subspace; 192 PetscFunctionReturn(0); 193 } 194 195 static PetscErrorCode PetscSpaceSetFromOptions_Sum(PetscSpace sp, PetscOptionItems *PetscOptionsObject) { 196 PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data; 197 PetscInt Ns, Nc, Nv, deg, i; 198 PetscBool concatenate = PETSC_TRUE; 199 const char *prefix; 200 201 PetscFunctionBegin; 202 PetscCall(PetscSpaceGetNumVariables(sp, &Nv)); 203 if (!Nv) PetscFunctionReturn(0); 204 PetscCall(PetscSpaceGetNumComponents(sp, &Nc)); 205 PetscCall(PetscSpaceSumGetNumSubspaces(sp, &Ns)); 206 PetscCall(PetscSpaceGetDegree(sp, °, NULL)); 207 Ns = (Ns == PETSC_DEFAULT) ? 1 : Ns; 208 209 PetscOptionsHeadBegin(PetscOptionsObject, "PetscSpace sum options"); 210 PetscCall(PetscOptionsBoundedInt("-petscspace_sum_spaces", "The number of subspaces", "PetscSpaceSumSetNumSubspaces", Ns, &Ns, NULL, 0)); 211 PetscCall(PetscOptionsBool("-petscspace_sum_concatenate", "Subspaces are concatenated components of the final space", "PetscSpaceSumSetFromOptions", concatenate, &concatenate, NULL)); 212 PetscOptionsHeadEnd(); 213 214 PetscCheck(Ns >= 0 && (Nv <= 0 || Ns != 0), PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a sum space of %" PetscInt_FMT " spaces", Ns); 215 if (Ns != sum->numSumSpaces) { PetscCall(PetscSpaceSumSetNumSubspaces(sp, Ns)); } 216 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)sp, &prefix)); 217 for (i = 0; i < Ns; ++i) { 218 PetscInt sNv; 219 PetscSpace subspace; 220 221 PetscCall(PetscSpaceSumGetSubspace(sp, i, &subspace)); 222 if (!subspace) { 223 char subspacePrefix[256]; 224 225 PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)sp), &subspace)); 226 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)subspace, prefix)); 227 PetscCall(PetscSNPrintf(subspacePrefix, 256, "sumcomp_%" PetscInt_FMT "_", i)); 228 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)subspace, subspacePrefix)); 229 } else PetscCall(PetscObjectReference((PetscObject)subspace)); 230 PetscCall(PetscSpaceSetFromOptions(subspace)); 231 PetscCall(PetscSpaceGetNumVariables(subspace, &sNv)); 232 PetscCheck(sNv, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Subspace %" PetscInt_FMT " has not been set properly, number of variables is 0.", i); 233 PetscCall(PetscSpaceSumSetSubspace(sp, i, subspace)); 234 PetscCall(PetscSpaceDestroy(&subspace)); 235 } 236 PetscFunctionReturn(0); 237 } 238 239 static PetscErrorCode PetscSpaceSetUp_Sum(PetscSpace sp) { 240 PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data; 241 PetscBool concatenate = PETSC_TRUE; 242 PetscBool uniform; 243 PetscInt Nv, Ns, Nc, i, sum_Nc = 0, deg = PETSC_MAX_INT, maxDeg = PETSC_MIN_INT; 244 PetscInt minNc, maxNc; 245 246 PetscFunctionBegin; 247 if (sum->setupCalled) PetscFunctionReturn(0); 248 249 PetscCall(PetscSpaceGetNumVariables(sp, &Nv)); 250 PetscCall(PetscSpaceGetNumComponents(sp, &Nc)); 251 PetscCall(PetscSpaceSumGetNumSubspaces(sp, &Ns)); 252 if (Ns == PETSC_DEFAULT) { 253 Ns = 1; 254 PetscCall(PetscSpaceSumSetNumSubspaces(sp, Ns)); 255 } 256 PetscCheck(Ns >= 0, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have %" PetscInt_FMT " subspaces", Ns); 257 uniform = PETSC_TRUE; 258 if (Ns) { 259 PetscSpace s0; 260 261 PetscCall(PetscSpaceSumGetSubspace(sp, 0, &s0)); 262 for (PetscInt i = 1; i < Ns; i++) { 263 PetscSpace si; 264 265 PetscCall(PetscSpaceSumGetSubspace(sp, i, &si)); 266 if (si != s0) { 267 uniform = PETSC_FALSE; 268 break; 269 } 270 } 271 } 272 273 minNc = Nc; 274 maxNc = Nc; 275 for (i = 0; i < Ns; ++i) { 276 PetscInt sNv, sNc, iDeg, iMaxDeg; 277 PetscSpace si; 278 279 PetscCall(PetscSpaceSumGetSubspace(sp, i, &si)); 280 PetscCall(PetscSpaceSetUp(si)); 281 PetscCall(PetscSpaceGetNumVariables(si, &sNv)); 282 PetscCheck(sNv == Nv, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Subspace %" PetscInt_FMT " has %" PetscInt_FMT " variables, space has %" PetscInt_FMT ".", i, sNv, Nv); 283 PetscCall(PetscSpaceGetNumComponents(si, &sNc)); 284 if (i == 0 && sNc == Nc) concatenate = PETSC_FALSE; 285 minNc = PetscMin(minNc, sNc); 286 maxNc = PetscMax(maxNc, sNc); 287 sum_Nc += sNc; 288 PetscCall(PetscSpaceSumGetSubspace(sp, i, &si)); 289 PetscCall(PetscSpaceGetDegree(si, &iDeg, &iMaxDeg)); 290 deg = PetscMin(deg, iDeg); 291 maxDeg = PetscMax(maxDeg, iMaxDeg); 292 } 293 294 if (concatenate) PetscCheck(sum_Nc == Nc, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Total number of subspace components (%" PetscInt_FMT ") does not match number of target space components (%" PetscInt_FMT ").", sum_Nc, Nc); 295 else PetscCheck(minNc == Nc && maxNc == Nc, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Subspaces must have same number of components as the target space."); 296 297 sp->degree = deg; 298 sp->maxDegree = maxDeg; 299 sum->concatenate = concatenate; 300 sum->uniform = uniform; 301 sum->setupCalled = PETSC_TRUE; 302 PetscFunctionReturn(0); 303 } 304 305 static PetscErrorCode PetscSpaceSumView_Ascii(PetscSpace sp, PetscViewer v) { 306 PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data; 307 PetscBool concatenate = sum->concatenate; 308 PetscInt i, Ns = sum->numSumSpaces; 309 310 PetscFunctionBegin; 311 if (concatenate) PetscCall(PetscViewerASCIIPrintf(v, "Sum space of %" PetscInt_FMT " concatenated subspaces%s\n", Ns, sum->uniform ? " (all identical)" : "")); 312 else PetscCall(PetscViewerASCIIPrintf(v, "Sum space of %" PetscInt_FMT " subspaces%s\n", Ns, sum->uniform ? " (all identical)" : "")); 313 for (i = 0; i < (sum->uniform ? (Ns > 0 ? 1 : 0) : Ns); ++i) { 314 PetscCall(PetscViewerASCIIPushTab(v)); 315 PetscCall(PetscSpaceView(sum->sumspaces[i], v)); 316 PetscCall(PetscViewerASCIIPopTab(v)); 317 } 318 PetscFunctionReturn(0); 319 } 320 321 static PetscErrorCode PetscSpaceView_Sum(PetscSpace sp, PetscViewer viewer) { 322 PetscBool iascii; 323 324 PetscFunctionBegin; 325 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 326 if (iascii) PetscCall(PetscSpaceSumView_Ascii(sp, viewer)); 327 PetscFunctionReturn(0); 328 } 329 330 static PetscErrorCode PetscSpaceDestroy_Sum(PetscSpace sp) { 331 PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data; 332 PetscInt i, Ns = sum->numSumSpaces; 333 334 PetscFunctionBegin; 335 for (i = 0; i < Ns; ++i) { PetscCall(PetscSpaceDestroy(&sum->sumspaces[i])); } 336 PetscCall(PetscFree(sum->sumspaces)); 337 if (sum->heightsubspaces) { 338 PetscInt d; 339 340 /* sp->Nv is the spatial dimension, so it is equal to the number 341 * of subspaces on higher co-dimension points */ 342 for (d = 0; d < sp->Nv; ++d) { PetscCall(PetscSpaceDestroy(&sum->heightsubspaces[d])); } 343 } 344 PetscCall(PetscFree(sum->heightsubspaces)); 345 PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetSubspace_C", NULL)); 346 PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetSubspace_C", NULL)); 347 PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetNumSubspaces_C", NULL)); 348 PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetNumSubspaces_C", NULL)); 349 PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetConcatenate_C", NULL)); 350 PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetConcatenate_C", NULL)); 351 PetscCall(PetscFree(sum)); 352 PetscFunctionReturn(0); 353 } 354 355 static PetscErrorCode PetscSpaceGetDimension_Sum(PetscSpace sp, PetscInt *dim) { 356 PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data; 357 PetscInt i, d = 0, Ns = sum->numSumSpaces; 358 359 PetscFunctionBegin; 360 if (!sum->setupCalled) { 361 PetscCall(PetscSpaceSetUp(sp)); 362 PetscCall(PetscSpaceGetDimension(sp, dim)); 363 PetscFunctionReturn(0); 364 } 365 366 for (i = 0; i < Ns; ++i) { 367 PetscInt id; 368 369 PetscCall(PetscSpaceGetDimension(sum->sumspaces[i], &id)); 370 d += id; 371 } 372 373 *dim = d; 374 PetscFunctionReturn(0); 375 } 376 377 static PetscErrorCode PetscSpaceEvaluate_Sum(PetscSpace sp, PetscInt npoints, const PetscReal points[], PetscReal B[], PetscReal D[], PetscReal H[]) { 378 PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data; 379 PetscBool concatenate = sum->concatenate; 380 DM dm = sp->dm; 381 PetscInt Nc = sp->Nc, Nv = sp->Nv, Ns = sum->numSumSpaces; 382 PetscInt i, s, offset, ncoffset, pdimfull, numelB, numelD, numelH; 383 PetscReal *sB = NULL, *sD = NULL, *sH = NULL; 384 385 PetscFunctionBegin; 386 if (!sum->setupCalled) { 387 PetscCall(PetscSpaceSetUp(sp)); 388 PetscCall(PetscSpaceEvaluate(sp, npoints, points, B, D, H)); 389 PetscFunctionReturn(0); 390 } 391 PetscCall(PetscSpaceGetDimension(sp, &pdimfull)); 392 numelB = npoints * pdimfull * Nc; 393 numelD = numelB * Nv; 394 numelH = numelD * Nv; 395 if (B || D || H) { PetscCall(DMGetWorkArray(dm, numelB, MPIU_REAL, &sB)); } 396 if (D || H) { PetscCall(DMGetWorkArray(dm, numelD, MPIU_REAL, &sD)); } 397 if (H) { PetscCall(DMGetWorkArray(dm, numelH, MPIU_REAL, &sH)); } 398 if (B) 399 for (i = 0; i < numelB; ++i) B[i] = 0.; 400 if (D) 401 for (i = 0; i < numelD; ++i) D[i] = 0.; 402 if (H) 403 for (i = 0; i < numelH; ++i) H[i] = 0.; 404 405 for (s = 0, offset = 0, ncoffset = 0; s < Ns; ++s) { 406 PetscInt sNv, spdim, sNc, p; 407 408 PetscCall(PetscSpaceGetNumVariables(sum->sumspaces[s], &sNv)); 409 PetscCall(PetscSpaceGetNumComponents(sum->sumspaces[s], &sNc)); 410 PetscCall(PetscSpaceGetDimension(sum->sumspaces[s], &spdim)); 411 PetscCheck(offset + spdim <= pdimfull, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Subspace dimensions exceed target space dimension."); 412 if (s == 0 || !sum->uniform) { PetscCall(PetscSpaceEvaluate(sum->sumspaces[s], npoints, points, sB, sD, sH)); } 413 if (B || D || H) { 414 for (p = 0; p < npoints; ++p) { 415 PetscInt j; 416 417 for (j = 0; j < spdim; ++j) { 418 PetscInt c; 419 420 for (c = 0; c < sNc; ++c) { 421 PetscInt compoffset, BInd, sBInd; 422 423 compoffset = concatenate ? c + ncoffset : c; 424 BInd = (p * pdimfull + j + offset) * Nc + compoffset; 425 sBInd = (p * spdim + j) * sNc + c; 426 if (B) B[BInd] = sB[sBInd]; 427 if (D || H) { 428 PetscInt v; 429 430 for (v = 0; v < Nv; ++v) { 431 PetscInt DInd, sDInd; 432 433 DInd = BInd * Nv + v; 434 sDInd = sBInd * Nv + v; 435 if (D) D[DInd] = sD[sDInd]; 436 if (H) { 437 PetscInt v2; 438 439 for (v2 = 0; v2 < Nv; ++v2) { 440 PetscInt HInd, sHInd; 441 442 HInd = DInd * Nv + v2; 443 sHInd = sDInd * Nv + v2; 444 H[HInd] = sH[sHInd]; 445 } 446 } 447 } 448 } 449 } 450 } 451 } 452 } 453 offset += spdim; 454 ncoffset += sNc; 455 } 456 457 if (H) { PetscCall(DMRestoreWorkArray(dm, numelH, MPIU_REAL, &sH)); } 458 if (D || H) { PetscCall(DMRestoreWorkArray(dm, numelD, MPIU_REAL, &sD)); } 459 if (B || D || H) { PetscCall(DMRestoreWorkArray(dm, numelB, MPIU_REAL, &sB)); } 460 PetscFunctionReturn(0); 461 } 462 463 static PetscErrorCode PetscSpaceGetHeightSubspace_Sum(PetscSpace sp, PetscInt height, PetscSpace *subsp) { 464 PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data; 465 PetscInt Nc, dim, order; 466 PetscBool tensor; 467 468 PetscFunctionBegin; 469 PetscCall(PetscSpaceGetNumComponents(sp, &Nc)); 470 PetscCall(PetscSpaceGetNumVariables(sp, &dim)); 471 PetscCall(PetscSpaceGetDegree(sp, &order, NULL)); 472 PetscCall(PetscSpacePolynomialGetTensor(sp, &tensor)); 473 PetscCheck(height <= dim && height >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Asked for space at height %" PetscInt_FMT " for dimension %" PetscInt_FMT " space", height, dim); 474 if (!sum->heightsubspaces) PetscCall(PetscCalloc1(dim, &sum->heightsubspaces)); 475 if (height <= dim) { 476 if (!sum->heightsubspaces[height - 1]) { 477 PetscSpace sub; 478 const char *name; 479 480 PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)sp), &sub)); 481 PetscCall(PetscObjectGetName((PetscObject)sp, &name)); 482 PetscCall(PetscObjectSetName((PetscObject)sub, name)); 483 PetscCall(PetscSpaceSetType(sub, PETSCSPACESUM)); 484 PetscCall(PetscSpaceSumSetNumSubspaces(sub, sum->numSumSpaces)); 485 PetscCall(PetscSpaceSumSetConcatenate(sub, sum->concatenate)); 486 PetscCall(PetscSpaceSetNumComponents(sub, Nc)); 487 PetscCall(PetscSpaceSetNumVariables(sub, dim - height)); 488 for (PetscInt i = 0; i < sum->numSumSpaces; i++) { 489 PetscSpace subh; 490 491 PetscCall(PetscSpaceGetHeightSubspace(sum->sumspaces[i], height, &subh)); 492 PetscCall(PetscSpaceSumSetSubspace(sub, i, subh)); 493 } 494 PetscCall(PetscSpaceSetUp(sub)); 495 sum->heightsubspaces[height - 1] = sub; 496 } 497 *subsp = sum->heightsubspaces[height - 1]; 498 } else { 499 *subsp = NULL; 500 } 501 PetscFunctionReturn(0); 502 } 503 504 static PetscErrorCode PetscSpaceInitialize_Sum(PetscSpace sp) { 505 PetscFunctionBegin; 506 sp->ops->setfromoptions = PetscSpaceSetFromOptions_Sum; 507 sp->ops->setup = PetscSpaceSetUp_Sum; 508 sp->ops->view = PetscSpaceView_Sum; 509 sp->ops->destroy = PetscSpaceDestroy_Sum; 510 sp->ops->getdimension = PetscSpaceGetDimension_Sum; 511 sp->ops->evaluate = PetscSpaceEvaluate_Sum; 512 sp->ops->getheightsubspace = PetscSpaceGetHeightSubspace_Sum; 513 514 PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetNumSubspaces_C", PetscSpaceSumGetNumSubspaces_Sum)); 515 PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetNumSubspaces_C", PetscSpaceSumSetNumSubspaces_Sum)); 516 PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetSubspace_C", PetscSpaceSumGetSubspace_Sum)); 517 PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetSubspace_C", PetscSpaceSumSetSubspace_Sum)); 518 PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetConcatenate_C", PetscSpaceSumGetConcatenate_Sum)); 519 PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetConcatenate_C", PetscSpaceSumSetConcatenate_Sum)); 520 PetscFunctionReturn(0); 521 } 522 523 /*MC 524 PETSCSPACESUM = "sum" - A PetscSpace object that encapsulates a sum of subspaces. 525 That sum can either be direct or concatenate a concatenation.For example if A and B are spaces each with 2 components, 526 the direct sum of A and B will also have 2 components while the concatenated sum will have 4 components.In both cases A and B must be defined over the 527 same number of variables. 528 529 Level: intermediate 530 531 .seealso: `PetscSpaceType`, `PetscSpaceCreate()`, `PetscSpaceSetType()` 532 M*/ 533 PETSC_EXTERN PetscErrorCode PetscSpaceCreate_Sum(PetscSpace sp) { 534 PetscSpace_Sum *sum; 535 536 PetscFunctionBegin; 537 PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 1); 538 PetscCall(PetscNewLog(sp, &sum)); 539 sum->numSumSpaces = PETSC_DEFAULT; 540 sp->data = sum; 541 PetscCall(PetscSpaceInitialize_Sum(sp)); 542 PetscFunctionReturn(0); 543 } 544 545 PETSC_EXTERN PetscErrorCode PetscSpaceCreateSum(PetscInt numSubspaces, const PetscSpace subspaces[], PetscBool concatenate, PetscSpace *sumSpace) { 546 PetscInt i, Nv, Nc = 0; 547 548 PetscFunctionBegin; 549 if (sumSpace) PetscCall(PetscSpaceDestroy(sumSpace)); 550 PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)subspaces[0]), sumSpace)); 551 PetscCall(PetscSpaceSetType(*sumSpace, PETSCSPACESUM)); 552 PetscCall(PetscSpaceSumSetNumSubspaces(*sumSpace, numSubspaces)); 553 PetscCall(PetscSpaceSumSetConcatenate(*sumSpace, concatenate)); 554 for (i = 0; i < numSubspaces; ++i) { 555 PetscInt sNc; 556 557 PetscCall(PetscSpaceSumSetSubspace(*sumSpace, i, subspaces[i])); 558 PetscCall(PetscSpaceGetNumComponents(subspaces[i], &sNc)); 559 if (concatenate) Nc += sNc; 560 else Nc = sNc; 561 } 562 PetscCall(PetscSpaceGetNumVariables(subspaces[0], &Nv)); 563 PetscCall(PetscSpaceSetNumComponents(*sumSpace, Nc)); 564 PetscCall(PetscSpaceSetNumVariables(*sumSpace, Nv)); 565 PetscCall(PetscSpaceSetUp(*sumSpace)); 566 567 PetscFunctionReturn(0); 568 } 569