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