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