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