Skip to content

Commit d2f5d15

Browse files
committed
SWE: Initial implementation of generic restriction matrix
This generic restriction matrix does not only have 1's but also the coordinate transformations needed from the coord system of the nodes that are on the panel edges (lat, long) to the local ones of the nodes on the adjacent panels
1 parent ae889c7 commit d2f5d15

File tree

4 files changed

+148
-164
lines changed

4 files changed

+148
-164
lines changed

examples/fluids/shallow-water/shallowwater.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,8 +374,8 @@ int main(int argc, char **argv) {
374374
// Setup transformation matrix different panels of the cube
375375
Mat T;
376376
EdgeNode edgenodes;
377-
ierr = FindPanelEdgeNodes(dm, &physCtxData, ncompq, &nedgenodes, &edgenodes,
378-
&T);
377+
ierr = FindPanelEdgeNodes(dm, &physCtxData, ncompq, degree, topodim,
378+
&nedgenodes, &edgenodes, &T);
379379
CHKERRQ(ierr);
380380

381381
// Transform coordinate according to their panel systems

examples/fluids/shallow-water/src/setup.c

Lines changed: 127 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ problemData problemOptions[] = {
7676
// -----------------------------------------------------------------------------
7777

7878
PetscErrorCode FindPanelEdgeNodes(DM dm, PhysicsContext phys_ctx,
79-
PetscInt ncomp, PetscInt *edgenodecnt,
79+
PetscInt ncomp, PetscInt degree,
80+
PetscInt topodim, PetscInt *edgenodecnt,
8081
EdgeNode *edgenodes, Mat *T) {
8182

8283
PetscInt ierr;
@@ -154,8 +155,8 @@ PetscErrorCode FindPanelEdgeNodes(DM dm, PhysicsContext phys_ctx,
154155
(*edgenodecnt)++;
155156
}
156157
}
157-
// ierr = SetupPanelCoordTransformations(dm, phys_ctx, ncomp, *edgenodes,
158-
// *edgenodecnt, T); CHKERRQ(ierr);
158+
ierr = SetupRestrictionMatrix(dm, phys_ctx, degree, ncomp, *edgenodes,
159+
*edgenodecnt, T); CHKERRQ(ierr);
159160

160161
// Free heap
161162
ierr = PetscFree2(bitmaploc, bitmap); CHKERRQ(ierr);
@@ -166,157 +167,147 @@ PetscErrorCode FindPanelEdgeNodes(DM dm, PhysicsContext phys_ctx,
166167
// -----------------------------------------------------------------------------
167168
// Auxiliary function that sets up all coordinate transformations between panels
168169
// -----------------------------------------------------------------------------
169-
PetscErrorCode SetupPanelCoordTransformations(DM dm, PhysicsContext phys_ctx,
170-
PetscInt ncomp,
171-
EdgeNode edgenodes,
172-
PetscInt nedgenodes, Mat *T) {
173-
PetscInt ierr;
170+
PetscErrorCode SetupRestrictionMatrix(DM dm, PhysicsContext phys_ctx,
171+
PetscInt degree, PetscInt ncomp,
172+
EdgeNode edgenodes, PetscInt nedgenodes,
173+
Mat *T) {
174+
PetscInt ierr, nnodes, c, cStart, cEnd, nelem, numP, gdofs;
174175
MPI_Comm comm;
175176
Vec X;
176-
PetscInt gdofs;
177+
PetscSection section;
177178
const PetscScalar *xarray;
178179

179180
PetscFunctionBeginUser;
180181
ierr = PetscObjectGetComm((PetscObject)dm, &comm); CHKERRQ(ierr);
182+
ierr = DMGetSection(dm, &section); CHKERRQ(ierr);
181183

182184
ierr = DMGetCoordinates(dm, &X); CHKERRQ(ierr);
183185
ierr = VecGetSize(X, &gdofs); CHKERRQ(ierr);
186+
nnodes = gdofs/ncomp;
187+
ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd); CHKERRQ(ierr);
188+
nelem = cEnd - cStart;
189+
numP = degree + 1;
184190

185191
// Preallocate sparse matrix
186-
ierr = MatCreateBAIJ(comm, 2, PETSC_DECIDE, PETSC_DECIDE, 4*gdofs/ncomp,
187-
4*gdofs/ncomp, 2, NULL, 0, NULL, T); CHKERRQ(ierr);
188-
for (PetscInt i=0; i < 4*gdofs/ncomp; i++) {
189-
ierr = MatSetValue(*T, i, i, 1., INSERT_VALUES); CHKERRQ(ierr);
190-
}
192+
ierr = MatCreateAIJ(comm, nelem*numP*numP*ncomp, nnodes*ncomp,
193+
PETSC_DETERMINE, PETSC_DETERMINE, 2, NULL,
194+
nnodes*ncomp, NULL, T); CHKERRQ(ierr);
191195

192-
ierr = VecGetArrayRead(X, &xarray); CHKERRQ(ierr);
193-
PetscScalar R = phys_ctx->R;
194-
// Nodes loop
195-
for (PetscInt i=0; i < gdofs; i += ncomp) {
196-
// Read global Cartesian coordinates
197-
PetscScalar x[3] = {xarray[i*ncomp + 0],
198-
xarray[i*ncomp + 1],
199-
xarray[i*ncomp + 2]
200-
};
201-
// Normalize quadrature point coordinates to sphere
202-
PetscScalar rad = sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]);
203-
x[0] *= R / rad;
204-
x[1] *= R / rad;
205-
x[2] *= R / rad;
206-
// Compute latitude and longitude
207-
const PetscScalar theta = asin(x[2] / R); // latitude
208-
const PetscScalar lambda = atan2(x[1], x[0]); // longitude
209-
210-
// For P_0 (front), P_1 (east), P_2 (back), P_3 (west):
211-
PetscScalar T00 = cos(theta)*cos(lambda) * cos(lambda);
212-
PetscScalar T01 = cos(theta)*cos(lambda) * 0.;
213-
PetscScalar T10 = cos(theta)*cos(lambda) * -sin(theta)*sin(lambda);
214-
PetscScalar T11 = cos(theta)*cos(lambda) * cos(theta);
215-
const PetscScalar T_lateral[2][2] = {{T00,
216-
T01},
217-
{T10,
218-
T11}
219-
};
220-
PetscScalar Tinv00 = 1./(cos(theta)*cos(lambda)) * (1./cos(lambda));
221-
PetscScalar Tinv01 = 1./(cos(theta)*cos(lambda)) * 0.;
222-
PetscScalar Tinv10 = 1./(cos(theta)*cos(lambda)) * tan(theta)*tan(lambda);
223-
PetscScalar Tinv11 = 1./(cos(theta)*cos(lambda)) * (1./cos(theta));
224-
const PetscScalar T_lateralinv[2][2] = {{Tinv00,
225-
Tinv01},
226-
{Tinv10,
227-
Tinv11}
228-
};
229-
// For P4 (north):
230-
T00 = sin(theta) * cos(lambda);
231-
T01 = sin(theta) * sin(lambda);
232-
T10 = sin(theta) * -sin(theta)*sin(lambda);
233-
T11 = sin(theta) * sin(theta)*cos(lambda);
234-
const PetscScalar T_top[2][2] = {{T00,
235-
T01},
236-
{T10,
237-
T11}
238-
};
239-
Tinv00 = 1./(sin(theta)*sin(theta)) * sin(theta)*cos(lambda);
240-
Tinv01 = 1./(sin(theta)*sin(theta)) * (-sin(lambda));
241-
Tinv10 = 1./(sin(theta)*sin(theta)) * sin(theta)*sin(lambda);
242-
Tinv11 = 1./(sin(theta)*sin(theta)) * cos(lambda);
243-
const PetscScalar T_topinv[2][2] = {{Tinv00,
244-
Tinv01},
245-
{Tinv10,
246-
Tinv11}
247-
};
248-
249-
// For P5 (south):
250-
T00 = sin(theta) * (-cos(theta));
251-
T01 = sin(theta) * sin(lambda);
252-
T10 = sin(theta) * sin(theta)*sin(lambda);
253-
T11 = sin(theta) * sin(theta)*cos(lambda);
254-
const PetscScalar T_bottom[2][2] = {{T00,
255-
T01},
256-
{T10,
257-
T11}
258-
};
259-
Tinv00 = 1./(sin(theta)*sin(theta)) * (-sin(theta)*cos(lambda));
260-
Tinv01 = 1./(sin(theta)*sin(theta)) * sin(lambda);
261-
Tinv10 = 1./(sin(theta)*sin(theta)) * sin(theta)*sin(lambda);
262-
Tinv11 = 1./(sin(theta)*sin(theta)) * cos(lambda);
263-
const PetscScalar T_bottominv[2][2] = {{Tinv00,
264-
Tinv01},
265-
{Tinv10,
266-
Tinv11}
267-
};
268-
269-
const PetscScalar (*transforms[6])[2][2] = {&T_lateral,
270-
&T_lateral,
271-
&T_lateral,
272-
&T_lateral,
273-
&T_top,
274-
&T_bottom
275-
};
276-
277-
const PetscScalar (*inv_transforms[6])[2][2] = {&T_lateralinv,
278-
&T_lateralinv,
279-
&T_lateralinv,
280-
&T_lateralinv,
281-
&T_topinv,
282-
&T_bottominv
283-
};
196+
// Loop over elements
197+
for (c = cStart; c < cEnd; c++) {
198+
PetscInt numindices, *indices, i;
199+
ierr = DMPlexGetClosureIndices(dm, section, section, c, PETSC_TRUE,
200+
&numindices, &indices, NULL, NULL);
201+
CHKERRQ(ierr);
202+
for (i = 0; i < numindices; i += ncomp) {
203+
for (PetscInt j = 0; j < ncomp; j++) {
204+
if (indices[i+j] != indices[i] + (PetscInt)(copysign(j, indices[i])))
205+
SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
206+
"Cell %D closure indices not interlaced", c);
207+
}
208+
// NO BC on closed surfaces
209+
PetscInt loc = indices[i];
284210

285-
for (PetscInt e = 0; e < nedgenodes; e++) {
286-
if (edgenodes[e].idx == i) {
287-
const PetscScalar (*matrixA)[2][2] = inv_transforms[edgenodes[e].panelA];
288-
const PetscScalar (*matrixB)[2][2] = transforms[edgenodes[e].panelB];
289-
290-
// inv_transform * transform (A^{-1}*B)
291-
// This product represents the mapping from coordinate system A
292-
// to spherical coordinates and then to coordinate system B. Vice versa
293-
// for transform * inv_transform (B^{-1}*A)
294-
PetscScalar matrixAB[2][2], matrixBA[2][2];
295-
for (int j=0; j<2; j++) {
296-
for (int k=0; k<2; k++) {
297-
matrixAB[j][k] = matrixBA[j][k] = 0;
298-
for (int l=0; l<2; l++) {
299-
matrixAB[j][k] += (*matrixA)[j][l] * (*matrixB)[l][k];
300-
matrixBA[j][k] += (*matrixB)[j][l] * (*matrixA)[l][k];
301-
}
302-
}
211+
// Query element panel
212+
PetscInt panel;
213+
ierr = DMGetLabelValue(dm, "panel", c, &panel); CHKERRQ(ierr);
214+
215+
// Query if edge node
216+
PetscBool isEdgeNode = PETSC_FALSE;
217+
218+
for (PetscInt e = 0; e < nedgenodes; e++) {
219+
if (edgenodes[e].idx == loc) {
220+
isEdgeNode = PETSC_TRUE;
221+
break;
303222
}
304-
PetscInt idxAB[2] = {4*i/ncomp + 0, 4*i/ncomp +1};
305-
PetscInt idxBA[2] = {4*i/ncomp + 2, 4*i/ncomp +3};
306-
ierr = MatSetValues(*T, 2, idxAB, 2, idxAB, (PetscScalar *)matrixAB,
307-
INSERT_VALUES); CHKERRQ(ierr);
308-
ierr = MatSetValues(*T, 2, idxBA, 2, idxBA, (PetscScalar *)matrixBA,
309-
INSERT_VALUES); CHKERRQ(ierr);
310223
}
224+
225+
PetscScalar entries[9];
226+
if (isEdgeNode) {
227+
ierr = VecGetArrayRead(X, &xarray); CHKERRQ(ierr);
228+
PetscScalar R = phys_ctx->R;
229+
// Read global Cartesian coordinates
230+
PetscScalar x[3] = {xarray[loc + 0],
231+
xarray[loc + 1],
232+
xarray[loc + 2]
233+
};
234+
// Restore array read
235+
ierr = VecRestoreArrayRead(X, &xarray); CHKERRQ(ierr);
236+
237+
// Normalize quadrature point coordinates to sphere
238+
PetscScalar rad = sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]);
239+
x[0] *= R / rad;
240+
x[1] *= R / rad;
241+
x[2] *= R / rad;
242+
// Compute latitude and longitude
243+
const PetscScalar theta = asin(x[2] / R); // latitude
244+
const PetscScalar lambda = atan2(x[1], x[0]); // longitude
245+
246+
PetscScalar T00, T01, T10, T11;
247+
248+
switch (panel) {
249+
case 0:
250+
case 1:
251+
case 2:
252+
case 3:
253+
// For P_0 (front), P_1 (east), P_2 (back), P_3 (west):
254+
T00 = cos(theta)*cos(lambda) * cos(lambda);
255+
T01 = cos(theta)*cos(lambda) * 0.;
256+
T10 = cos(theta)*cos(lambda) * -sin(theta)*sin(lambda);
257+
T11 = cos(theta)*cos(lambda) * cos(theta);
258+
break;
259+
case 4:
260+
// For P4 (north):
261+
T00 = sin(theta) * cos(lambda);
262+
T01 = sin(theta) * sin(lambda);
263+
T10 = sin(theta) * -sin(theta)*sin(lambda);
264+
T11 = sin(theta) * sin(theta)*cos(lambda);
265+
break;
266+
case 5:
267+
// For P5 (south):
268+
T00 = sin(theta) * (-cos(theta));
269+
T01 = sin(theta) * sin(lambda);
270+
T10 = sin(theta) * sin(theta)*sin(lambda);
271+
T11 = sin(theta) * sin(theta)*cos(lambda);
272+
break;
273+
}
274+
275+
entries[0] = T00;
276+
entries[1] = T01;
277+
entries[2] = 0.;
278+
entries[3] = T10;
279+
entries[4] = T11;
280+
entries[5] = 0.;
281+
entries[6] = 0.;
282+
entries[7] = 0.;
283+
entries[8] = 1.;
284+
285+
} else {
286+
entries[0] = 1.;
287+
entries[1] = 0.;
288+
entries[2] = 0.;
289+
entries[3] = 0.;
290+
entries[4] = 1.;
291+
entries[5] = 0.;
292+
entries[6] = 0.;
293+
entries[7] = 0.;
294+
entries[8] = 1.;
295+
}
296+
PetscInt elem = c - cStart;
297+
PetscInt idxrow[3] = {elem*loc + 0, elem*loc + 1, elem*loc + 2};
298+
PetscInt idxcol[3] = {loc + 0, loc + 1, loc + 2};
299+
ierr = MatSetValues(*T, ncomp, idxrow, ncomp, idxcol, entries,
300+
INSERT_VALUES); CHKERRQ(ierr);
311301
}
302+
ierr = DMPlexRestoreClosureIndices(dm, section, section, c, PETSC_TRUE,
303+
&numindices, &indices, NULL, NULL);
304+
CHKERRQ(ierr);
312305
}
306+
313307
// Assemble matrix for all node transformations
314308
ierr = MatAssemblyBegin(*T, MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
315309
ierr = MatAssemblyEnd(*T, MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
316310

317-
// Restore array read
318-
ierr = VecRestoreArrayRead(X, &xarray); CHKERRQ(ierr);
319-
320311
PetscFunctionReturn(0);
321312
}
322313

@@ -377,9 +368,7 @@ PetscErrorCode TransformCoords(DM dm, Vec Xloc, const PetscInt ncompx,
377368
xpanelslocarray[n*ncompx+1] = lambda;
378369
xpanelslocarray[n*ncompx+2] = -1;
379370
}
380-
381371
else {
382-
383372
switch (panel) {
384373
case 0:
385374
x = l * (Y / X);
@@ -680,9 +669,6 @@ PetscErrorCode SetupLibceed(DM dm, Ceed ceed, CeedInt degree, CeedInt qextra,
680669
CHKERRQ(ierr);
681670

682671
// CEED restrictions
683-
// TODO: After the resitrction matrix is implemented comment the following line
684-
ierr = CreateRestrictionPlex(ceed, dmcoord, numP, ncompq, &Erestrictq);
685-
CHKERRQ(ierr);
686672
ierr = CreateRestrictionPlex(ceed, dmcoord, 2, ncompx, &Erestrictx);
687673
CHKERRQ(ierr);
688674

@@ -693,11 +679,9 @@ PetscErrorCode SetupLibceed(DM dm, Ceed ceed, CeedInt degree, CeedInt qextra,
693679
CEED_STRIDES_BACKEND, &Erestrictqdi);
694680
// Solution vec restriction is a strided (identity) because we use a user
695681
// mat mult before and after operator apply
696-
// TODO: After the restriction matrix for the solution vector is implemented,
697-
// decomment the following line
698-
// CeedElemRestrictionCreateStrided(ceed, nelem, numP*numP, ncompq,
699-
// ncompq*nelem*numP*numP,
700-
// CEED_STRIDES_BACKEND, &Erestrictq);
682+
CeedElemRestrictionCreateStrided(ceed, nelem, numP*numP, ncompq,
683+
ncompq*nelem*numP*numP,
684+
CEED_STRIDES_BACKEND, &Erestrictq);
701685

702686
// Element coordinates
703687
ierr = DMGetCoordinatesLocal(dm, &Xloc); CHKERRQ(ierr);

0 commit comments

Comments
 (0)