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