@@ -314,11 +314,176 @@ fespace cg2_2d = {
314314 .lower = cg2_2d_lower
315315};
316316
317+ /* -------------------------------------------------------
318+ * CG1 element in 3D
319+ * ------------------------------------------------------- */
320+
321+ /* z=0 z=1
322+ * 2
323+ * |\
324+ * 0-1 3 // One degree of freedom per vertex
325+ */
326+
327+ void cg1_3dinterpolate (double * lambda , double * wts ) {
328+ wts [0 ]= lambda [0 ];
329+ wts [1 ]= lambda [1 ];
330+ wts [2 ]= lambda [2 ];
331+ wts [3 ]= lambda [3 ];
332+ }
333+
334+ void cg1_3dgrad (double * lambda , double * grad ) {
335+ double g [] =
336+ { 1 , 0 , 0 , 0 ,
337+ 0 , 1 , 0 , 0 ,
338+ 0 , 0 , 1 , 0 ,
339+ 0 , 0 , 0 , 1 };
340+ memcpy (grad , g , sizeof (g ));
341+ }
342+
343+ unsigned int cg1_3dshape [] = { 1 , 0 , 0 , 0 };
344+
345+ double cg1_3dnodes [] = { 0.0 , 0.0 , 0.0 ,
346+ 1.0 , 0.0 , 0.0 ,
347+ 0.0 , 1.0 , 0.0 ,
348+ 0.0 , 0.0 , 1.0 };
349+
350+ eldefninstruction cg1_3deldefn [] = {
351+ QUANTITY (0 ,0 ,0 ), // Fetch quantity on vertex 0
352+ QUANTITY (0 ,1 ,0 ), // Fetch quantity on vertex 1
353+ QUANTITY (0 ,2 ,0 ), // Fetch quantity on vertex 2
354+ QUANTITY (0 ,3 ,0 ), // Fetch quantity on vertex 3
355+ ENDDEFN
356+ };
357+
358+ fespace * cg1_3d_lower [] = {
359+ & cg1_2d ,
360+ & cg1_1d ,
361+ NULL
362+ };
363+
364+ fespace cg1_3d = {
365+ .name = "CG1" ,
366+ .grade = 3 ,
367+ .shape = cg1_3dshape ,
368+ .degree = 1 ,
369+ .nnodes = 4 ,
370+ .nsubel = 0 ,
371+ .nodes = cg1_3dnodes ,
372+ .ifn = cg1_3dinterpolate ,
373+ .gfn = cg1_3dgrad ,
374+ .eldefn = cg1_3deldefn ,
375+ .lower = cg1_3d_lower
376+ };
377+
378+ /* -------------------------------------------------------
379+ * CG2 element in 3D
380+ * ------------------------------------------------------- */
381+
382+ /* z=0 z=0.5 z=1
383+ * 2
384+ * |\
385+ * 6 5 9
386+ * | \ | \
387+ * 0-4-1 7--8 3 - i.e. vertices
388+ */
389+
390+ void cg2_3dinterpolate (double * lambda , double * wts ) {
391+ wts [0 ]= lambda [0 ]* (2 * lambda [0 ]- 1 );
392+ wts [1 ]= lambda [1 ]* (2 * lambda [1 ]- 1 );
393+ wts [2 ]= lambda [2 ]* (2 * lambda [2 ]- 1 );
394+ wts [3 ]= lambda [3 ]* (2 * lambda [3 ]- 1 );
395+ wts [4 ]= 4 * lambda [0 ]* lambda [1 ];
396+ wts [5 ]= 4 * lambda [1 ]* lambda [2 ];
397+ wts [6 ]= 4 * lambda [2 ]* lambda [0 ];
398+ wts [7 ]= 4 * lambda [0 ]* lambda [3 ];
399+ wts [8 ]= 4 * lambda [1 ]* lambda [3 ];
400+ wts [9 ]= 4 * lambda [2 ]* lambda [3 ];
401+ }
402+
403+ void cg2_3dgrad (double * lambda , double * grad ) { // TODO: FIX
404+ // Gij = d Xi[i] / d lambda[j]
405+ // Note this is in column-major order!
406+ double g [] =
407+ { 4 * lambda [0 ]- 1 , 0 , 0 , 0 ,
408+ 4 * lambda [1 ], 0 , 4 * lambda [2 ], 4 * lambda [3 ], 0 , 0 ,
409+
410+ 0 , 4 * lambda [1 ]- 1 , 0 , 0 ,
411+ 4 * lambda [0 ], 4 * lambda [2 ], 0 , 0 , 4 * lambda [3 ], 0 ,
412+
413+ 0 , 0 , 4 * lambda [2 ]- 1 , 0 ,
414+ 0 , 4 * lambda [1 ], 4 * lambda [0 ], 0 , 0 , 4 * lambda [3 ],
415+
416+ 0 , 0 , 0 , 4 * lambda [3 ]- 1 ,
417+ 0 , 0 , 0 , 4 * lambda [0 ], 4 * lambda [1 ], 4 * lambda [2 ]
418+ };
419+
420+ memcpy (grad , g , sizeof (g ));
421+ }
422+
423+ unsigned int cg2_3dshape [] = { 1 , 1 , 0 , 0 };
424+
425+ double cg2_3dnodes [] = { 0 , 0 , 0 ,
426+ 1 , 0 , 0 ,
427+ 0 , 1 , 0 ,
428+ 0 , 0 , 1 ,
429+ 0.5 , 0 , 0 ,
430+ 0.5 , 0.5 , 0 ,
431+ 0 , 0.5 , 0 ,
432+ 0 , 0 , 0.5 ,
433+ 0.5 , 0 , 0.5 ,
434+ 0 , 0.5 , 0.5 };
435+
436+ eldefninstruction cg2_3deldefn [] = {
437+ LINE (0 ,0 ,1 ), // Identify line subelement with vertex indices (0,1)
438+ LINE (1 ,1 ,2 ), // Identify line subelement with vertex indices (1,2)
439+ LINE (2 ,2 ,0 ), // Identify line subelement with vertex indices (2,0)
440+ LINE (3 ,0 ,3 ), // Identify line subelement with vertex indices (0,3)
441+ LINE (4 ,1 ,3 ), // Identify line subelement with vertex indices (1,3)
442+ LINE (5 ,2 ,3 ), // Identify line subelement with vertex indices (2,3)
443+ QUANTITY (0 ,0 ,0 ), // Fetch quantity on vertex 0
444+ QUANTITY (0 ,1 ,0 ), // Fetch quantity on vertex 1
445+ QUANTITY (0 ,2 ,0 ), // Fetch quantity on vertex 2
446+ QUANTITY (0 ,3 ,0 ), // Fetch quantity on vertex 3
447+ QUANTITY (1 ,0 ,0 ), // Fetch quantity from line 0
448+ QUANTITY (1 ,1 ,0 ), // Fetch quantity from line 1
449+ QUANTITY (1 ,2 ,0 ), // Fetch quantity from line 2
450+ QUANTITY (1 ,3 ,0 ), // Fetch quantity from line 3
451+ QUANTITY (1 ,4 ,0 ), // Fetch quantity from line 4
452+ QUANTITY (1 ,5 ,0 ), // Fetch quantity from line 5
453+ ENDDEFN
454+ };
455+
456+ fespace * cg2_3d_lower [] = {
457+ & cg2_2d ,
458+ & cg2_1d ,
459+ NULL
460+ };
461+
462+ fespace cg2_3d = {
463+ .name = "CG2" ,
464+ .grade = 3 ,
465+ .shape = cg2_3dshape ,
466+ .degree = 2 ,
467+ .nnodes = 10 ,
468+ .nsubel = 6 ,
469+ .nodes = cg2_3dnodes ,
470+ .ifn = cg2_3dinterpolate ,
471+ .gfn = cg2_3dgrad ,
472+ .eldefn = cg2_3deldefn ,
473+ .lower = cg2_3d_lower
474+ };
475+
476+ /* -------------------------------------------------------
477+ * List of finite elements
478+ * ------------------------------------------------------- */
479+
317480fespace * fespaces [] = {
318481 & cg1_1d ,
319482 & cg2_1d ,
320483 & cg1_2d ,
321484 & cg2_2d ,
485+ & cg1_3d ,
486+ & cg2_3d ,
322487 NULL
323488};
324489
0 commit comments