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