Actual source code: ex1.c
1: #include <petscfe.h>
2: #include <petscdmplex.h>
3: #include <petsc/private/hashmap.h>
4: #include <petsc/private/dmpleximpl.h>
5: #include <petsc/private/petscfeimpl.h>
7: const char help[] = "Test PETSCDUALSPACELAGRANGE\n";
9: typedef struct _PetscHashLagKey {
10: PetscInt dim;
11: PetscInt order;
12: PetscInt formDegree;
13: PetscBool trimmed;
14: PetscInt tensor;
15: PetscBool continuous;
16: } PetscHashLagKey;
18: #define PetscHashLagKeyHash(key) \
19: PetscHashCombine(PetscHashCombine(PetscHashCombine(PetscHashInt((key).dim), PetscHashInt((key).order)), PetscHashInt((key).formDegree)), PetscHashCombine(PetscHashCombine(PetscHashInt((key).trimmed), PetscHashInt((key).tensor)), PetscHashInt((key).continuous)))
21: #define PetscHashLagKeyEqual(k1, k2) \
22: (((k1).dim == (k2).dim) ? ((k1).order == (k2).order) ? ((k1).formDegree == (k2).formDegree) ? ((k1).trimmed == (k2).trimmed) ? ((k1).tensor == (k2).tensor) ? ((k1).continuous == (k2).continuous) : 0 : 0 : 0 : 0 : 0)
24: PETSC_HASH_MAP(HashLag, PetscHashLagKey, PetscInt, PetscHashLagKeyHash, PetscHashLagKeyEqual, 0)
26: static PetscErrorCode ExpectedNumDofs_Total(PetscInt dim, PetscInt order, PetscInt formDegree, PetscBool trimmed, PetscInt tensor, PetscInt nCopies, PetscInt *nDofs);
27: static PetscErrorCode ExpectedNumDofs_Interior(PetscInt dim, PetscInt order, PetscInt formDegree, PetscBool trimmed, PetscInt tensor, PetscInt nCopies, PetscInt *nDofs);
29: static PetscErrorCode ExpectedNumDofs_Total(PetscInt dim, PetscInt order, PetscInt formDegree, PetscBool trimmed, PetscInt tensor, PetscInt nCopies, PetscInt *nDofs)
30: {
31: PetscFunctionBegin;
32: formDegree = PetscAbsInt(formDegree);
33: /* see femtable.org for the source of most of these values */
34: *nDofs = -1;
35: if (tensor == 0) { /* simplex spaces */
36: if (trimmed) {
37: PetscInt rnchooserk;
38: PetscInt rkm1choosek;
40: PetscCall(PetscDTBinomialInt(order + dim, order + formDegree, &rnchooserk));
41: PetscCall(PetscDTBinomialInt(order + formDegree - 1, formDegree, &rkm1choosek));
42: *nDofs = rnchooserk * rkm1choosek * nCopies;
43: } else {
44: PetscInt rnchooserk;
45: PetscInt rkchoosek;
47: PetscCall(PetscDTBinomialInt(order + dim, order + formDegree, &rnchooserk));
48: PetscCall(PetscDTBinomialInt(order + formDegree, formDegree, &rkchoosek));
49: *nDofs = rnchooserk * rkchoosek * nCopies;
50: }
51: } else if (tensor == 1) { /* hypercubes */
52: if (trimmed) {
53: PetscInt nchoosek;
54: PetscInt rpowk, rp1pownmk;
56: PetscCall(PetscDTBinomialInt(dim, formDegree, &nchoosek));
57: rpowk = PetscPowInt(order, formDegree);
58: rp1pownmk = PetscPowInt(order + 1, dim - formDegree);
59: *nDofs = nchoosek * rpowk * rp1pownmk * nCopies;
60: } else {
61: PetscInt nchoosek;
62: PetscInt rp1pown;
64: PetscCall(PetscDTBinomialInt(dim, formDegree, &nchoosek));
65: rp1pown = PetscPowInt(order + 1, dim);
66: *nDofs = nchoosek * rp1pown * nCopies;
67: }
68: } else { /* prism */
69: PetscInt tracek = 0;
70: PetscInt tracekm1 = 0;
71: PetscInt fiber0 = 0;
72: PetscInt fiber1 = 0;
74: if (formDegree < dim) {
75: PetscCall(ExpectedNumDofs_Total(dim - 1, order, formDegree, trimmed, 0, 1, &tracek));
76: PetscCall(ExpectedNumDofs_Total(1, order, 0, trimmed, 0, 1, &fiber0));
77: }
78: if (formDegree > 0) {
79: PetscCall(ExpectedNumDofs_Total(dim - 1, order, formDegree - 1, trimmed, 0, 1, &tracekm1));
80: PetscCall(ExpectedNumDofs_Total(1, order, 1, trimmed, 0, 1, &fiber1));
81: }
82: *nDofs = (tracek * fiber0 + tracekm1 * fiber1) * nCopies;
83: }
84: PetscFunctionReturn(PETSC_SUCCESS);
85: }
87: static PetscErrorCode ExpectedNumDofs_Interior(PetscInt dim, PetscInt order, PetscInt formDegree, PetscBool trimmed, PetscInt tensor, PetscInt nCopies, PetscInt *nDofs)
88: {
89: PetscFunctionBegin;
90: formDegree = PetscAbsInt(formDegree);
91: /* see femtable.org for the source of most of these values */
92: *nDofs = -1;
93: if (tensor == 0) { /* simplex spaces */
94: if (trimmed) {
95: if (order + formDegree > dim) {
96: PetscInt eorder = order + formDegree - dim - 1;
97: PetscInt eformDegree = dim - formDegree;
98: PetscInt rnchooserk;
99: PetscInt rkchoosek;
101: PetscCall(PetscDTBinomialInt(eorder + dim, eorder + eformDegree, &rnchooserk));
102: PetscCall(PetscDTBinomialInt(eorder + eformDegree, eformDegree, &rkchoosek));
103: *nDofs = rnchooserk * rkchoosek * nCopies;
104: } else {
105: *nDofs = 0;
106: }
108: } else {
109: if (order + formDegree > dim) {
110: PetscInt eorder = order + formDegree - dim;
111: PetscInt eformDegree = dim - formDegree;
112: PetscInt rnchooserk;
113: PetscInt rkm1choosek;
115: PetscCall(PetscDTBinomialInt(eorder + dim, eorder + eformDegree, &rnchooserk));
116: PetscCall(PetscDTBinomialInt(eorder + eformDegree - 1, eformDegree, &rkm1choosek));
117: *nDofs = rnchooserk * rkm1choosek * nCopies;
118: } else {
119: *nDofs = 0;
120: }
121: }
122: } else if (tensor == 1) { /* hypercubes */
123: if (dim < 2) {
124: PetscCall(ExpectedNumDofs_Interior(dim, order, formDegree, trimmed, 0, nCopies, nDofs));
125: } else {
126: PetscInt tracek = 0;
127: PetscInt tracekm1 = 0;
128: PetscInt fiber0 = 0;
129: PetscInt fiber1 = 0;
131: if (formDegree < dim) {
132: PetscCall(ExpectedNumDofs_Interior(dim - 1, order, formDegree, trimmed, dim > 2 ? 1 : 0, 1, &tracek));
133: PetscCall(ExpectedNumDofs_Interior(1, order, 0, trimmed, 0, 1, &fiber0));
134: }
135: if (formDegree > 0) {
136: PetscCall(ExpectedNumDofs_Interior(dim - 1, order, formDegree - 1, trimmed, dim > 2 ? 1 : 0, 1, &tracekm1));
137: PetscCall(ExpectedNumDofs_Interior(1, order, 1, trimmed, 0, 1, &fiber1));
138: }
139: *nDofs = (tracek * fiber0 + tracekm1 * fiber1) * nCopies;
140: }
141: } else { /* prism */
142: PetscInt tracek = 0;
143: PetscInt tracekm1 = 0;
144: PetscInt fiber0 = 0;
145: PetscInt fiber1 = 0;
147: if (formDegree < dim) {
148: PetscCall(ExpectedNumDofs_Interior(dim - 1, order, formDegree, trimmed, 0, 1, &tracek));
149: PetscCall(ExpectedNumDofs_Interior(1, order, 0, trimmed, 0, 1, &fiber0));
150: }
151: if (formDegree > 0) {
152: PetscCall(ExpectedNumDofs_Interior(dim - 1, order, formDegree - 1, trimmed, 0, 1, &tracekm1));
153: PetscCall(ExpectedNumDofs_Interior(1, order, 1, trimmed, 0, 1, &fiber1));
154: }
155: *nDofs = (tracek * fiber0 + tracekm1 * fiber1) * nCopies;
156: }
157: PetscFunctionReturn(PETSC_SUCCESS);
158: }
160: PetscErrorCode testLagrange(PetscHashLag lagTable, DM K, PetscInt dim, PetscInt order, PetscInt formDegree, PetscBool trimmed, PetscInt tensorCell, PetscBool continuous, PetscInt nCopies)
161: {
162: PetscDualSpace sp;
163: PetscInt Nk;
164: PetscHashLagKey key;
165: PetscHashIter iter;
166: PetscBool missing;
167: PetscInt spdim, spintdim, exspdim, exspintdim;
169: PetscFunctionBegin;
170: PetscCall(PetscDTBinomialInt(dim, PetscAbsInt(formDegree), &Nk));
171: PetscCall(PetscDualSpaceCreate(PETSC_COMM_SELF, &sp));
172: PetscCall(PetscDualSpaceSetType(sp, PETSCDUALSPACELAGRANGE));
173: PetscCall(PetscDualSpaceSetDM(sp, K));
174: PetscCall(PetscDualSpaceSetOrder(sp, order));
175: PetscCall(PetscDualSpaceSetFormDegree(sp, formDegree));
176: PetscCall(PetscDualSpaceSetNumComponents(sp, nCopies * Nk));
177: PetscCall(PetscDualSpaceLagrangeSetContinuity(sp, continuous));
178: PetscCall(PetscDualSpaceLagrangeSetTensor(sp, (PetscBool)(tensorCell > 0)));
179: PetscCall(PetscDualSpaceLagrangeSetTrimmed(sp, trimmed));
180: PetscCall(PetscInfo(NULL, "Input: dim %" PetscInt_FMT ", order %" PetscInt_FMT ", trimmed %" PetscInt_FMT ", tensorCell %" PetscInt_FMT ", continuous %" PetscInt_FMT ", formDegree %" PetscInt_FMT ", nCopies %" PetscInt_FMT "\n", dim, order, (PetscInt)trimmed, tensorCell, (PetscInt)continuous, formDegree, nCopies));
181: PetscCall(ExpectedNumDofs_Total(dim, order, formDegree, trimmed, tensorCell, nCopies, &exspdim));
182: if (continuous && dim > 0 && order > 0) {
183: PetscCall(ExpectedNumDofs_Interior(dim, order, formDegree, trimmed, tensorCell, nCopies, &exspintdim));
184: } else {
185: exspintdim = exspdim;
186: }
187: PetscCall(PetscDualSpaceSetUp(sp));
188: PetscCall(PetscDualSpaceGetDimension(sp, &spdim));
189: PetscCall(PetscDualSpaceGetInteriorDimension(sp, &spintdim));
190: PetscCheck(spdim == exspdim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected dual space dimension %" PetscInt_FMT ", got %" PetscInt_FMT, exspdim, spdim);
191: PetscCheck(spintdim == exspintdim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected dual space interior dimension %" PetscInt_FMT ", got %" PetscInt_FMT, exspintdim, spintdim);
192: key.dim = dim;
193: key.formDegree = formDegree;
194: PetscCall(PetscDualSpaceGetOrder(sp, &key.order));
195: PetscCall(PetscDualSpaceLagrangeGetContinuity(sp, &key.continuous));
196: if (tensorCell == 2) {
197: key.tensor = 2;
198: } else {
199: PetscBool bTensor;
201: PetscCall(PetscDualSpaceLagrangeGetTensor(sp, &bTensor));
202: key.tensor = bTensor;
203: }
204: PetscCall(PetscDualSpaceLagrangeGetTrimmed(sp, &key.trimmed));
205: PetscCall(PetscInfo(NULL, "After setup: order %" PetscInt_FMT ", trimmed %" PetscInt_FMT ", tensor %" PetscInt_FMT ", continuous %" PetscInt_FMT "\n", key.order, (PetscInt)key.trimmed, key.tensor, (PetscInt)key.continuous));
206: PetscCall(PetscHashLagPut(lagTable, key, &iter, &missing));
207: if (missing) {
208: DMPolytopeType type;
210: PetscCall(DMPlexGetCellType(K, 0, &type));
211: PetscCall(PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF, "New space: %s, order %" PetscInt_FMT ", trimmed %" PetscInt_FMT ", tensor %" PetscInt_FMT ", continuous %" PetscInt_FMT ", form degree %" PetscInt_FMT "\n", DMPolytopeTypes[type], order, (PetscInt)trimmed, tensorCell, (PetscInt)continuous, formDegree));
212: PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_SELF));
213: {
214: PetscQuadrature intNodes, allNodes;
215: Mat intMat, allMat;
216: MatInfo info;
217: PetscInt i, j, nodeIdxDim, nodeVecDim, nNodes;
218: const PetscInt *nodeIdx;
219: const PetscReal *nodeVec;
221: PetscDualSpace_Lag *lag = (PetscDualSpace_Lag *)sp->data;
223: PetscCall(PetscLagNodeIndicesGetData_Internal(lag->allNodeIndices, &nodeIdxDim, &nodeVecDim, &nNodes, &nodeIdx, &nodeVec));
224: PetscCheck(nodeVecDim == Nk, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Incorrect nodeVecDim");
225: PetscCheck(nNodes == spdim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Incorrect nNodes");
227: PetscCall(PetscDualSpaceGetAllData(sp, &allNodes, &allMat));
229: PetscCall(PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF, "All nodes:\n"));
230: PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_SELF));
231: PetscCall(PetscQuadratureView(allNodes, PETSC_VIEWER_STDOUT_SELF));
232: PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_SELF));
233: PetscCall(PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF, "All node indices:\n"));
234: for (i = 0; i < spdim; i++) {
235: PetscCall(PetscPrintf(PETSC_COMM_SELF, "("));
236: for (j = 0; j < nodeIdxDim; j++) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT ",", nodeIdx[i * nodeIdxDim + j]));
237: PetscCall(PetscPrintf(PETSC_COMM_SELF, "): ["));
238: for (j = 0; j < nodeVecDim; j++) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %g,", (double)nodeVec[i * nodeVecDim + j]));
239: PetscCall(PetscPrintf(PETSC_COMM_SELF, "]\n"));
240: }
242: PetscCall(MatGetInfo(allMat, MAT_LOCAL, &info));
243: PetscCall(PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF, "All matrix: %" PetscInt_FMT " nonzeros\n", (PetscInt)info.nz_used));
245: PetscCall(PetscDualSpaceGetInteriorData(sp, &intNodes, &intMat));
246: if (intMat && intMat != allMat) {
247: PetscInt intNodeIdxDim, intNodeVecDim, intNnodes;
248: const PetscInt *intNodeIdx;
249: const PetscReal *intNodeVec;
250: PetscBool same;
252: PetscCall(PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF, "Interior nodes:\n"));
253: PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_SELF));
254: PetscCall(PetscQuadratureView(intNodes, PETSC_VIEWER_STDOUT_SELF));
255: PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_SELF));
257: PetscCall(MatGetInfo(intMat, MAT_LOCAL, &info));
258: PetscCall(PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF, "Interior matrix: %" PetscInt_FMT " nonzeros\n", (PetscInt)info.nz_used));
259: PetscCall(PetscLagNodeIndicesGetData_Internal(lag->intNodeIndices, &intNodeIdxDim, &intNodeVecDim, &intNnodes, &intNodeIdx, &intNodeVec));
260: PetscCheck(intNodeIdxDim == nodeIdxDim && intNodeVecDim == nodeVecDim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Interior node indices not the same shale as all node indices");
261: PetscCheck(intNnodes == spintdim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Incorrect interior nNodes");
262: PetscCall(PetscArraycmp(intNodeIdx, nodeIdx, nodeIdxDim * intNnodes, &same));
263: PetscCheck(same, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Interior node indices not the same as start of all node indices");
264: PetscCall(PetscArraycmp(intNodeVec, nodeVec, nodeVecDim * intNnodes, &same));
265: PetscCheck(same, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Interior node vectors not the same as start of all node vectors");
266: } else if (intMat) {
267: PetscCall(PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF, "Interior data is the same as all data\n"));
268: PetscCheck(intNodes == allNodes, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Interior nodes should be the same as all nodes");
269: PetscCheck(lag->intNodeIndices == lag->allNodeIndices, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Interior node indices should be the same as all node indices");
270: }
271: }
272: if (dim <= 2 && spintdim) {
273: PetscInt numFaces;
275: {
276: DMPolytopeType ct;
277: /* The number of arrangements is no longer based on the number of faces */
278: PetscCall(DMPlexGetCellType(K, 0, &ct));
279: numFaces = DMPolytopeTypeGetNumArrangements(ct) / 2;
280: }
281: for (PetscInt o = -numFaces; o < numFaces; ++o) {
282: Mat symMat;
284: PetscCall(PetscDualSpaceCreateInteriorSymmetryMatrix_Lagrange(sp, o, &symMat));
285: PetscCall(PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF, "Interior node symmetry matrix for orientation %" PetscInt_FMT ":\n", o));
286: PetscCall(PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_SELF));
287: PetscCall(MatView(symMat, PETSC_VIEWER_STDOUT_SELF));
288: PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_SELF));
289: PetscCall(MatDestroy(&symMat));
290: }
291: }
292: PetscCall(PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_SELF));
293: }
294: PetscCall(PetscDualSpaceDestroy(&sp));
295: PetscFunctionReturn(PETSC_SUCCESS);
296: }
298: int main(int argc, char **argv)
299: {
300: PetscInt dim;
301: PetscHashLag lagTable;
302: PetscInt tensorCell;
303: PetscInt order, ordermin, ordermax;
304: PetscBool continuous;
305: PetscBool trimmed;
306: DM dm;
308: PetscFunctionBeginUser;
309: PetscCall(PetscInitialize(&argc, &argv, NULL, help));
310: dim = 3;
311: tensorCell = 0;
312: continuous = PETSC_FALSE;
313: trimmed = PETSC_FALSE;
314: PetscOptionsBegin(PETSC_COMM_WORLD, "", "Options for PETSCDUALSPACELAGRANGE test", "none");
315: PetscCall(PetscOptionsRangeInt("-dim", "The spatial dimension", "ex1.c", dim, &dim, NULL, 0, 3));
316: PetscCall(PetscOptionsRangeInt("-tensor", "(0) simplex (1) hypercube (2) wedge", "ex1.c", tensorCell, &tensorCell, NULL, 0, 2));
317: PetscCall(PetscOptionsBool("-continuous", "Whether the dual space has continuity", "ex1.c", continuous, &continuous, NULL));
318: PetscCall(PetscOptionsBool("-trimmed", "Whether the dual space matches a trimmed polynomial space", "ex1.c", trimmed, &trimmed, NULL));
319: PetscOptionsEnd();
320: PetscCall(PetscHashLagCreate(&lagTable));
322: if (tensorCell < 2) {
323: PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, DMPolytopeTypeSimpleShape(dim, (PetscBool)(tensorCell == 0)), &dm));
324: } else {
325: PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, DM_POLYTOPE_TRI_PRISM, &dm));
326: }
327: ordermin = trimmed ? 1 : 0;
328: ordermax = tensorCell == 2 ? 4 : tensorCell == 1 ? 3 : dim + 2;
329: for (order = ordermin; order <= ordermax; order++) {
330: PetscInt formDegree;
332: for (formDegree = PetscMin(0, -dim + 1); formDegree <= dim; formDegree++) {
333: for (PetscInt nCopies = 1; nCopies <= 3; nCopies++) PetscCall(testLagrange(lagTable, dm, dim, order, formDegree, trimmed, tensorCell, continuous, nCopies));
334: }
335: }
336: PetscCall(DMDestroy(&dm));
337: PetscCall(PetscHashLagDestroy(&lagTable));
338: PetscCall(PetscFinalize());
339: return 0;
340: }
342: /*TEST
344: test:
345: suffix: 0
346: args: -dim 0
348: test:
349: suffix: 1_discontinuous_full
350: args: -dim 1 -continuous 0 -trimmed 0
352: test:
353: suffix: 1_continuous_full
354: args: -dim 1 -continuous 1 -trimmed 0
356: test:
357: suffix: 2_simplex_discontinuous_full
358: args: -dim 2 -tensor 0 -continuous 0 -trimmed 0
360: test:
361: suffix: 2_simplex_continuous_full
362: args: -dim 2 -tensor 0 -continuous 1 -trimmed 0
364: test:
365: suffix: 2_tensor_discontinuous_full
366: args: -dim 2 -tensor 1 -continuous 0 -trimmed 0
368: test:
369: suffix: 2_tensor_continuous_full
370: args: -dim 2 -tensor 1 -continuous 1 -trimmed 0
372: test:
373: suffix: 3_simplex_discontinuous_full
374: args: -dim 3 -tensor 0 -continuous 0 -trimmed 0
376: test:
377: suffix: 3_simplex_continuous_full
378: args: -dim 3 -tensor 0 -continuous 1 -trimmed 0
380: test:
381: suffix: 3_tensor_discontinuous_full
382: args: -dim 3 -tensor 1 -continuous 0 -trimmed 0
384: test:
385: suffix: 3_tensor_continuous_full
386: args: -dim 3 -tensor 1 -continuous 1 -trimmed 0
388: test:
389: suffix: 3_wedge_discontinuous_full
390: args: -dim 3 -tensor 2 -continuous 0 -trimmed 0
392: test:
393: suffix: 3_wedge_continuous_full
394: args: -dim 3 -tensor 2 -continuous 1 -trimmed 0
396: test:
397: suffix: 1_discontinuous_trimmed
398: args: -dim 1 -continuous 0 -trimmed 1
400: test:
401: suffix: 1_continuous_trimmed
402: args: -dim 1 -continuous 1 -trimmed 1
404: test:
405: suffix: 2_simplex_discontinuous_trimmed
406: args: -dim 2 -tensor 0 -continuous 0 -trimmed 1
408: test:
409: suffix: 2_simplex_continuous_trimmed
410: args: -dim 2 -tensor 0 -continuous 1 -trimmed 1
412: test:
413: suffix: 2_tensor_discontinuous_trimmed
414: args: -dim 2 -tensor 1 -continuous 0 -trimmed 1
416: test:
417: suffix: 2_tensor_continuous_trimmed
418: args: -dim 2 -tensor 1 -continuous 1 -trimmed 1
420: test:
421: suffix: 3_simplex_discontinuous_trimmed
422: args: -dim 3 -tensor 0 -continuous 0 -trimmed 1
424: test:
425: suffix: 3_simplex_continuous_trimmed
426: args: -dim 3 -tensor 0 -continuous 1 -trimmed 1
428: test:
429: suffix: 3_tensor_discontinuous_trimmed
430: args: -dim 3 -tensor 1 -continuous 0 -trimmed 1
432: test:
433: suffix: 3_tensor_continuous_trimmed
434: args: -dim 3 -tensor 1 -continuous 1 -trimmed 1
436: test:
437: suffix: 3_wedge_discontinuous_trimmed
438: args: -dim 3 -tensor 2 -continuous 0 -trimmed 1
440: test:
441: suffix: 3_wedge_continuous_trimmed
442: args: -dim 3 -tensor 2 -continuous 1 -trimmed 1
444: TEST*/