120cf1dd8SToby Isaac #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/ 220cf1dd8SToby Isaac #include <petsc/private/dtimpl.h> /*I "petscdt.h" I*/ 320cf1dd8SToby Isaac #include <petscblaslapack.h> 420cf1dd8SToby Isaac 52b99622eSMatthew G. Knepley static PetscErrorCode PetscFEDestroy_Composite(PetscFE fem) 620cf1dd8SToby Isaac { 720cf1dd8SToby Isaac PetscFE_Composite *cmp = (PetscFE_Composite *) fem->data; 820cf1dd8SToby Isaac PetscErrorCode ierr; 920cf1dd8SToby Isaac 1020cf1dd8SToby Isaac PetscFunctionBegin; 1120cf1dd8SToby Isaac ierr = PetscFree(cmp->embedding);CHKERRQ(ierr); 1220cf1dd8SToby Isaac ierr = PetscFree(cmp);CHKERRQ(ierr); 1320cf1dd8SToby Isaac PetscFunctionReturn(0); 1420cf1dd8SToby Isaac } 1520cf1dd8SToby Isaac 162b99622eSMatthew G. Knepley static PetscErrorCode PetscFESetUp_Composite(PetscFE fem) 1720cf1dd8SToby Isaac { 1820cf1dd8SToby Isaac PetscFE_Composite *cmp = (PetscFE_Composite *) fem->data; 1920cf1dd8SToby Isaac DM K; 20*412e9a14SMatthew G. Knepley DMPolytopeType ct; 21*412e9a14SMatthew G. Knepley DMPlexCellRefiner cr; 2220cf1dd8SToby Isaac PetscReal *subpoint; 2320cf1dd8SToby Isaac PetscBLASInt *pivots; 2420cf1dd8SToby Isaac PetscBLASInt n, info; 2520cf1dd8SToby Isaac PetscScalar *work, *invVscalar; 2620cf1dd8SToby Isaac PetscInt dim, pdim, spdim, j, s; 2720cf1dd8SToby Isaac PetscErrorCode ierr; 2820cf1dd8SToby Isaac 2920cf1dd8SToby Isaac PetscFunctionBegin; 3020cf1dd8SToby Isaac /* Get affine mapping from reference cell to each subcell */ 3120cf1dd8SToby Isaac ierr = PetscDualSpaceGetDM(fem->dualSpace, &K);CHKERRQ(ierr); 3220cf1dd8SToby Isaac ierr = DMGetDimension(K, &dim);CHKERRQ(ierr); 33*412e9a14SMatthew G. Knepley ierr = DMPlexGetCellType(K, 0, &ct);CHKERRQ(ierr); 34*412e9a14SMatthew G. Knepley ierr = DMPlexCellRefinerCreate(K, &cr);CHKERRQ(ierr); 35*412e9a14SMatthew G. Knepley ierr = DMPlexCellRefinerGetAffineTransforms(cr, ct, &cmp->numSubelements, &cmp->v0, &cmp->jac, &cmp->invjac);CHKERRQ(ierr); 36*412e9a14SMatthew G. Knepley ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr); 3720cf1dd8SToby Isaac /* Determine dof embedding into subelements */ 3820cf1dd8SToby Isaac ierr = PetscDualSpaceGetDimension(fem->dualSpace, &pdim);CHKERRQ(ierr); 3920cf1dd8SToby Isaac ierr = PetscSpaceGetDimension(fem->basisSpace, &spdim);CHKERRQ(ierr); 4020cf1dd8SToby Isaac ierr = PetscMalloc1(cmp->numSubelements*spdim,&cmp->embedding);CHKERRQ(ierr); 4120cf1dd8SToby Isaac ierr = DMGetWorkArray(K, dim, MPIU_REAL, &subpoint);CHKERRQ(ierr); 4220cf1dd8SToby Isaac for (s = 0; s < cmp->numSubelements; ++s) { 4320cf1dd8SToby Isaac PetscInt sd = 0; 4420cf1dd8SToby Isaac 4520cf1dd8SToby Isaac for (j = 0; j < pdim; ++j) { 4620cf1dd8SToby Isaac PetscBool inside; 4720cf1dd8SToby Isaac PetscQuadrature f; 4820cf1dd8SToby Isaac PetscInt d, e; 4920cf1dd8SToby Isaac 5020cf1dd8SToby Isaac ierr = PetscDualSpaceGetFunctional(fem->dualSpace, j, &f);CHKERRQ(ierr); 5120cf1dd8SToby Isaac /* Apply transform to first point, and check that point is inside subcell */ 5220cf1dd8SToby Isaac for (d = 0; d < dim; ++d) { 5320cf1dd8SToby Isaac subpoint[d] = -1.0; 5420cf1dd8SToby Isaac for (e = 0; e < dim; ++e) subpoint[d] += cmp->invjac[(s*dim + d)*dim+e]*(f->points[e] - cmp->v0[s*dim+e]); 5520cf1dd8SToby Isaac } 56*412e9a14SMatthew G. Knepley ierr = CellRefinerInCellTest_Internal(ct, subpoint, &inside);CHKERRQ(ierr); 5720cf1dd8SToby Isaac if (inside) {cmp->embedding[s*spdim+sd++] = j;} 5820cf1dd8SToby Isaac } 5920cf1dd8SToby Isaac if (sd != spdim) SETERRQ3(PetscObjectComm((PetscObject) fem), PETSC_ERR_PLIB, "Subelement %d has %d dual basis vectors != %d", s, sd, spdim); 6020cf1dd8SToby Isaac } 6120cf1dd8SToby Isaac ierr = DMRestoreWorkArray(K, dim, MPIU_REAL, &subpoint);CHKERRQ(ierr); 6220cf1dd8SToby Isaac /* Construct the change of basis from prime basis to nodal basis for each subelement */ 6320cf1dd8SToby Isaac ierr = PetscMalloc1(cmp->numSubelements*spdim*spdim,&fem->invV);CHKERRQ(ierr); 6420cf1dd8SToby Isaac ierr = PetscMalloc2(spdim,&pivots,spdim,&work);CHKERRQ(ierr); 6520cf1dd8SToby Isaac #if defined(PETSC_USE_COMPLEX) 6620cf1dd8SToby Isaac ierr = PetscMalloc1(cmp->numSubelements*spdim*spdim,&invVscalar);CHKERRQ(ierr); 6720cf1dd8SToby Isaac #else 6820cf1dd8SToby Isaac invVscalar = fem->invV; 6920cf1dd8SToby Isaac #endif 7020cf1dd8SToby Isaac for (s = 0; s < cmp->numSubelements; ++s) { 7120cf1dd8SToby Isaac for (j = 0; j < spdim; ++j) { 7220cf1dd8SToby Isaac PetscReal *Bf; 7320cf1dd8SToby Isaac PetscQuadrature f; 7420cf1dd8SToby Isaac const PetscReal *points, *weights; 7520cf1dd8SToby Isaac PetscInt Nc, Nq, q, k; 7620cf1dd8SToby Isaac 7720cf1dd8SToby Isaac ierr = PetscDualSpaceGetFunctional(fem->dualSpace, cmp->embedding[s*spdim+j], &f);CHKERRQ(ierr); 7820cf1dd8SToby Isaac ierr = PetscQuadratureGetData(f, NULL, &Nc, &Nq, &points, &weights);CHKERRQ(ierr); 7920cf1dd8SToby Isaac ierr = PetscMalloc1(f->numPoints*spdim*Nc,&Bf);CHKERRQ(ierr); 8020cf1dd8SToby Isaac ierr = PetscSpaceEvaluate(fem->basisSpace, Nq, points, Bf, NULL, NULL);CHKERRQ(ierr); 8120cf1dd8SToby Isaac for (k = 0; k < spdim; ++k) { 8220cf1dd8SToby Isaac /* n_j \cdot \phi_k */ 8320cf1dd8SToby Isaac invVscalar[(s*spdim + j)*spdim+k] = 0.0; 8420cf1dd8SToby Isaac for (q = 0; q < Nq; ++q) { 8520cf1dd8SToby Isaac invVscalar[(s*spdim + j)*spdim+k] += Bf[q*spdim+k]*weights[q]; 8620cf1dd8SToby Isaac } 8720cf1dd8SToby Isaac } 8820cf1dd8SToby Isaac ierr = PetscFree(Bf);CHKERRQ(ierr); 8920cf1dd8SToby Isaac } 9020cf1dd8SToby Isaac n = spdim; 9120cf1dd8SToby Isaac PetscStackCallBLAS("LAPACKgetrf", LAPACKgetrf_(&n, &n, &invVscalar[s*spdim*spdim], &n, pivots, &info)); 9220cf1dd8SToby Isaac PetscStackCallBLAS("LAPACKgetri", LAPACKgetri_(&n, &invVscalar[s*spdim*spdim], &n, pivots, work, &n, &info)); 9320cf1dd8SToby Isaac } 9420cf1dd8SToby Isaac #if defined(PETSC_USE_COMPLEX) 9520cf1dd8SToby Isaac for (s = 0; s <cmp->numSubelements*spdim*spdim; s++) fem->invV[s] = PetscRealPart(invVscalar[s]); 9620cf1dd8SToby Isaac ierr = PetscFree(invVscalar);CHKERRQ(ierr); 9720cf1dd8SToby Isaac #endif 9820cf1dd8SToby Isaac ierr = PetscFree2(pivots,work);CHKERRQ(ierr); 9920cf1dd8SToby Isaac PetscFunctionReturn(0); 10020cf1dd8SToby Isaac } 10120cf1dd8SToby Isaac 102ef0bb6c7SMatthew G. Knepley static PetscErrorCode PetscFECreateTabulation_Composite(PetscFE fem, PetscInt npoints, const PetscReal points[], PetscInt K, PetscTabulation T) 10320cf1dd8SToby Isaac { 10420cf1dd8SToby Isaac PetscFE_Composite *cmp = (PetscFE_Composite *) fem->data; 10520cf1dd8SToby Isaac DM dm; 106*412e9a14SMatthew G. Knepley DMPolytopeType ct; 10720cf1dd8SToby Isaac PetscInt pdim; /* Dimension of FE space P */ 10820cf1dd8SToby Isaac PetscInt spdim; /* Dimension of subelement FE space P */ 10920cf1dd8SToby Isaac PetscInt dim; /* Spatial dimension */ 11020cf1dd8SToby Isaac PetscInt comp; /* Field components */ 11120cf1dd8SToby Isaac PetscInt *subpoints; 112ef0bb6c7SMatthew G. Knepley PetscReal *B = K >= 0 ? T->T[0] : NULL; 113ef0bb6c7SMatthew G. Knepley PetscReal *D = K >= 1 ? T->T[1] : NULL; 114ef0bb6c7SMatthew G. Knepley PetscReal *H = K >= 2 ? T->T[2] : NULL; 115ef0bb6c7SMatthew G. Knepley PetscReal *tmpB = NULL, *tmpD = NULL, *tmpH = NULL, *subpoint; 11620cf1dd8SToby Isaac PetscInt p, s, d, e, j, k; 11720cf1dd8SToby Isaac PetscErrorCode ierr; 11820cf1dd8SToby Isaac 11920cf1dd8SToby Isaac PetscFunctionBegin; 12020cf1dd8SToby Isaac ierr = PetscDualSpaceGetDM(fem->dualSpace, &dm);CHKERRQ(ierr); 12120cf1dd8SToby Isaac ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 122*412e9a14SMatthew G. Knepley ierr = DMPlexGetCellType(dm, 0, &ct);CHKERRQ(ierr); 12320cf1dd8SToby Isaac ierr = PetscSpaceGetDimension(fem->basisSpace, &spdim);CHKERRQ(ierr); 12420cf1dd8SToby Isaac ierr = PetscDualSpaceGetDimension(fem->dualSpace, &pdim);CHKERRQ(ierr); 12520cf1dd8SToby Isaac ierr = PetscFEGetNumComponents(fem, &comp);CHKERRQ(ierr); 12620cf1dd8SToby Isaac /* Divide points into subelements */ 12720cf1dd8SToby Isaac ierr = DMGetWorkArray(dm, npoints, MPIU_INT, &subpoints);CHKERRQ(ierr); 12820cf1dd8SToby Isaac ierr = DMGetWorkArray(dm, dim, MPIU_REAL, &subpoint);CHKERRQ(ierr); 12920cf1dd8SToby Isaac for (p = 0; p < npoints; ++p) { 13020cf1dd8SToby Isaac for (s = 0; s < cmp->numSubelements; ++s) { 13120cf1dd8SToby Isaac PetscBool inside; 13220cf1dd8SToby Isaac 13320cf1dd8SToby Isaac /* Apply transform, and check that point is inside cell */ 13420cf1dd8SToby Isaac for (d = 0; d < dim; ++d) { 13520cf1dd8SToby Isaac subpoint[d] = -1.0; 13620cf1dd8SToby Isaac for (e = 0; e < dim; ++e) subpoint[d] += cmp->invjac[(s*dim + d)*dim+e]*(points[p*dim+e] - cmp->v0[s*dim+e]); 13720cf1dd8SToby Isaac } 138*412e9a14SMatthew G. Knepley ierr = CellRefinerInCellTest_Internal(ct, subpoint, &inside);CHKERRQ(ierr); 13920cf1dd8SToby Isaac if (inside) {subpoints[p] = s; break;} 14020cf1dd8SToby Isaac } 14120cf1dd8SToby Isaac if (s >= cmp->numSubelements) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %d was not found in any subelement", p); 14220cf1dd8SToby Isaac } 14320cf1dd8SToby Isaac ierr = DMRestoreWorkArray(dm, dim, MPIU_REAL, &subpoint);CHKERRQ(ierr); 14420cf1dd8SToby Isaac /* Evaluate the prime basis functions at all points */ 145ef0bb6c7SMatthew G. Knepley if (K >= 0) {ierr = DMGetWorkArray(dm, npoints*spdim, MPIU_REAL, &tmpB);CHKERRQ(ierr);} 146ef0bb6c7SMatthew G. Knepley if (K >= 1) {ierr = DMGetWorkArray(dm, npoints*spdim*dim, MPIU_REAL, &tmpD);CHKERRQ(ierr);} 147ef0bb6c7SMatthew G. Knepley if (K >= 2) {ierr = DMGetWorkArray(dm, npoints*spdim*dim*dim, MPIU_REAL, &tmpH);CHKERRQ(ierr);} 148ef0bb6c7SMatthew G. Knepley ierr = PetscSpaceEvaluate(fem->basisSpace, npoints, points, tmpB, tmpD, tmpH);CHKERRQ(ierr); 14920cf1dd8SToby Isaac /* Translate to the nodal basis */ 150ef0bb6c7SMatthew G. Knepley if (K >= 0) {ierr = PetscArrayzero(B, npoints*pdim*comp);CHKERRQ(ierr);} 151ef0bb6c7SMatthew G. Knepley if (K >= 1) {ierr = PetscArrayzero(D, npoints*pdim*comp*dim);CHKERRQ(ierr);} 152ef0bb6c7SMatthew G. Knepley if (K >= 2) {ierr = PetscArrayzero(H, npoints*pdim*comp*dim*dim);CHKERRQ(ierr);} 15320cf1dd8SToby Isaac for (p = 0; p < npoints; ++p) { 15420cf1dd8SToby Isaac const PetscInt s = subpoints[p]; 15520cf1dd8SToby Isaac 15620cf1dd8SToby Isaac if (B) { 15720cf1dd8SToby Isaac /* Multiply by V^{-1} (spdim x spdim) */ 15820cf1dd8SToby Isaac for (j = 0; j < spdim; ++j) { 15920cf1dd8SToby Isaac const PetscInt i = (p*pdim + cmp->embedding[s*spdim+j])*comp; 16020cf1dd8SToby Isaac 16120cf1dd8SToby Isaac B[i] = 0.0; 16220cf1dd8SToby Isaac for (k = 0; k < spdim; ++k) { 16320cf1dd8SToby Isaac B[i] += fem->invV[(s*spdim + k)*spdim+j] * tmpB[p*spdim + k]; 16420cf1dd8SToby Isaac } 16520cf1dd8SToby Isaac } 16620cf1dd8SToby Isaac } 16720cf1dd8SToby Isaac if (D) { 16820cf1dd8SToby Isaac /* Multiply by V^{-1} (spdim x spdim) */ 16920cf1dd8SToby Isaac for (j = 0; j < spdim; ++j) { 17020cf1dd8SToby Isaac for (d = 0; d < dim; ++d) { 17120cf1dd8SToby Isaac const PetscInt i = ((p*pdim + cmp->embedding[s*spdim+j])*comp + 0)*dim + d; 17220cf1dd8SToby Isaac 17320cf1dd8SToby Isaac D[i] = 0.0; 17420cf1dd8SToby Isaac for (k = 0; k < spdim; ++k) { 17520cf1dd8SToby Isaac D[i] += fem->invV[(s*spdim + k)*spdim+j] * tmpD[(p*spdim + k)*dim + d]; 17620cf1dd8SToby Isaac } 17720cf1dd8SToby Isaac } 17820cf1dd8SToby Isaac } 17920cf1dd8SToby Isaac } 18020cf1dd8SToby Isaac if (H) { 18120cf1dd8SToby Isaac /* Multiply by V^{-1} (pdim x pdim) */ 18220cf1dd8SToby Isaac for (j = 0; j < spdim; ++j) { 18320cf1dd8SToby Isaac for (d = 0; d < dim*dim; ++d) { 18420cf1dd8SToby Isaac const PetscInt i = ((p*pdim + cmp->embedding[s*spdim+j])*comp + 0)*dim*dim + d; 18520cf1dd8SToby Isaac 18620cf1dd8SToby Isaac H[i] = 0.0; 18720cf1dd8SToby Isaac for (k = 0; k < spdim; ++k) { 18820cf1dd8SToby Isaac H[i] += fem->invV[(s*spdim + k)*spdim+j] * tmpH[(p*spdim + k)*dim*dim + d]; 18920cf1dd8SToby Isaac } 19020cf1dd8SToby Isaac } 19120cf1dd8SToby Isaac } 19220cf1dd8SToby Isaac } 19320cf1dd8SToby Isaac } 19420cf1dd8SToby Isaac ierr = DMRestoreWorkArray(dm, npoints, MPIU_INT, &subpoints);CHKERRQ(ierr); 195ef0bb6c7SMatthew G. Knepley if (K >= 0) {ierr = DMRestoreWorkArray(dm, npoints*spdim, MPIU_REAL, &tmpB);CHKERRQ(ierr);} 196ef0bb6c7SMatthew G. Knepley if (K >= 1) {ierr = DMRestoreWorkArray(dm, npoints*spdim*dim, MPIU_REAL, &tmpD);CHKERRQ(ierr);} 197ef0bb6c7SMatthew G. Knepley if (K >= 2) {ierr = DMRestoreWorkArray(dm, npoints*spdim*dim*dim, MPIU_REAL, &tmpH);CHKERRQ(ierr);} 19820cf1dd8SToby Isaac PetscFunctionReturn(0); 19920cf1dd8SToby Isaac } 20020cf1dd8SToby Isaac 2012b99622eSMatthew G. Knepley static PetscErrorCode PetscFEInitialize_Composite(PetscFE fem) 20220cf1dd8SToby Isaac { 20320cf1dd8SToby Isaac PetscFunctionBegin; 20420cf1dd8SToby Isaac fem->ops->setfromoptions = NULL; 20520cf1dd8SToby Isaac fem->ops->setup = PetscFESetUp_Composite; 20620cf1dd8SToby Isaac fem->ops->view = NULL; 20720cf1dd8SToby Isaac fem->ops->destroy = PetscFEDestroy_Composite; 20820cf1dd8SToby Isaac fem->ops->getdimension = PetscFEGetDimension_Basic; 209ef0bb6c7SMatthew G. Knepley fem->ops->createtabulation = PetscFECreateTabulation_Composite; 21020cf1dd8SToby Isaac fem->ops->integrateresidual = PetscFEIntegrateResidual_Basic; 21120cf1dd8SToby Isaac fem->ops->integratebdresidual = PetscFEIntegrateBdResidual_Basic; 21220cf1dd8SToby Isaac fem->ops->integratejacobianaction = NULL/* PetscFEIntegrateJacobianAction_Basic */; 21320cf1dd8SToby Isaac fem->ops->integratejacobian = PetscFEIntegrateJacobian_Basic; 21420cf1dd8SToby Isaac PetscFunctionReturn(0); 21520cf1dd8SToby Isaac } 21620cf1dd8SToby Isaac 21720cf1dd8SToby Isaac /*MC 21820cf1dd8SToby Isaac PETSCFECOMPOSITE = "composite" - A PetscFE object that represents a composite element 21920cf1dd8SToby Isaac 22020cf1dd8SToby Isaac Level: intermediate 22120cf1dd8SToby Isaac 22220cf1dd8SToby Isaac .seealso: PetscFEType, PetscFECreate(), PetscFESetType() 22320cf1dd8SToby Isaac M*/ 22420cf1dd8SToby Isaac PETSC_EXTERN PetscErrorCode PetscFECreate_Composite(PetscFE fem) 22520cf1dd8SToby Isaac { 22620cf1dd8SToby Isaac PetscFE_Composite *cmp; 22720cf1dd8SToby Isaac PetscErrorCode ierr; 22820cf1dd8SToby Isaac 22920cf1dd8SToby Isaac PetscFunctionBegin; 23020cf1dd8SToby Isaac PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 23120cf1dd8SToby Isaac ierr = PetscNewLog(fem, &cmp);CHKERRQ(ierr); 23220cf1dd8SToby Isaac fem->data = cmp; 23320cf1dd8SToby Isaac 23420cf1dd8SToby Isaac cmp->numSubelements = -1; 23520cf1dd8SToby Isaac cmp->v0 = NULL; 23620cf1dd8SToby Isaac cmp->jac = NULL; 23720cf1dd8SToby Isaac 23820cf1dd8SToby Isaac ierr = PetscFEInitialize_Composite(fem);CHKERRQ(ierr); 23920cf1dd8SToby Isaac PetscFunctionReturn(0); 24020cf1dd8SToby Isaac } 24120cf1dd8SToby Isaac 24220cf1dd8SToby Isaac /*@C 24320cf1dd8SToby Isaac PetscFECompositeGetMapping - Returns the mappings from the reference element to each subelement 24420cf1dd8SToby Isaac 24520cf1dd8SToby Isaac Not collective 24620cf1dd8SToby Isaac 24720cf1dd8SToby Isaac Input Parameter: 24820cf1dd8SToby Isaac . fem - The PetscFE object 24920cf1dd8SToby Isaac 25020cf1dd8SToby Isaac Output Parameters: 25120cf1dd8SToby Isaac + blockSize - The number of elements in a block 25220cf1dd8SToby Isaac . numBlocks - The number of blocks in a batch 25320cf1dd8SToby Isaac . batchSize - The number of elements in a batch 25420cf1dd8SToby Isaac - numBatches - The number of batches in a chunk 25520cf1dd8SToby Isaac 25620cf1dd8SToby Isaac Level: intermediate 25720cf1dd8SToby Isaac 25820cf1dd8SToby Isaac .seealso: PetscFECreate() 25920cf1dd8SToby Isaac @*/ 26020cf1dd8SToby Isaac PetscErrorCode PetscFECompositeGetMapping(PetscFE fem, PetscInt *numSubelements, const PetscReal *v0[], const PetscReal *jac[], const PetscReal *invjac[]) 26120cf1dd8SToby Isaac { 26220cf1dd8SToby Isaac PetscFE_Composite *cmp = (PetscFE_Composite *) fem->data; 26320cf1dd8SToby Isaac 26420cf1dd8SToby Isaac PetscFunctionBegin; 26520cf1dd8SToby Isaac PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 26620cf1dd8SToby Isaac if (numSubelements) {PetscValidPointer(numSubelements, 2); *numSubelements = cmp->numSubelements;} 26720cf1dd8SToby Isaac if (v0) {PetscValidPointer(v0, 3); *v0 = cmp->v0;} 26820cf1dd8SToby Isaac if (jac) {PetscValidPointer(jac, 4); *jac = cmp->jac;} 26920cf1dd8SToby Isaac if (invjac) {PetscValidPointer(invjac, 5); *invjac = cmp->invjac;} 27020cf1dd8SToby Isaac PetscFunctionReturn(0); 27120cf1dd8SToby Isaac } 272