120cf1dd8SToby Isaac #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/ 220cf1dd8SToby Isaac 320cf1dd8SToby Isaac typedef struct { 420cf1dd8SToby Isaac PetscDualSpace dualSubspace; 520cf1dd8SToby Isaac PetscSpace origSpace; 620cf1dd8SToby Isaac PetscReal *x; 720cf1dd8SToby Isaac PetscReal *x_alloc; 820cf1dd8SToby Isaac PetscReal *Jx; 920cf1dd8SToby Isaac PetscReal *Jx_alloc; 1020cf1dd8SToby Isaac PetscReal *u; 1120cf1dd8SToby Isaac PetscReal *u_alloc; 1220cf1dd8SToby Isaac PetscReal *Ju; 1320cf1dd8SToby Isaac PetscReal *Ju_alloc; 1420cf1dd8SToby Isaac PetscReal *Q; 1520cf1dd8SToby Isaac PetscInt Nb; 1620cf1dd8SToby Isaac } PetscSpace_Subspace; 1720cf1dd8SToby Isaac 1820cf1dd8SToby Isaac static PetscErrorCode PetscSpaceDestroy_Subspace(PetscSpace sp) 1920cf1dd8SToby Isaac { 2020cf1dd8SToby Isaac PetscSpace_Subspace *subsp; 2120cf1dd8SToby Isaac 2220cf1dd8SToby Isaac PetscFunctionBegin; 2320cf1dd8SToby Isaac subsp = (PetscSpace_Subspace *) sp->data; 2420cf1dd8SToby Isaac subsp->x = NULL; 25*9566063dSJacob Faibussowitsch PetscCall(PetscFree(subsp->x_alloc)); 2620cf1dd8SToby Isaac subsp->Jx = NULL; 27*9566063dSJacob Faibussowitsch PetscCall(PetscFree(subsp->Jx_alloc)); 2820cf1dd8SToby Isaac subsp->u = NULL; 29*9566063dSJacob Faibussowitsch PetscCall(PetscFree(subsp->u_alloc)); 3020cf1dd8SToby Isaac subsp->Ju = NULL; 31*9566063dSJacob Faibussowitsch PetscCall(PetscFree(subsp->Ju_alloc)); 32*9566063dSJacob Faibussowitsch PetscCall(PetscFree(subsp->Q)); 33*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceDestroy(&subsp->origSpace)); 34*9566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceDestroy(&subsp->dualSubspace)); 35*9566063dSJacob Faibussowitsch PetscCall(PetscFree(subsp)); 3620cf1dd8SToby Isaac sp->data = NULL; 37*9566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject) sp, "PetscSpacePolynomialGetTensor_C", NULL)); 3820cf1dd8SToby Isaac PetscFunctionReturn(0); 3920cf1dd8SToby Isaac } 4020cf1dd8SToby Isaac 4120cf1dd8SToby Isaac static PetscErrorCode PetscSpaceView_Subspace(PetscSpace sp, PetscViewer viewer) 4220cf1dd8SToby Isaac { 4320cf1dd8SToby Isaac PetscBool iascii; 4420cf1dd8SToby Isaac PetscSpace_Subspace *subsp; 4520cf1dd8SToby Isaac 4620cf1dd8SToby Isaac PetscFunctionBegin; 4720cf1dd8SToby Isaac subsp = (PetscSpace_Subspace *) sp->data; 48*9566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii)); 4920cf1dd8SToby Isaac if (iascii) { 5020cf1dd8SToby Isaac PetscInt origDim, subDim, origNc, subNc, o, s; 5120cf1dd8SToby Isaac 52*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetNumVariables(subsp->origSpace,&origDim)); 53*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetNumComponents(subsp->origSpace,&origNc)); 54*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetNumVariables(sp,&subDim)); 55*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetNumComponents(sp,&subNc)); 5620cf1dd8SToby Isaac if (subsp->x) { 57*9566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"Subspace-to-space domain shift:\n\n")); 5820cf1dd8SToby Isaac for (o = 0; o < origDim; o++) { 59*9566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," %g\n", (double)subsp->x[o])); 6020cf1dd8SToby Isaac } 6120cf1dd8SToby Isaac } 6220cf1dd8SToby Isaac if (subsp->Jx) { 63*9566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"Subspace-to-space domain transform:\n\n")); 6420cf1dd8SToby Isaac for (o = 0; o < origDim; o++) { 65*9566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," %g", (double)subsp->Jx[o * subDim + 0])); 66*9566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE)); 6720cf1dd8SToby Isaac for (s = 1; s < subDim; s++) { 68*9566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," %g", (double)subsp->Jx[o * subDim + s])); 6920cf1dd8SToby Isaac } 70*9566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"\n")); 71*9566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE)); 7220cf1dd8SToby Isaac } 7320cf1dd8SToby Isaac } 7420cf1dd8SToby Isaac if (subsp->u) { 75*9566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"Space-to-subspace range shift:\n\n")); 7620cf1dd8SToby Isaac for (o = 0; o < origNc; o++) { 77*9566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," %d\n", subsp->u[o])); 7820cf1dd8SToby Isaac } 7920cf1dd8SToby Isaac } 8020cf1dd8SToby Isaac if (subsp->Ju) { 81*9566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"Space-to-subsace domain transform:\n")); 8220cf1dd8SToby Isaac for (o = 0; o < origNc; o++) { 83*9566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE)); 8420cf1dd8SToby Isaac for (s = 0; s < subNc; s++) { 85*9566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," %d", subsp->Ju[o * subNc + s])); 8620cf1dd8SToby Isaac } 87*9566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE)); 8820cf1dd8SToby Isaac } 89*9566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"\n")); 9020cf1dd8SToby Isaac } 91*9566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"Original space:\n")); 9220cf1dd8SToby Isaac } 93*9566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 94*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceView(subsp->origSpace,viewer)); 95*9566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 9620cf1dd8SToby Isaac PetscFunctionReturn(0); 9720cf1dd8SToby Isaac } 9820cf1dd8SToby Isaac 9920cf1dd8SToby Isaac static PetscErrorCode PetscSpaceEvaluate_Subspace(PetscSpace sp, PetscInt npoints, const PetscReal points[], PetscReal B[], PetscReal D[], PetscReal H[]) 10020cf1dd8SToby Isaac { 10120cf1dd8SToby Isaac PetscSpace_Subspace *subsp = (PetscSpace_Subspace *) sp->data; 10220cf1dd8SToby Isaac PetscSpace origsp; 10320cf1dd8SToby Isaac PetscInt origDim, subDim, origNc, subNc, subNb, origNb, i, j, k, l, m, n, o; 10420cf1dd8SToby Isaac PetscReal *inpoints, *inB = NULL, *inD = NULL, *inH = NULL; 10520cf1dd8SToby Isaac 10620cf1dd8SToby Isaac PetscFunctionBegin; 10720cf1dd8SToby Isaac origsp = subsp->origSpace; 108*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetNumVariables(sp,&subDim)); 109*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetNumVariables(origsp,&origDim)); 110*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetNumComponents(sp,&subNc)); 111*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetNumComponents(origsp,&origNc)); 112*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetDimension(sp,&subNb)); 113*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetDimension(origsp,&origNb)); 114*9566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(sp->dm,npoints*origDim,MPIU_REAL,&inpoints)); 11520cf1dd8SToby Isaac for (i = 0; i < npoints; i++) { 11620cf1dd8SToby Isaac if (subsp->x) { 11720cf1dd8SToby Isaac for (j = 0; j < origDim; j++) inpoints[i * origDim + j] = subsp->x[j]; 11820cf1dd8SToby Isaac } else { 11920cf1dd8SToby Isaac for (j = 0; j < origDim; j++) inpoints[i * origDim + j] = 0.0; 12020cf1dd8SToby Isaac } 12120cf1dd8SToby Isaac if (subsp->Jx) { 12220cf1dd8SToby Isaac for (j = 0; j < origDim; j++) { 12320cf1dd8SToby Isaac for (k = 0; k < subDim; k++) { 12420cf1dd8SToby Isaac inpoints[i * origDim + j] += subsp->Jx[j * subDim + k] * points[i * subDim + k]; 12520cf1dd8SToby Isaac } 12620cf1dd8SToby Isaac } 12720cf1dd8SToby Isaac } else { 12820cf1dd8SToby Isaac for (j = 0; j < PetscMin(subDim, origDim); j++) { 12920cf1dd8SToby Isaac inpoints[i * origDim + j] += points[i * subDim + j]; 13020cf1dd8SToby Isaac } 13120cf1dd8SToby Isaac } 13220cf1dd8SToby Isaac } 13320cf1dd8SToby Isaac if (B) { 134*9566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(sp->dm,npoints*origNb*origNc,MPIU_REAL,&inB)); 13520cf1dd8SToby Isaac } 13620cf1dd8SToby Isaac if (D) { 137*9566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(sp->dm,npoints*origNb*origNc*origDim,MPIU_REAL,&inD)); 13820cf1dd8SToby Isaac } 13920cf1dd8SToby Isaac if (H) { 140*9566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(sp->dm,npoints*origNb*origNc*origDim*origDim,MPIU_REAL,&inH)); 14120cf1dd8SToby Isaac } 142*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceEvaluate(origsp,npoints,inpoints,inB,inD,inH)); 14320cf1dd8SToby Isaac if (H) { 14420cf1dd8SToby Isaac PetscReal *phi, *psi; 14520cf1dd8SToby Isaac 146*9566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(sp->dm,origNc*origDim*origDim,MPIU_REAL,&phi)); 147*9566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(sp->dm,origNc*subDim*subDim,MPIU_REAL,&psi)); 14820cf1dd8SToby Isaac for (i = 0; i < npoints * subNb * subNc * subDim; i++) D[i] = 0.0; 14920cf1dd8SToby Isaac for (i = 0; i < subNb; i++) { 15020cf1dd8SToby Isaac const PetscReal *subq = &subsp->Q[i * origNb]; 15120cf1dd8SToby Isaac 15220cf1dd8SToby Isaac for (j = 0; j < npoints; j++) { 15320cf1dd8SToby Isaac for (k = 0; k < origNc * origDim; k++) phi[k] = 0.; 15420cf1dd8SToby Isaac for (k = 0; k < origNc * subDim; k++) psi[k] = 0.; 15520cf1dd8SToby Isaac for (k = 0; k < origNb; k++) { 15620cf1dd8SToby Isaac for (l = 0; l < origNc * origDim * origDim; l++) { 15720cf1dd8SToby Isaac phi[l] += inH[(j * origNb + k) * origNc * origDim * origDim + l] * subq[k]; 15820cf1dd8SToby Isaac } 15920cf1dd8SToby Isaac } 16020cf1dd8SToby Isaac if (subsp->Jx) { 16120cf1dd8SToby Isaac for (k = 0; k < subNc; k++) { 16220cf1dd8SToby Isaac for (l = 0; l < subDim; l++) { 16320cf1dd8SToby Isaac for (m = 0; m < origDim; m++) { 16420cf1dd8SToby Isaac for (n = 0; n < subDim; n++) { 16520cf1dd8SToby Isaac for (o = 0; o < origDim; o++) { 16620cf1dd8SToby Isaac psi[(k * subDim + l) * subDim + n] += subsp->Jx[m * subDim + l] * subsp->Jx[o * subDim + n] * phi[(k * origDim + m) * origDim + o]; 16720cf1dd8SToby Isaac } 16820cf1dd8SToby Isaac } 16920cf1dd8SToby Isaac } 17020cf1dd8SToby Isaac } 17120cf1dd8SToby Isaac } 17220cf1dd8SToby Isaac } else { 17320cf1dd8SToby Isaac for (k = 0; k < subNc; k++) { 17420cf1dd8SToby Isaac for (l = 0; l < PetscMin(subDim, origDim); l++) { 17520cf1dd8SToby Isaac for (m = 0; m < PetscMin(subDim, origDim); m++) { 17620cf1dd8SToby Isaac psi[(k * subDim + l) * subDim + m] += phi[(k * origDim + l) * origDim + m]; 17720cf1dd8SToby Isaac } 17820cf1dd8SToby Isaac } 17920cf1dd8SToby Isaac } 18020cf1dd8SToby Isaac } 18120cf1dd8SToby Isaac if (subsp->Ju) { 18220cf1dd8SToby Isaac for (k = 0; k < subNc; k++) { 18320cf1dd8SToby Isaac for (l = 0; l < origNc; l++) { 18420cf1dd8SToby Isaac for (m = 0; m < subDim * subDim; m++) { 18520cf1dd8SToby Isaac H[((j * subNb + i) * subNc + k) * subDim * subDim + m] += subsp->Ju[k * origNc + l] * psi[l * subDim * subDim + m]; 18620cf1dd8SToby Isaac } 18720cf1dd8SToby Isaac } 18820cf1dd8SToby Isaac } 18920cf1dd8SToby Isaac } 19020cf1dd8SToby Isaac else { 19120cf1dd8SToby Isaac for (k = 0; k < PetscMin(subNc, origNc); k++) { 19220cf1dd8SToby Isaac for (l = 0; l < subDim * subDim; l++) { 19320cf1dd8SToby Isaac H[((j * subNb + i) * subNc + k) * subDim * subDim + l] += psi[k * subDim * subDim + l]; 19420cf1dd8SToby Isaac } 19520cf1dd8SToby Isaac } 19620cf1dd8SToby Isaac } 19720cf1dd8SToby Isaac } 19820cf1dd8SToby Isaac } 199*9566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(sp->dm,subNc*origDim,MPIU_REAL,&psi)); 200*9566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(sp->dm,origNc*origDim,MPIU_REAL,&phi)); 201*9566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(sp->dm,npoints*origNb*origNc*origDim,MPIU_REAL,&inH)); 20220cf1dd8SToby Isaac } 20320cf1dd8SToby Isaac if (D) { 20420cf1dd8SToby Isaac PetscReal *phi, *psi; 20520cf1dd8SToby Isaac 206*9566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(sp->dm,origNc*origDim,MPIU_REAL,&phi)); 207*9566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(sp->dm,origNc*subDim,MPIU_REAL,&psi)); 20820cf1dd8SToby Isaac for (i = 0; i < npoints * subNb * subNc * subDim; i++) D[i] = 0.0; 20920cf1dd8SToby Isaac for (i = 0; i < subNb; i++) { 21020cf1dd8SToby Isaac const PetscReal *subq = &subsp->Q[i * origNb]; 21120cf1dd8SToby Isaac 21220cf1dd8SToby Isaac for (j = 0; j < npoints; j++) { 21320cf1dd8SToby Isaac for (k = 0; k < origNc * origDim; k++) phi[k] = 0.; 21420cf1dd8SToby Isaac for (k = 0; k < origNc * subDim; k++) psi[k] = 0.; 21520cf1dd8SToby Isaac for (k = 0; k < origNb; k++) { 21620cf1dd8SToby Isaac for (l = 0; l < origNc * origDim; l++) { 21720cf1dd8SToby Isaac phi[l] += inD[(j * origNb + k) * origNc * origDim + l] * subq[k]; 21820cf1dd8SToby Isaac } 21920cf1dd8SToby Isaac } 22020cf1dd8SToby Isaac if (subsp->Jx) { 22120cf1dd8SToby Isaac for (k = 0; k < subNc; k++) { 22220cf1dd8SToby Isaac for (l = 0; l < subDim; l++) { 22320cf1dd8SToby Isaac for (m = 0; m < origDim; m++) { 22420cf1dd8SToby Isaac psi[k * subDim + l] += subsp->Jx[m * subDim + l] * phi[k * origDim + m]; 22520cf1dd8SToby Isaac } 22620cf1dd8SToby Isaac } 22720cf1dd8SToby Isaac } 22820cf1dd8SToby Isaac } else { 22920cf1dd8SToby Isaac for (k = 0; k < subNc; k++) { 23020cf1dd8SToby Isaac for (l = 0; l < PetscMin(subDim, origDim); l++) { 23120cf1dd8SToby Isaac psi[k * subDim + l] += phi[k * origDim + l]; 23220cf1dd8SToby Isaac } 23320cf1dd8SToby Isaac } 23420cf1dd8SToby Isaac } 23520cf1dd8SToby Isaac if (subsp->Ju) { 23620cf1dd8SToby Isaac for (k = 0; k < subNc; k++) { 23720cf1dd8SToby Isaac for (l = 0; l < origNc; l++) { 23820cf1dd8SToby Isaac for (m = 0; m < subDim; m++) { 23920cf1dd8SToby Isaac D[((j * subNb + i) * subNc + k) * subDim + m] += subsp->Ju[k * origNc + l] * psi[l * subDim + m]; 24020cf1dd8SToby Isaac } 24120cf1dd8SToby Isaac } 24220cf1dd8SToby Isaac } 24320cf1dd8SToby Isaac } 24420cf1dd8SToby Isaac else { 24520cf1dd8SToby Isaac for (k = 0; k < PetscMin(subNc, origNc); k++) { 24620cf1dd8SToby Isaac for (l = 0; l < subDim; l++) { 24720cf1dd8SToby Isaac D[((j * subNb + i) * subNc + k) * subDim + l] += psi[k * subDim + l]; 24820cf1dd8SToby Isaac } 24920cf1dd8SToby Isaac } 25020cf1dd8SToby Isaac } 25120cf1dd8SToby Isaac } 25220cf1dd8SToby Isaac } 253*9566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(sp->dm,subNc*origDim,MPIU_REAL,&psi)); 254*9566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(sp->dm,origNc*origDim,MPIU_REAL,&phi)); 255*9566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(sp->dm,npoints*origNb*origNc*origDim,MPIU_REAL,&inD)); 25620cf1dd8SToby Isaac } 25720cf1dd8SToby Isaac if (B) { 25820cf1dd8SToby Isaac PetscReal *phi; 25920cf1dd8SToby Isaac 260*9566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(sp->dm,origNc,MPIU_REAL,&phi)); 26120cf1dd8SToby Isaac if (subsp->u) { 26220cf1dd8SToby Isaac for (i = 0; i < npoints * subNb; i++) { 26320cf1dd8SToby Isaac for (j = 0; j < subNc; j++) B[i * subNc + j] = subsp->u[j]; 26420cf1dd8SToby Isaac } 26520cf1dd8SToby Isaac } else { 26620cf1dd8SToby Isaac for (i = 0; i < npoints * subNb * subNc; i++) B[i] = 0.0; 26720cf1dd8SToby Isaac } 26820cf1dd8SToby Isaac for (i = 0; i < subNb; i++) { 26920cf1dd8SToby Isaac const PetscReal *subq = &subsp->Q[i * origNb]; 27020cf1dd8SToby Isaac 27120cf1dd8SToby Isaac for (j = 0; j < npoints; j++) { 27220cf1dd8SToby Isaac for (k = 0; k < origNc; k++) phi[k] = 0.; 27320cf1dd8SToby Isaac for (k = 0; k < origNb; k++) { 27420cf1dd8SToby Isaac for (l = 0; l < origNc; l++) { 27520cf1dd8SToby Isaac phi[l] += inB[(j * origNb + k) * origNc + l] * subq[k]; 27620cf1dd8SToby Isaac } 27720cf1dd8SToby Isaac } 27820cf1dd8SToby Isaac if (subsp->Ju) { 27920cf1dd8SToby Isaac for (k = 0; k < subNc; k++) { 28020cf1dd8SToby Isaac for (l = 0; l < origNc; l++) { 28120cf1dd8SToby Isaac B[(j * subNb + i) * subNc + k] += subsp->Ju[k * origNc + l] * phi[l]; 28220cf1dd8SToby Isaac } 28320cf1dd8SToby Isaac } 28420cf1dd8SToby Isaac } 28520cf1dd8SToby Isaac else { 28620cf1dd8SToby Isaac for (k = 0; k < PetscMin(subNc, origNc); k++) { 28720cf1dd8SToby Isaac B[(j * subNb + i) * subNc + k] += phi[k]; 28820cf1dd8SToby Isaac } 28920cf1dd8SToby Isaac } 29020cf1dd8SToby Isaac } 29120cf1dd8SToby Isaac } 292*9566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(sp->dm,origNc,MPIU_REAL,&phi)); 293*9566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(sp->dm,npoints*origNb*origNc,MPIU_REAL,&inB)); 29420cf1dd8SToby Isaac } 295*9566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(sp->dm,npoints*origDim,MPIU_REAL,&inpoints)); 29620cf1dd8SToby Isaac PetscFunctionReturn(0); 29720cf1dd8SToby Isaac } 29820cf1dd8SToby Isaac 29920cf1dd8SToby Isaac PETSC_EXTERN PetscErrorCode PetscSpaceCreate_Subspace(PetscSpace sp) 30020cf1dd8SToby Isaac { 30120cf1dd8SToby Isaac PetscSpace_Subspace *subsp; 302362febeeSStefano Zampini 303362febeeSStefano Zampini PetscFunctionBegin; 304*9566063dSJacob Faibussowitsch PetscCall(PetscNewLog(sp,&subsp)); 30520cf1dd8SToby Isaac sp->data = (void *) subsp; 30620cf1dd8SToby Isaac PetscFunctionReturn(0); 30720cf1dd8SToby Isaac } 30820cf1dd8SToby Isaac 30920cf1dd8SToby Isaac static PetscErrorCode PetscSpaceGetDimension_Subspace(PetscSpace sp, PetscInt *dim) 31020cf1dd8SToby Isaac { 31120cf1dd8SToby Isaac PetscSpace_Subspace *subsp; 31220cf1dd8SToby Isaac 31320cf1dd8SToby Isaac PetscFunctionBegin; 31420cf1dd8SToby Isaac subsp = (PetscSpace_Subspace *) sp->data; 31520cf1dd8SToby Isaac *dim = subsp->Nb; 31620cf1dd8SToby Isaac PetscFunctionReturn(0); 31720cf1dd8SToby Isaac } 31820cf1dd8SToby Isaac 31920cf1dd8SToby Isaac static PetscErrorCode PetscSpaceSetUp_Subspace(PetscSpace sp) 32020cf1dd8SToby Isaac { 32120cf1dd8SToby Isaac const PetscReal *x; 32220cf1dd8SToby Isaac const PetscReal *Jx; 32320cf1dd8SToby Isaac const PetscReal *u; 32420cf1dd8SToby Isaac const PetscReal *Ju; 32520cf1dd8SToby Isaac PetscDualSpace dualSubspace; 32620cf1dd8SToby Isaac PetscSpace origSpace; 32720cf1dd8SToby Isaac PetscInt origDim, subDim, origNc, subNc, origNb, subNb, f, i, j, numPoints, offset; 32820cf1dd8SToby Isaac PetscReal *allPoints, *allWeights, *B, *V; 32920cf1dd8SToby Isaac DM dm; 33020cf1dd8SToby Isaac PetscSpace_Subspace *subsp; 33120cf1dd8SToby Isaac 33220cf1dd8SToby Isaac PetscFunctionBegin; 33320cf1dd8SToby Isaac subsp = (PetscSpace_Subspace *) sp->data; 33420cf1dd8SToby Isaac x = subsp->x; 33520cf1dd8SToby Isaac Jx = subsp->Jx; 33620cf1dd8SToby Isaac u = subsp->u; 33720cf1dd8SToby Isaac Ju = subsp->Ju; 33820cf1dd8SToby Isaac origSpace = subsp->origSpace; 33920cf1dd8SToby Isaac dualSubspace = subsp->dualSubspace; 340*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetNumComponents(origSpace,&origNc)); 341*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetNumVariables(origSpace,&origDim)); 342*9566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(dualSubspace,&dm)); 343*9566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm,&subDim)); 344*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetDimension(origSpace,&origNb)); 345*9566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(dualSubspace,&subNb)); 346*9566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumComponents(dualSubspace,&subNc)); 34720cf1dd8SToby Isaac 34820cf1dd8SToby Isaac for (f = 0, numPoints = 0; f < subNb; f++) { 34920cf1dd8SToby Isaac PetscQuadrature q; 35020cf1dd8SToby Isaac PetscInt qNp; 35120cf1dd8SToby Isaac 352*9566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(dualSubspace,f,&q)); 353*9566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q,NULL,NULL,&qNp,NULL,NULL)); 35420cf1dd8SToby Isaac numPoints += qNp; 35520cf1dd8SToby Isaac } 356*9566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(subNb*origNb,&V)); 357*9566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(numPoints*origDim,&allPoints,numPoints*origNc,&allWeights,numPoints*origNb*origNc,&B)); 35820cf1dd8SToby Isaac for (f = 0, offset = 0; f < subNb; f++) { 35920cf1dd8SToby Isaac PetscQuadrature q; 36020cf1dd8SToby Isaac PetscInt qNp, p; 36120cf1dd8SToby Isaac const PetscReal *qp; 36220cf1dd8SToby Isaac const PetscReal *qw; 36320cf1dd8SToby Isaac 364*9566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(dualSubspace,f,&q)); 365*9566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q,NULL,NULL,&qNp,&qp,&qw)); 36620cf1dd8SToby Isaac for (p = 0; p < qNp; p++, offset++) { 36720cf1dd8SToby Isaac if (x) { 36820cf1dd8SToby Isaac for (i = 0; i < origDim; i++) allPoints[origDim * offset + i] = x[i]; 36920cf1dd8SToby Isaac } else { 37020cf1dd8SToby Isaac for (i = 0; i < origDim; i++) allPoints[origDim * offset + i] = 0.0; 37120cf1dd8SToby Isaac } 37220cf1dd8SToby Isaac if (Jx) { 37320cf1dd8SToby Isaac for (i = 0; i < origDim; i++) { 37420cf1dd8SToby Isaac for (j = 0; j < subDim; j++) { 37520cf1dd8SToby Isaac allPoints[origDim * offset + i] += Jx[i * subDim + j] * qp[j]; 37620cf1dd8SToby Isaac } 37720cf1dd8SToby Isaac } 37820cf1dd8SToby Isaac } else { 37920cf1dd8SToby Isaac for (i = 0; i < PetscMin(subDim, origDim); i++) allPoints[origDim * offset + i] += qp[i]; 38020cf1dd8SToby Isaac } 38120cf1dd8SToby Isaac for (i = 0; i < origNc; i++) allWeights[origNc * offset + i] = 0.0; 38220cf1dd8SToby Isaac if (Ju) { 38320cf1dd8SToby Isaac for (i = 0; i < origNc; i++) { 38420cf1dd8SToby Isaac for (j = 0; j < subNc; j++) { 38520cf1dd8SToby Isaac allWeights[offset * origNc + i] += qw[j] * Ju[j * origNc + i]; 38620cf1dd8SToby Isaac } 38720cf1dd8SToby Isaac } 38820cf1dd8SToby Isaac } else { 38920cf1dd8SToby Isaac for (i = 0; i < PetscMin(subNc, origNc); i++) allWeights[offset * origNc + i] += qw[i]; 39020cf1dd8SToby Isaac } 39120cf1dd8SToby Isaac } 39220cf1dd8SToby Isaac } 393*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceEvaluate(origSpace,numPoints,allPoints,B,NULL,NULL)); 39420cf1dd8SToby Isaac for (f = 0, offset = 0; f < subNb; f++) { 39520cf1dd8SToby Isaac PetscInt b, p, s, qNp; 39620cf1dd8SToby Isaac PetscQuadrature q; 39720cf1dd8SToby Isaac const PetscReal *qw; 39820cf1dd8SToby Isaac 399*9566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(dualSubspace,f,&q)); 400*9566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q,NULL,NULL,&qNp,NULL,&qw)); 40120cf1dd8SToby Isaac if (u) { 40220cf1dd8SToby Isaac for (b = 0; b < origNb; b++) { 40320cf1dd8SToby Isaac for (s = 0; s < subNc; s++) { 40420cf1dd8SToby Isaac V[f * origNb + b] += qw[s] * u[s]; 40520cf1dd8SToby Isaac } 40620cf1dd8SToby Isaac } 40720cf1dd8SToby Isaac } else { 40820cf1dd8SToby Isaac for (b = 0; b < origNb; b++) V[f * origNb + b] = 0.0; 40920cf1dd8SToby Isaac } 41020cf1dd8SToby Isaac for (p = 0; p < qNp; p++, offset++) { 41120cf1dd8SToby Isaac for (b = 0; b < origNb; b++) { 41220cf1dd8SToby Isaac for (s = 0; s < origNc; s++) { 41320cf1dd8SToby Isaac V[f * origNb + b] += B[(offset * origNb + b) * origNc + s] * allWeights[offset * origNc + s]; 41420cf1dd8SToby Isaac } 41520cf1dd8SToby Isaac } 41620cf1dd8SToby Isaac } 41720cf1dd8SToby Isaac } 41820cf1dd8SToby Isaac /* orthnormalize rows of V */ 41920cf1dd8SToby Isaac for (f = 0; f < subNb; f++) { 42020cf1dd8SToby Isaac PetscReal rho = 0.0, scal; 42120cf1dd8SToby Isaac 42220cf1dd8SToby Isaac for (i = 0; i < origNb; i++) rho += PetscSqr(V[f * origNb + i]); 42320cf1dd8SToby Isaac 42420cf1dd8SToby Isaac scal = 1. / PetscSqrtReal(rho); 42520cf1dd8SToby Isaac 42620cf1dd8SToby Isaac for (i = 0; i < origNb; i++) V[f * origNb + i] *= scal; 42720cf1dd8SToby Isaac for (j = f + 1; j < subNb; j++) { 42820cf1dd8SToby Isaac for (i = 0, scal = 0.; i < origNb; i++) scal += V[f * origNb + i] * V[j * origNb + i]; 42920cf1dd8SToby Isaac for (i = 0; i < origNb; i++) V[j * origNb + i] -= V[f * origNb + i] * scal; 43020cf1dd8SToby Isaac } 43120cf1dd8SToby Isaac } 432*9566063dSJacob Faibussowitsch PetscCall(PetscFree3(allPoints,allWeights,B)); 43320cf1dd8SToby Isaac subsp->Q = V; 43420cf1dd8SToby Isaac PetscFunctionReturn(0); 43520cf1dd8SToby Isaac } 43620cf1dd8SToby Isaac 43720cf1dd8SToby Isaac static PetscErrorCode PetscSpacePolynomialGetTensor_Subspace(PetscSpace sp, PetscBool *poly) 43820cf1dd8SToby Isaac { 43920cf1dd8SToby Isaac PetscSpace_Subspace *subsp = (PetscSpace_Subspace *) sp->data; 44020cf1dd8SToby Isaac 44120cf1dd8SToby Isaac PetscFunctionBegin; 44220cf1dd8SToby Isaac *poly = PETSC_FALSE; 443*9566063dSJacob Faibussowitsch PetscCall(PetscSpacePolynomialGetTensor(subsp->origSpace,poly)); 44420cf1dd8SToby Isaac if (*poly) { 44520cf1dd8SToby Isaac if (subsp->Jx) { 44620cf1dd8SToby Isaac PetscInt subDim, origDim, i, j; 44720cf1dd8SToby Isaac PetscInt maxnnz; 44820cf1dd8SToby Isaac 449*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetNumVariables(subsp->origSpace,&origDim)); 450*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetNumVariables(sp,&subDim)); 45120cf1dd8SToby Isaac maxnnz = 0; 45220cf1dd8SToby Isaac for (i = 0; i < origDim; i++) { 45320cf1dd8SToby Isaac PetscInt nnz = 0; 45420cf1dd8SToby Isaac 45520cf1dd8SToby Isaac for (j = 0; j < subDim; j++) nnz += (subsp->Jx[i * subDim + j] != 0.); 45620cf1dd8SToby Isaac maxnnz = PetscMax(maxnnz,nnz); 45720cf1dd8SToby Isaac } 45820cf1dd8SToby Isaac for (j = 0; j < subDim; j++) { 45920cf1dd8SToby Isaac PetscInt nnz = 0; 46020cf1dd8SToby Isaac 46120cf1dd8SToby Isaac for (i = 0; i < origDim; i++) nnz += (subsp->Jx[i * subDim + j] != 0.); 46220cf1dd8SToby Isaac maxnnz = PetscMax(maxnnz,nnz); 46320cf1dd8SToby Isaac } 46420cf1dd8SToby Isaac if (maxnnz > 1) *poly = PETSC_FALSE; 46520cf1dd8SToby Isaac } 46620cf1dd8SToby Isaac } 46720cf1dd8SToby Isaac PetscFunctionReturn(0); 46820cf1dd8SToby Isaac } 46920cf1dd8SToby Isaac 47020cf1dd8SToby Isaac static PetscErrorCode PetscSpaceInitialize_Subspace(PetscSpace sp) 47120cf1dd8SToby Isaac { 47220cf1dd8SToby Isaac PetscFunctionBegin; 47320cf1dd8SToby Isaac sp->ops->setup = PetscSpaceSetUp_Subspace; 47420cf1dd8SToby Isaac sp->ops->view = PetscSpaceView_Subspace; 47520cf1dd8SToby Isaac sp->ops->destroy = PetscSpaceDestroy_Subspace; 47620cf1dd8SToby Isaac sp->ops->getdimension = PetscSpaceGetDimension_Subspace; 47720cf1dd8SToby Isaac sp->ops->evaluate = PetscSpaceEvaluate_Subspace; 478*9566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject) sp, "PetscSpacePolynomialGetTensor_C", PetscSpacePolynomialGetTensor_Subspace)); 47920cf1dd8SToby Isaac PetscFunctionReturn(0); 48020cf1dd8SToby Isaac } 48120cf1dd8SToby Isaac 48220cf1dd8SToby Isaac PetscErrorCode PetscSpaceCreateSubspace(PetscSpace origSpace, PetscDualSpace dualSubspace, PetscReal *x, PetscReal *Jx, PetscReal *u, PetscReal *Ju, PetscCopyMode copymode, PetscSpace *subspace) 48320cf1dd8SToby Isaac { 48420cf1dd8SToby Isaac PetscSpace_Subspace *subsp; 48520cf1dd8SToby Isaac PetscInt origDim, subDim, origNc, subNc, subNb; 48620cf1dd8SToby Isaac PetscInt order; 48720cf1dd8SToby Isaac DM dm; 48820cf1dd8SToby Isaac 48920cf1dd8SToby Isaac PetscFunctionBegin; 49020cf1dd8SToby Isaac PetscValidHeaderSpecific(origSpace,PETSCSPACE_CLASSID,1); 49120cf1dd8SToby Isaac PetscValidHeaderSpecific(dualSubspace,PETSCDUALSPACE_CLASSID,2); 49220cf1dd8SToby Isaac if (x) PetscValidRealPointer(x,3); 49320cf1dd8SToby Isaac if (Jx) PetscValidRealPointer(Jx,4); 49420cf1dd8SToby Isaac if (u) PetscValidRealPointer(u,5); 49520cf1dd8SToby Isaac if (Ju) PetscValidRealPointer(Ju,6); 496064a246eSJacob Faibussowitsch PetscValidPointer(subspace,8); 497*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetNumComponents(origSpace,&origNc)); 498*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetNumVariables(origSpace,&origDim)); 499*9566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(dualSubspace,&dm)); 500*9566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm,&subDim)); 501*9566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(dualSubspace,&subNb)); 502*9566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumComponents(dualSubspace,&subNc)); 503*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)origSpace),subspace)); 504*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetType(*subspace,PETSCSPACESUBSPACE)); 505*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumVariables(*subspace,subDim)); 506*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumComponents(*subspace,subNc)); 507*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetDegree(origSpace,&order,NULL)); 508*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetDegree(*subspace,order,PETSC_DETERMINE)); 50920cf1dd8SToby Isaac subsp = (PetscSpace_Subspace *) (*subspace)->data; 51020cf1dd8SToby Isaac subsp->Nb = subNb; 51120cf1dd8SToby Isaac switch (copymode) { 51220cf1dd8SToby Isaac case PETSC_OWN_POINTER: 51320cf1dd8SToby Isaac if (x) subsp->x_alloc = x; 51420cf1dd8SToby Isaac if (Jx) subsp->Jx_alloc = Jx; 51520cf1dd8SToby Isaac if (u) subsp->u_alloc = u; 51620cf1dd8SToby Isaac if (Ju) subsp->Ju_alloc = Ju; 51720cf1dd8SToby Isaac case PETSC_USE_POINTER: 51820cf1dd8SToby Isaac if (x) subsp->x = x; 51920cf1dd8SToby Isaac if (Jx) subsp->Jx = Jx; 52020cf1dd8SToby Isaac if (u) subsp->u = u; 52120cf1dd8SToby Isaac if (Ju) subsp->Ju = Ju; 52220cf1dd8SToby Isaac break; 52320cf1dd8SToby Isaac case PETSC_COPY_VALUES: 52420cf1dd8SToby Isaac if (x) { 525*9566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(origDim,&subsp->x_alloc)); 526*9566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(subsp->x_alloc,x,origDim)); 52720cf1dd8SToby Isaac subsp->x = subsp->x_alloc; 52820cf1dd8SToby Isaac } 52920cf1dd8SToby Isaac if (Jx) { 530*9566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(origDim * subDim,&subsp->Jx_alloc)); 531*9566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(subsp->Jx_alloc,Jx,origDim * subDim)); 53220cf1dd8SToby Isaac subsp->Jx = subsp->Jx_alloc; 53320cf1dd8SToby Isaac } 53420cf1dd8SToby Isaac if (u) { 535*9566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(subNc,&subsp->u_alloc)); 536*9566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(subsp->u_alloc,u,subNc)); 53720cf1dd8SToby Isaac subsp->u = subsp->u_alloc; 53820cf1dd8SToby Isaac } 53920cf1dd8SToby Isaac if (Ju) { 540*9566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(origNc * subNc,&subsp->Ju_alloc)); 541*9566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(subsp->Ju_alloc,Ju,origNc * subNc)); 54220cf1dd8SToby Isaac subsp->Ju = subsp->Ju_alloc; 54320cf1dd8SToby Isaac } 54420cf1dd8SToby Isaac break; 54520cf1dd8SToby Isaac default: 54620cf1dd8SToby Isaac SETERRQ(PetscObjectComm((PetscObject)origSpace),PETSC_ERR_ARG_OUTOFRANGE,"Unknown copy mode"); 54720cf1dd8SToby Isaac } 548*9566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)origSpace)); 54920cf1dd8SToby Isaac subsp->origSpace = origSpace; 550*9566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dualSubspace)); 55120cf1dd8SToby Isaac subsp->dualSubspace = dualSubspace; 552*9566063dSJacob Faibussowitsch PetscCall(PetscSpaceInitialize_Subspace(*subspace)); 55320cf1dd8SToby Isaac PetscFunctionReturn(0); 55420cf1dd8SToby Isaac } 555