diff --git a/.gitmodules b/.gitmodules index df3e121e16..9166b37e33 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "contrib/metaphysicl"] path = contrib/metaphysicl - url = ../../libMesh/MetaPhysicL + url = ../../rochi00/MetaPhysicL [submodule "contrib/timpi"] path = contrib/timpi url = ../../libMesh/TIMPI diff --git a/Makefile.am b/Makefile.am index dea7f3fd3a..16cde78e4f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -257,6 +257,12 @@ SUBDIRS += contrib include src/libmesh_SOURCES +# When Kokkos support is enabled, add the Kokkos FE type-conversion sources. +# These are kept in src/kokkos/ and not in src/libmesh_SOURCES (which is +# auto-generated) so that they don't affect non-Kokkos builds. +if LIBMESH_ENABLE_KOKKOS +endif + # A convenience library to hold proper libMesh # objects. This will get appended with any contributed # sources to create the final library. diff --git a/Makefile.in b/Makefile.in index cec62a434f..c1c863052e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -109,21 +109,27 @@ target_triplet = @target@ @LIBMESH_PROF_MODE_TRUE@am__append_8 = contrib/utils/libmesh-prof.pc @LIBMESH_OPROF_MODE_TRUE@am__append_9 = contrib/utils/libmesh-oprof.pc @LIBMESH_OPROF_MODE_TRUE@am__append_10 = contrib/utils/libmesh-oprof.pc -@LIBMESH_DBG_MODE_TRUE@am__append_11 = libmesh_dbg.la -@LIBMESH_DEVEL_MODE_TRUE@am__append_12 = libmesh_devel.la -@LIBMESH_OPT_MODE_TRUE@am__append_13 = libmesh_opt.la -@LIBMESH_PROF_MODE_TRUE@am__append_14 = libmesh_prof.la -@LIBMESH_OPROF_MODE_TRUE@am__append_15 = libmesh_oprof.la -@LIBMESH_ENABLE_CPPUNIT_TRUE@am__append_16 = tests + +# When Kokkos support is enabled, add the Kokkos FE type-conversion sources. +# These are kept in src/kokkos/ and not in src/libmesh_SOURCES (which is +# auto-generated) so that they don't affect non-Kokkos builds. +@LIBMESH_ENABLE_KOKKOS_TRUE@am__append_11 = src/kokkos/fe_types.C +@LIBMESH_ENABLE_KOKKOS_TRUE@am__append_12 = $(KOKKOS_CPPFLAGS) -I$(top_srcdir)/include +@LIBMESH_DBG_MODE_TRUE@am__append_13 = libmesh_dbg.la +@LIBMESH_DEVEL_MODE_TRUE@am__append_14 = libmesh_devel.la +@LIBMESH_OPT_MODE_TRUE@am__append_15 = libmesh_opt.la +@LIBMESH_PROF_MODE_TRUE@am__append_16 = libmesh_prof.la +@LIBMESH_OPROF_MODE_TRUE@am__append_17 = libmesh_oprof.la +@LIBMESH_ENABLE_CPPUNIT_TRUE@am__append_18 = tests bin_PROGRAMS = $(am__EXEEXT_2) $(am__EXEEXT_4) $(am__EXEEXT_6) -@LIBMESH_OPT_MODE_TRUE@am__append_17 = $(opt_programs) -@LIBMESH_DEVEL_MODE_TRUE@am__append_18 = $(devel_programs) -@LIBMESH_DBG_MODE_TRUE@am__append_19 = $(dbg_programs) +@LIBMESH_OPT_MODE_TRUE@am__append_19 = $(opt_programs) +@LIBMESH_DEVEL_MODE_TRUE@am__append_20 = $(devel_programs) +@LIBMESH_DBG_MODE_TRUE@am__append_21 = $(dbg_programs) ########################################################### # Examples -@LIBMESH_ENABLE_EXAMPLES_TRUE@am__append_20 = examples -@CODE_COVERAGE_ENABLED_TRUE@am__append_21 = src/apps/*.gcda src/apps/*.gcno +@LIBMESH_ENABLE_EXAMPLES_TRUE@am__append_22 = examples +@CODE_COVERAGE_ENABLED_TRUE@am__append_23 = src/apps/*.gcda src/apps/*.gcno subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = \ @@ -591,9 +597,10 @@ am__libmesh_dbg_la_SOURCES_DIST = src/base/dirichlet_boundary.C \ src/utils/string_to_enum.C src/utils/thread_buffered_syncbuf.C \ src/utils/timestamp.C src/utils/topology_map.C \ src/utils/tree.C src/utils/tree_node.C src/utils/utility.C \ - src/utils/xdr_cxx.C + src/utils/xdr_cxx.C src/kokkos/fe_types.C am__dirstamp = $(am__leading_dot)dirstamp -am__objects_1 = src/base/libmesh_dbg_la-dirichlet_boundary.lo \ +@LIBMESH_ENABLE_KOKKOS_TRUE@am__objects_1 = src/kokkos/libmesh_dbg_la-fe_types.lo +am__objects_2 = src/base/libmesh_dbg_la-dirichlet_boundary.lo \ src/base/libmesh_dbg_la-dof_map.lo \ src/base/libmesh_dbg_la-dof_map_base.lo \ src/base/libmesh_dbg_la-dof_map_constraints.lo \ @@ -1068,8 +1075,8 @@ am__objects_1 = src/base/libmesh_dbg_la-dirichlet_boundary.lo \ src/utils/libmesh_dbg_la-tree.lo \ src/utils/libmesh_dbg_la-tree_node.lo \ src/utils/libmesh_dbg_la-utility.lo \ - src/utils/libmesh_dbg_la-xdr_cxx.lo -@LIBMESH_DBG_MODE_TRUE@am_libmesh_dbg_la_OBJECTS = $(am__objects_1) + src/utils/libmesh_dbg_la-xdr_cxx.lo $(am__objects_1) +@LIBMESH_DBG_MODE_TRUE@am_libmesh_dbg_la_OBJECTS = $(am__objects_2) libmesh_dbg_la_OBJECTS = $(am_libmesh_dbg_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -1406,8 +1413,9 @@ am__libmesh_devel_la_SOURCES_DIST = src/base/dirichlet_boundary.C \ src/utils/string_to_enum.C src/utils/thread_buffered_syncbuf.C \ src/utils/timestamp.C src/utils/topology_map.C \ src/utils/tree.C src/utils/tree_node.C src/utils/utility.C \ - src/utils/xdr_cxx.C -am__objects_2 = src/base/libmesh_devel_la-dirichlet_boundary.lo \ + src/utils/xdr_cxx.C src/kokkos/fe_types.C +@LIBMESH_ENABLE_KOKKOS_TRUE@am__objects_3 = src/kokkos/libmesh_devel_la-fe_types.lo +am__objects_4 = src/base/libmesh_devel_la-dirichlet_boundary.lo \ src/base/libmesh_devel_la-dof_map.lo \ src/base/libmesh_devel_la-dof_map_base.lo \ src/base/libmesh_devel_la-dof_map_constraints.lo \ @@ -1882,9 +1890,9 @@ am__objects_2 = src/base/libmesh_devel_la-dirichlet_boundary.lo \ src/utils/libmesh_devel_la-tree.lo \ src/utils/libmesh_devel_la-tree_node.lo \ src/utils/libmesh_devel_la-utility.lo \ - src/utils/libmesh_devel_la-xdr_cxx.lo + src/utils/libmesh_devel_la-xdr_cxx.lo $(am__objects_3) @LIBMESH_DEVEL_MODE_TRUE@am_libmesh_devel_la_OBJECTS = \ -@LIBMESH_DEVEL_MODE_TRUE@ $(am__objects_2) +@LIBMESH_DEVEL_MODE_TRUE@ $(am__objects_4) libmesh_devel_la_OBJECTS = $(am_libmesh_devel_la_OBJECTS) libmesh_devel_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ @@ -2217,8 +2225,9 @@ am__libmesh_oprof_la_SOURCES_DIST = src/base/dirichlet_boundary.C \ src/utils/string_to_enum.C src/utils/thread_buffered_syncbuf.C \ src/utils/timestamp.C src/utils/topology_map.C \ src/utils/tree.C src/utils/tree_node.C src/utils/utility.C \ - src/utils/xdr_cxx.C -am__objects_3 = src/base/libmesh_oprof_la-dirichlet_boundary.lo \ + src/utils/xdr_cxx.C src/kokkos/fe_types.C +@LIBMESH_ENABLE_KOKKOS_TRUE@am__objects_5 = src/kokkos/libmesh_oprof_la-fe_types.lo +am__objects_6 = src/base/libmesh_oprof_la-dirichlet_boundary.lo \ src/base/libmesh_oprof_la-dof_map.lo \ src/base/libmesh_oprof_la-dof_map_base.lo \ src/base/libmesh_oprof_la-dof_map_constraints.lo \ @@ -2693,9 +2702,9 @@ am__objects_3 = src/base/libmesh_oprof_la-dirichlet_boundary.lo \ src/utils/libmesh_oprof_la-tree.lo \ src/utils/libmesh_oprof_la-tree_node.lo \ src/utils/libmesh_oprof_la-utility.lo \ - src/utils/libmesh_oprof_la-xdr_cxx.lo + src/utils/libmesh_oprof_la-xdr_cxx.lo $(am__objects_5) @LIBMESH_OPROF_MODE_TRUE@am_libmesh_oprof_la_OBJECTS = \ -@LIBMESH_OPROF_MODE_TRUE@ $(am__objects_3) +@LIBMESH_OPROF_MODE_TRUE@ $(am__objects_6) libmesh_oprof_la_OBJECTS = $(am_libmesh_oprof_la_OBJECTS) libmesh_oprof_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ @@ -3028,8 +3037,9 @@ am__libmesh_opt_la_SOURCES_DIST = src/base/dirichlet_boundary.C \ src/utils/string_to_enum.C src/utils/thread_buffered_syncbuf.C \ src/utils/timestamp.C src/utils/topology_map.C \ src/utils/tree.C src/utils/tree_node.C src/utils/utility.C \ - src/utils/xdr_cxx.C -am__objects_4 = src/base/libmesh_opt_la-dirichlet_boundary.lo \ + src/utils/xdr_cxx.C src/kokkos/fe_types.C +@LIBMESH_ENABLE_KOKKOS_TRUE@am__objects_7 = src/kokkos/libmesh_opt_la-fe_types.lo +am__objects_8 = src/base/libmesh_opt_la-dirichlet_boundary.lo \ src/base/libmesh_opt_la-dof_map.lo \ src/base/libmesh_opt_la-dof_map_base.lo \ src/base/libmesh_opt_la-dof_map_constraints.lo \ @@ -3504,8 +3514,8 @@ am__objects_4 = src/base/libmesh_opt_la-dirichlet_boundary.lo \ src/utils/libmesh_opt_la-tree.lo \ src/utils/libmesh_opt_la-tree_node.lo \ src/utils/libmesh_opt_la-utility.lo \ - src/utils/libmesh_opt_la-xdr_cxx.lo -@LIBMESH_OPT_MODE_TRUE@am_libmesh_opt_la_OBJECTS = $(am__objects_4) + src/utils/libmesh_opt_la-xdr_cxx.lo $(am__objects_7) +@LIBMESH_OPT_MODE_TRUE@am_libmesh_opt_la_OBJECTS = $(am__objects_8) libmesh_opt_la_OBJECTS = $(am_libmesh_opt_la_OBJECTS) libmesh_opt_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ @@ -3838,8 +3848,9 @@ am__libmesh_prof_la_SOURCES_DIST = src/base/dirichlet_boundary.C \ src/utils/string_to_enum.C src/utils/thread_buffered_syncbuf.C \ src/utils/timestamp.C src/utils/topology_map.C \ src/utils/tree.C src/utils/tree_node.C src/utils/utility.C \ - src/utils/xdr_cxx.C -am__objects_5 = src/base/libmesh_prof_la-dirichlet_boundary.lo \ + src/utils/xdr_cxx.C src/kokkos/fe_types.C +@LIBMESH_ENABLE_KOKKOS_TRUE@am__objects_9 = src/kokkos/libmesh_prof_la-fe_types.lo +am__objects_10 = src/base/libmesh_prof_la-dirichlet_boundary.lo \ src/base/libmesh_prof_la-dof_map.lo \ src/base/libmesh_prof_la-dof_map_base.lo \ src/base/libmesh_prof_la-dof_map_constraints.lo \ @@ -4314,8 +4325,9 @@ am__objects_5 = src/base/libmesh_prof_la-dirichlet_boundary.lo \ src/utils/libmesh_prof_la-tree.lo \ src/utils/libmesh_prof_la-tree_node.lo \ src/utils/libmesh_prof_la-utility.lo \ - src/utils/libmesh_prof_la-xdr_cxx.lo -@LIBMESH_PROF_MODE_TRUE@am_libmesh_prof_la_OBJECTS = $(am__objects_5) + src/utils/libmesh_prof_la-xdr_cxx.lo $(am__objects_9) +@LIBMESH_PROF_MODE_TRUE@am_libmesh_prof_la_OBJECTS = \ +@LIBMESH_PROF_MODE_TRUE@ $(am__objects_10) libmesh_prof_la_OBJECTS = $(am_libmesh_prof_la_OBJECTS) libmesh_prof_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ @@ -5795,6 +5807,11 @@ am__depfiles_remade = src/apps/$(DEPDIR)/amr_dbg-amr.Po \ src/ghosting/$(DEPDIR)/libmesh_prof_la-overlap_coupling.Plo \ src/ghosting/$(DEPDIR)/libmesh_prof_la-point_neighbor_coupling.Plo \ src/ghosting/$(DEPDIR)/libmesh_prof_la-sibling_coupling.Plo \ + src/kokkos/$(DEPDIR)/libmesh_dbg_la-fe_types.Plo \ + src/kokkos/$(DEPDIR)/libmesh_devel_la-fe_types.Plo \ + src/kokkos/$(DEPDIR)/libmesh_oprof_la-fe_types.Plo \ + src/kokkos/$(DEPDIR)/libmesh_opt_la-fe_types.Plo \ + src/kokkos/$(DEPDIR)/libmesh_prof_la-fe_types.Plo \ src/mesh/$(DEPDIR)/libmesh_dbg_la-abaqus_io.Plo \ src/mesh/$(DEPDIR)/libmesh_dbg_la-boundary_info.Plo \ src/mesh/$(DEPDIR)/libmesh_dbg_la-boundary_mesh.Plo \ @@ -7754,7 +7771,7 @@ vtkversion = @vtkversion@ # test/unit/Makefile.in # Make sure we build the library before we test it -SUBDIRS = include contrib . $(am__append_16) $(am__append_20) doc +SUBDIRS = include contrib . $(am__append_18) $(am__append_22) doc AUTOMAKE_OPTIONS = subdir-objects ACLOCAL_AMFLAGS = -I m4 -I m4/autoconf-submodule AM_CFLAGS = $(libmesh_CFLAGS) @@ -7784,10 +7801,8 @@ TAR_OPTIONS = --hard-dereference # codes. These will be augmented with method-specific # cppflags later on AM_CPPFLAGS = -DLIBMESH_IS_COMPILING_ITSELF \ - $(libmesh_contrib_INCLUDES) \ - $(libmesh_optional_INCLUDES) \ - -I$(top_builddir)/include # required for libmesh_version.h - + $(libmesh_contrib_INCLUDES) $(libmesh_optional_INCLUDES) \ + -I$(top_builddir)/include $(am__append_12) # additional files which must be included in 'make dist' EXTRA_DIST = reference_elements \ @@ -7860,491 +7875,336 @@ DISTCLEANFILES = \ # Do not edit - automatically generated from ./rebuild_libmesh_SOURCES.sh -libmesh_SOURCES = \ - src/base/dirichlet_boundary.C \ - src/base/dof_map.C \ - src/base/dof_map_base.C \ - src/base/dof_map_constraints.C \ - src/base/dof_object.C \ - src/base/libmesh.C \ - src/base/libmesh_common.C \ - src/base/libmesh_exceptions.C \ - src/base/libmesh_singleton.C \ - src/base/libmesh_version.C \ - src/base/periodic_boundaries.C \ - src/base/periodic_boundary.C \ - src/base/periodic_boundary_base.C \ - src/base/print_trace.C \ - src/base/reference_counted_object.C \ - src/base/reference_counter.C \ - src/base/single_predicates.C \ - src/base/sparsity_pattern.C \ - src/base/variable.C \ - src/error_estimation/adjoint_refinement_estimator.C \ - src/error_estimation/adjoint_residual_error_estimator.C \ - src/error_estimation/discontinuity_measure.C \ - src/error_estimation/error_estimator.C \ - src/error_estimation/exact_error_estimator.C \ - src/error_estimation/exact_solution.C \ - src/error_estimation/fourth_error_estimators.C \ - src/error_estimation/hp_coarsentest.C \ - src/error_estimation/hp_selector.C \ - src/error_estimation/hp_singular.C \ - src/error_estimation/jump_error_estimator.C \ - src/error_estimation/kelly_error_estimator.C \ - src/error_estimation/patch_recovery_error_estimator.C \ - src/error_estimation/smoothness_estimator.C \ - src/error_estimation/uniform_refinement_estimator.C \ - src/error_estimation/weighted_patch_recovery_error_estimator.C \ - src/fe/fe.C \ - src/fe/fe_abstract.C \ - src/fe/fe_base.C \ - src/fe/fe_bernstein.C \ - src/fe/fe_bernstein_shape_0D.C \ - src/fe/fe_bernstein_shape_1D.C \ - src/fe/fe_bernstein_shape_2D.C \ - src/fe/fe_bernstein_shape_3D.C \ - src/fe/fe_boundary.C \ - src/fe/fe_clough.C \ - src/fe/fe_clough_shape_0D.C \ - src/fe/fe_clough_shape_1D.C \ - src/fe/fe_clough_shape_2D.C \ - src/fe/fe_clough_shape_3D.C \ - src/fe/fe_compute_data.C \ - src/fe/fe_hermite.C \ - src/fe/fe_hermite_shape_0D.C \ - src/fe/fe_hermite_shape_1D.C \ - src/fe/fe_hermite_shape_2D.C \ - src/fe/fe_hermite_shape_3D.C \ - src/fe/fe_hierarchic.C \ - src/fe/fe_hierarchic_shape_0D.C \ - src/fe/fe_hierarchic_shape_1D.C \ - src/fe/fe_hierarchic_shape_2D.C \ - src/fe/fe_hierarchic_shape_3D.C \ - src/fe/fe_hierarchic_vec.C \ - src/fe/fe_interface.C \ - src/fe/fe_interface_inf_fe.C \ - src/fe/fe_l2_hierarchic.C \ - src/fe/fe_l2_lagrange.C \ - src/fe/fe_lagrange.C \ - src/fe/fe_lagrange_shape_0D.C \ - src/fe/fe_lagrange_shape_1D.C \ - src/fe/fe_lagrange_shape_2D.C \ - src/fe/fe_lagrange_shape_3D.C \ - src/fe/fe_lagrange_vec.C \ - src/fe/fe_map.C \ - src/fe/fe_monomial.C \ - src/fe/fe_monomial_shape_0D.C \ - src/fe/fe_monomial_shape_1D.C \ - src/fe/fe_monomial_shape_2D.C \ - src/fe/fe_monomial_shape_3D.C \ - src/fe/fe_monomial_vec.C \ - src/fe/fe_nedelec_one.C \ - src/fe/fe_nedelec_one_shape_2D.C \ - src/fe/fe_nedelec_one_shape_3D.C \ - src/fe/fe_rational.C \ - src/fe/fe_rational_shape_0D.C \ - src/fe/fe_rational_shape_1D.C \ - src/fe/fe_rational_shape_2D.C \ - src/fe/fe_rational_shape_3D.C \ - src/fe/fe_raviart.C \ - src/fe/fe_raviart_shape_2D.C \ - src/fe/fe_raviart_shape_3D.C \ - src/fe/fe_scalar.C \ - src/fe/fe_scalar_shape_0D.C \ - src/fe/fe_scalar_shape_1D.C \ - src/fe/fe_scalar_shape_2D.C \ - src/fe/fe_scalar_shape_3D.C \ - src/fe/fe_side_hierarchic.C \ - src/fe/fe_subdivision_2D.C \ - src/fe/fe_szabab.C \ - src/fe/fe_szabab_shape_0D.C \ - src/fe/fe_szabab_shape_1D.C \ - src/fe/fe_szabab_shape_2D.C \ - src/fe/fe_szabab_shape_3D.C \ - src/fe/fe_transformation_base.C \ - src/fe/fe_type.C \ - src/fe/fe_xyz.C \ - src/fe/fe_xyz_boundary.C \ - src/fe/fe_xyz_map.C \ - src/fe/fe_xyz_shape_0D.C \ - src/fe/fe_xyz_shape_1D.C \ - src/fe/fe_xyz_shape_2D.C \ - src/fe/fe_xyz_shape_3D.C \ - src/fe/h1_fe_transformation.C \ - src/fe/hcurl_fe_transformation.C \ - src/fe/hdiv_fe_transformation.C \ - src/fe/inf_fe.C \ - src/fe/inf_fe_base_radial.C \ - src/fe/inf_fe_boundary.C \ - src/fe/inf_fe_jacobi_20_00_eval.C \ - src/fe/inf_fe_jacobi_30_00_eval.C \ - src/fe/inf_fe_lagrange_eval.C \ - src/fe/inf_fe_legendre_eval.C \ - src/fe/inf_fe_map.C \ - src/fe/inf_fe_map_eval.C \ - src/fe/inf_fe_static.C \ - src/geom/bounding_box.C \ - src/geom/cell.C \ - src/geom/cell_c0polyhedron.C \ - src/geom/cell_hex.C \ - src/geom/cell_hex20.C \ - src/geom/cell_hex27.C \ - src/geom/cell_hex8.C \ - src/geom/cell_inf.C \ - src/geom/cell_inf_hex.C \ - src/geom/cell_inf_hex16.C \ - src/geom/cell_inf_hex18.C \ - src/geom/cell_inf_hex8.C \ - src/geom/cell_inf_prism.C \ - src/geom/cell_inf_prism12.C \ - src/geom/cell_inf_prism6.C \ - src/geom/cell_polyhedron.C \ - src/geom/cell_prism.C \ - src/geom/cell_prism15.C \ - src/geom/cell_prism18.C \ - src/geom/cell_prism20.C \ - src/geom/cell_prism21.C \ - src/geom/cell_prism6.C \ - src/geom/cell_pyramid.C \ - src/geom/cell_pyramid13.C \ - src/geom/cell_pyramid14.C \ - src/geom/cell_pyramid18.C \ - src/geom/cell_pyramid5.C \ - src/geom/cell_tet.C \ - src/geom/cell_tet10.C \ - src/geom/cell_tet14.C \ - src/geom/cell_tet4.C \ - src/geom/edge.C \ - src/geom/edge_edge2.C \ - src/geom/edge_edge3.C \ - src/geom/edge_edge4.C \ - src/geom/edge_inf_edge2.C \ - src/geom/elem.C \ - src/geom/elem_cutter.C \ - src/geom/elem_quality.C \ - src/geom/elem_refinement.C \ - src/geom/elem_side_builder.C \ - src/geom/face.C \ - src/geom/face_c0polygon.C \ - src/geom/face_inf_quad.C \ - src/geom/face_inf_quad4.C \ - src/geom/face_inf_quad6.C \ - src/geom/face_polygon.C \ - src/geom/face_quad.C \ - src/geom/face_quad4.C \ - src/geom/face_quad4_shell.C \ - src/geom/face_quad8.C \ - src/geom/face_quad8_shell.C \ - src/geom/face_quad9.C \ - src/geom/face_quad9_shell.C \ - src/geom/face_tri.C \ - src/geom/face_tri3.C \ - src/geom/face_tri3_shell.C \ - src/geom/face_tri3_subdivision.C \ - src/geom/face_tri6.C \ - src/geom/face_tri7.C \ - src/geom/node.C \ - src/geom/node_elem.C \ - src/geom/plane.C \ - src/geom/point.C \ - src/geom/reference_elem.C \ - src/geom/reference_elem.data \ - src/geom/remote_elem.C \ - src/geom/sphere.C \ - src/geom/surface.C \ - src/ghosting/default_coupling.C \ - src/ghosting/ghost_point_neighbors.C \ - src/ghosting/non_manifold_coupling.C \ - src/ghosting/overlap_coupling.C \ - src/ghosting/point_neighbor_coupling.C \ - src/ghosting/sibling_coupling.C \ - src/mesh/abaqus_io.C \ - src/mesh/boundary_info.C \ - src/mesh/boundary_mesh.C \ - src/mesh/checkpoint_io.C \ - src/mesh/distributed_mesh.C \ - src/mesh/dyna_io.C \ - src/mesh/ensight_io.C \ - src/mesh/exodusII_io.C \ - src/mesh/exodusII_io_helper.C \ - src/mesh/fro_io.C \ - src/mesh/gmsh_io.C \ - src/mesh/gmv_io.C \ - src/mesh/gnuplot_io.C \ - src/mesh/inf_elem_builder.C \ - src/mesh/matlab_io.C \ - src/mesh/medit_io.C \ - src/mesh/mesh_base.C \ - src/mesh/mesh_communication.C \ - src/mesh/mesh_communication_global_indices.C \ - src/mesh/mesh_function.C \ - src/mesh/mesh_generation.C \ - src/mesh/mesh_iterators.C \ - src/mesh/mesh_modification.C \ - src/mesh/mesh_netgen_interface.C \ - src/mesh/mesh_output.C \ - src/mesh/mesh_refinement.C \ - src/mesh/mesh_refinement_flagging.C \ - src/mesh/mesh_refinement_smoothing.C \ - src/mesh/mesh_serializer.C \ - src/mesh/mesh_smoother.C \ - src/mesh/mesh_smoother_laplace.C \ - src/mesh/mesh_smoother_vsmoother.C \ - src/mesh/mesh_subdivision_support.C \ - src/mesh/mesh_tet_interface.C \ - src/mesh/mesh_tetgen_interface.C \ - src/mesh/mesh_tetgen_wrapper.C \ - src/mesh/mesh_tools.C \ - src/mesh/mesh_triangle_holes.C \ - src/mesh/mesh_triangle_interface.C \ - src/mesh/mesh_triangle_wrapper.C \ - src/mesh/namebased_io.C \ - src/mesh/nemesis_io.C \ - src/mesh/nemesis_io_helper.C \ - src/mesh/off_io.C \ - src/mesh/patch.C \ - src/mesh/poly2tri_triangulator.C \ - src/mesh/postscript_io.C \ - src/mesh/replicated_mesh.C \ - src/mesh/sides_to_elem_map.C \ - src/mesh/simplex_refiner.C \ - src/mesh/stl_io.C \ - src/mesh/tecplot_io.C \ - src/mesh/tetgen_io.C \ - src/mesh/triangulator_interface.C \ - src/mesh/ucd_io.C \ - src/mesh/unstructured_mesh.C \ - src/mesh/unv_io.C \ - src/mesh/vtk_io.C \ - src/mesh/xdr_io.C \ - src/numerics/coupling_matrix.C \ - src/numerics/dense_matrix.C \ - src/numerics/dense_matrix_base.C \ - src/numerics/dense_matrix_blas_lapack.C \ - src/numerics/dense_submatrix.C \ - src/numerics/dense_subvector.C \ - src/numerics/dense_vector.C \ - src/numerics/dense_vector_base.C \ - src/numerics/diagonal_matrix.C \ - src/numerics/distributed_vector.C \ - src/numerics/eigen_preconditioner.C \ - src/numerics/eigen_sparse_matrix.C \ - src/numerics/eigen_sparse_vector.C \ - src/numerics/laspack_matrix.C \ - src/numerics/laspack_vector.C \ - src/numerics/lumped_mass_matrix.C \ - src/numerics/numeric_vector.C \ - src/numerics/petsc_matrix.C \ - src/numerics/petsc_matrix_base.C \ - src/numerics/petsc_matrix_shell_matrix.C \ - src/numerics/petsc_preconditioner.C \ - src/numerics/petsc_shell_matrix.C \ - src/numerics/petsc_vector.C \ - src/numerics/preconditioner.C \ - src/numerics/shell_matrix.C \ - src/numerics/sparse_matrix.C \ - src/numerics/sparse_shell_matrix.C \ - src/numerics/static_condensation.C \ - src/numerics/static_condensation_dof_map.C \ - src/numerics/sum_shell_matrix.C \ - src/numerics/tensor_shell_matrix.C \ - src/numerics/tensor_tools.C \ - src/numerics/trilinos_epetra_matrix.C \ - src/numerics/trilinos_epetra_vector.C \ - src/numerics/trilinos_preconditioner.C \ - src/numerics/type_tensor.C \ - src/numerics/type_vector.C \ - src/numerics/wrapped_petsc.C \ - src/parallel/parallel_bin_sorter.C \ - src/parallel/parallel_elem.C \ - src/parallel/parallel_ghost_sync.C \ - src/parallel/parallel_histogram.C \ - src/parallel/parallel_node.C \ - src/parallel/parallel_sort.C \ - src/parallel/threads.C \ - src/partitioning/centroid_partitioner.C \ - src/partitioning/linear_partitioner.C \ - src/partitioning/mapped_subdomain_partitioner.C \ - src/partitioning/metis_partitioner.C \ - src/partitioning/parmetis_partitioner.C \ - src/partitioning/partitioner.C \ - src/partitioning/partitioner_factory.C \ - src/partitioning/sfc_partitioner.C \ - src/partitioning/subdomain_partitioner.C \ - src/physics/diff_physics.C \ - src/physics/diff_qoi.C \ - src/physics/fem_physics.C \ - src/quadrature/quadrature.C \ - src/quadrature/quadrature_build.C \ - src/quadrature/quadrature_clough.C \ - src/quadrature/quadrature_clough_1D.C \ - src/quadrature/quadrature_clough_2D.C \ - src/quadrature/quadrature_clough_3D.C \ - src/quadrature/quadrature_composite.C \ - src/quadrature/quadrature_conical.C \ - src/quadrature/quadrature_conical_2D.C \ - src/quadrature/quadrature_conical_3D.C \ - src/quadrature/quadrature_gauss.C \ - src/quadrature/quadrature_gauss_1D.C \ - src/quadrature/quadrature_gauss_2D.C \ - src/quadrature/quadrature_gauss_3D.C \ - src/quadrature/quadrature_gauss_lobatto.C \ - src/quadrature/quadrature_gauss_lobatto_1D.C \ - src/quadrature/quadrature_gauss_lobatto_2D.C \ - src/quadrature/quadrature_gauss_lobatto_3D.C \ - src/quadrature/quadrature_gm.C \ - src/quadrature/quadrature_gm_2D.C \ - src/quadrature/quadrature_gm_3D.C \ - src/quadrature/quadrature_grid.C \ - src/quadrature/quadrature_grid_1D.C \ - src/quadrature/quadrature_grid_2D.C \ - src/quadrature/quadrature_grid_3D.C \ - src/quadrature/quadrature_jacobi.C \ - src/quadrature/quadrature_jacobi_1D.C \ - src/quadrature/quadrature_monomial.C \ - src/quadrature/quadrature_monomial_1D.C \ - src/quadrature/quadrature_monomial_2D.C \ - src/quadrature/quadrature_monomial_3D.C \ - src/quadrature/quadrature_nodal.C \ - src/quadrature/quadrature_nodal_1D.C \ - src/quadrature/quadrature_nodal_2D.C \ - src/quadrature/quadrature_nodal_3D.C \ - src/quadrature/quadrature_simpson.C \ - src/quadrature/quadrature_simpson_1D.C \ - src/quadrature/quadrature_simpson_2D.C \ - src/quadrature/quadrature_simpson_3D.C \ - src/quadrature/quadrature_trap.C \ - src/quadrature/quadrature_trap_1D.C \ - src/quadrature/quadrature_trap_2D.C \ - src/quadrature/quadrature_trap_3D.C \ - src/reduced_basis/rb_assembly_expansion.C \ - src/reduced_basis/rb_construction.C \ - src/reduced_basis/rb_construction_base.C \ - src/reduced_basis/rb_data_deserialization.C \ - src/reduced_basis/rb_data_serialization.C \ - src/reduced_basis/rb_eim_assembly.C \ - src/reduced_basis/rb_eim_construction.C \ - src/reduced_basis/rb_eim_evaluation.C \ - src/reduced_basis/rb_eim_theta.C \ - src/reduced_basis/rb_evaluation.C \ - src/reduced_basis/rb_parameters.C \ - src/reduced_basis/rb_parametrized.C \ - src/reduced_basis/rb_parametrized_function.C \ - src/reduced_basis/rb_scm_construction.C \ - src/reduced_basis/rb_scm_evaluation.C \ - src/reduced_basis/rb_temporal_discretization.C \ - src/reduced_basis/rb_theta.C \ - src/reduced_basis/rb_theta_expansion.C \ - src/reduced_basis/transient_rb_assembly_expansion.C \ - src/reduced_basis/transient_rb_construction.C \ - src/reduced_basis/transient_rb_evaluation.C \ - src/reduced_basis/transient_rb_theta_expansion.C \ - src/solution_transfer/boundary_volume_solution_transfer.C \ - src/solution_transfer/direct_solution_transfer.C \ - src/solution_transfer/dtk_adapter.C \ - src/solution_transfer/dtk_evaluator.C \ - src/solution_transfer/dtk_solution_transfer.C \ - src/solution_transfer/meshfree_interpolation.C \ - src/solution_transfer/meshfree_interpolation_function.C \ - src/solution_transfer/meshfree_solution_transfer.C \ - src/solution_transfer/meshfunction_solution_transfer.C \ - src/solution_transfer/radial_basis_interpolation.C \ - src/solution_transfer/solution_transfer.C \ - src/solvers/adaptive_time_solver.C \ - src/solvers/diff_solver.C \ - src/solvers/eigen_solver.C \ - src/solvers/eigen_sparse_linear_solver.C \ - src/solvers/eigen_time_solver.C \ - src/solvers/euler2_solver.C \ - src/solvers/euler_solver.C \ - src/solvers/file_history_data.C \ - src/solvers/file_solution_history.C \ - src/solvers/first_order_unsteady_solver.C \ - src/solvers/laspack_linear_solver.C \ - src/solvers/linear_solver.C \ - src/solvers/memory_history_data.C \ - src/solvers/memory_solution_history.C \ - src/solvers/newmark_solver.C \ - src/solvers/newton_solver.C \ - src/solvers/nlopt_optimization_solver.C \ - src/solvers/no_solution_history.C \ - src/solvers/nonlinear_solver.C \ - src/solvers/optimization_solver.C \ - src/solvers/petsc_auto_fieldsplit.C \ - src/solvers/petsc_diff_solver.C \ - src/solvers/petsc_dm_wrapper.C \ - src/solvers/petsc_linear_solver.C \ - src/solvers/petsc_nonlinear_solver.C \ - src/solvers/petscdmlibmesh.C \ - src/solvers/petscdmlibmeshimpl.C \ - src/solvers/second_order_unsteady_solver.C \ - src/solvers/slepc_eigen_solver.C \ - src/solvers/solution_history.C \ - src/solvers/steady_solver.C \ - src/solvers/tao_optimization_solver.C \ - src/solvers/time_solver.C \ - src/solvers/trilinos_aztec_linear_solver.C \ - src/solvers/trilinos_nox_nonlinear_solver.C \ - src/solvers/twostep_time_solver.C \ - src/solvers/unsteady_solver.C \ - src/systems/condensed_eigen_system.C \ - src/systems/continuation_system.C \ - src/systems/dg_fem_context.C \ - src/systems/diff_context.C \ - src/systems/diff_system.C \ - src/systems/eigen_system.C \ - src/systems/equation_systems.C \ - src/systems/equation_systems_io.C \ - src/systems/explicit_system.C \ - src/systems/fem_context.C \ - src/systems/fem_system.C \ - src/systems/frequency_system.C \ - src/systems/implicit_system.C \ - src/systems/inter_mesh_projection.C \ - src/systems/linear_implicit_system.C \ - src/systems/newmark_system.C \ - src/systems/nonlinear_implicit_system.C \ - src/systems/optimization_system.C \ - src/systems/parameter_vector.C \ - src/systems/qoi_set.C \ - src/systems/steady_system.C \ - src/systems/system.C \ - src/systems/system_io.C \ - src/systems/system_norm.C \ - src/systems/system_projection.C \ - src/systems/system_subset.C \ - src/systems/system_subset_by_subdomain.C \ - src/systems/transient_system.C \ - src/systems/variational_smoother_constraint.C \ - src/systems/variational_smoother_system.C \ - src/utils/error_vector.C \ - src/utils/hashword.C \ - src/utils/location_maps.C \ - src/utils/number_lookups.C \ - src/utils/perf_log.C \ - src/utils/plt_loader.C \ - src/utils/plt_loader_read.C \ - src/utils/plt_loader_write.C \ - src/utils/point_locator_base.C \ - src/utils/point_locator_nanoflann.C \ - src/utils/point_locator_tree.C \ - src/utils/statistics.C \ - src/utils/string_to_enum.C \ - src/utils/thread_buffered_syncbuf.C \ - src/utils/timestamp.C \ - src/utils/topology_map.C \ - src/utils/tree.C \ - src/utils/tree_node.C \ - src/utils/utility.C \ - src/utils/xdr_cxx.C - +libmesh_SOURCES = src/base/dirichlet_boundary.C src/base/dof_map.C \ + src/base/dof_map_base.C src/base/dof_map_constraints.C \ + src/base/dof_object.C src/base/libmesh.C \ + src/base/libmesh_common.C src/base/libmesh_exceptions.C \ + src/base/libmesh_singleton.C src/base/libmesh_version.C \ + src/base/periodic_boundaries.C src/base/periodic_boundary.C \ + src/base/periodic_boundary_base.C src/base/print_trace.C \ + src/base/reference_counted_object.C \ + src/base/reference_counter.C src/base/single_predicates.C \ + src/base/sparsity_pattern.C src/base/variable.C \ + src/error_estimation/adjoint_refinement_estimator.C \ + src/error_estimation/adjoint_residual_error_estimator.C \ + src/error_estimation/discontinuity_measure.C \ + src/error_estimation/error_estimator.C \ + src/error_estimation/exact_error_estimator.C \ + src/error_estimation/exact_solution.C \ + src/error_estimation/fourth_error_estimators.C \ + src/error_estimation/hp_coarsentest.C \ + src/error_estimation/hp_selector.C \ + src/error_estimation/hp_singular.C \ + src/error_estimation/jump_error_estimator.C \ + src/error_estimation/kelly_error_estimator.C \ + src/error_estimation/patch_recovery_error_estimator.C \ + src/error_estimation/smoothness_estimator.C \ + src/error_estimation/uniform_refinement_estimator.C \ + src/error_estimation/weighted_patch_recovery_error_estimator.C \ + src/fe/fe.C src/fe/fe_abstract.C src/fe/fe_base.C \ + src/fe/fe_bernstein.C src/fe/fe_bernstein_shape_0D.C \ + src/fe/fe_bernstein_shape_1D.C src/fe/fe_bernstein_shape_2D.C \ + src/fe/fe_bernstein_shape_3D.C src/fe/fe_boundary.C \ + src/fe/fe_clough.C src/fe/fe_clough_shape_0D.C \ + src/fe/fe_clough_shape_1D.C src/fe/fe_clough_shape_2D.C \ + src/fe/fe_clough_shape_3D.C src/fe/fe_compute_data.C \ + src/fe/fe_hermite.C src/fe/fe_hermite_shape_0D.C \ + src/fe/fe_hermite_shape_1D.C src/fe/fe_hermite_shape_2D.C \ + src/fe/fe_hermite_shape_3D.C src/fe/fe_hierarchic.C \ + src/fe/fe_hierarchic_shape_0D.C \ + src/fe/fe_hierarchic_shape_1D.C \ + src/fe/fe_hierarchic_shape_2D.C \ + src/fe/fe_hierarchic_shape_3D.C src/fe/fe_hierarchic_vec.C \ + src/fe/fe_interface.C src/fe/fe_interface_inf_fe.C \ + src/fe/fe_l2_hierarchic.C src/fe/fe_l2_lagrange.C \ + src/fe/fe_lagrange.C src/fe/fe_lagrange_shape_0D.C \ + src/fe/fe_lagrange_shape_1D.C src/fe/fe_lagrange_shape_2D.C \ + src/fe/fe_lagrange_shape_3D.C src/fe/fe_lagrange_vec.C \ + src/fe/fe_map.C src/fe/fe_monomial.C \ + src/fe/fe_monomial_shape_0D.C src/fe/fe_monomial_shape_1D.C \ + src/fe/fe_monomial_shape_2D.C src/fe/fe_monomial_shape_3D.C \ + src/fe/fe_monomial_vec.C src/fe/fe_nedelec_one.C \ + src/fe/fe_nedelec_one_shape_2D.C \ + src/fe/fe_nedelec_one_shape_3D.C src/fe/fe_rational.C \ + src/fe/fe_rational_shape_0D.C src/fe/fe_rational_shape_1D.C \ + src/fe/fe_rational_shape_2D.C src/fe/fe_rational_shape_3D.C \ + src/fe/fe_raviart.C src/fe/fe_raviart_shape_2D.C \ + src/fe/fe_raviart_shape_3D.C src/fe/fe_scalar.C \ + src/fe/fe_scalar_shape_0D.C src/fe/fe_scalar_shape_1D.C \ + src/fe/fe_scalar_shape_2D.C src/fe/fe_scalar_shape_3D.C \ + src/fe/fe_side_hierarchic.C src/fe/fe_subdivision_2D.C \ + src/fe/fe_szabab.C src/fe/fe_szabab_shape_0D.C \ + src/fe/fe_szabab_shape_1D.C src/fe/fe_szabab_shape_2D.C \ + src/fe/fe_szabab_shape_3D.C src/fe/fe_transformation_base.C \ + src/fe/fe_type.C src/fe/fe_xyz.C src/fe/fe_xyz_boundary.C \ + src/fe/fe_xyz_map.C src/fe/fe_xyz_shape_0D.C \ + src/fe/fe_xyz_shape_1D.C src/fe/fe_xyz_shape_2D.C \ + src/fe/fe_xyz_shape_3D.C src/fe/h1_fe_transformation.C \ + src/fe/hcurl_fe_transformation.C \ + src/fe/hdiv_fe_transformation.C src/fe/inf_fe.C \ + src/fe/inf_fe_base_radial.C src/fe/inf_fe_boundary.C \ + src/fe/inf_fe_jacobi_20_00_eval.C \ + src/fe/inf_fe_jacobi_30_00_eval.C \ + src/fe/inf_fe_lagrange_eval.C src/fe/inf_fe_legendre_eval.C \ + src/fe/inf_fe_map.C src/fe/inf_fe_map_eval.C \ + src/fe/inf_fe_static.C src/geom/bounding_box.C src/geom/cell.C \ + src/geom/cell_c0polyhedron.C src/geom/cell_hex.C \ + src/geom/cell_hex20.C src/geom/cell_hex27.C \ + src/geom/cell_hex8.C src/geom/cell_inf.C \ + src/geom/cell_inf_hex.C src/geom/cell_inf_hex16.C \ + src/geom/cell_inf_hex18.C src/geom/cell_inf_hex8.C \ + src/geom/cell_inf_prism.C src/geom/cell_inf_prism12.C \ + src/geom/cell_inf_prism6.C src/geom/cell_polyhedron.C \ + src/geom/cell_prism.C src/geom/cell_prism15.C \ + src/geom/cell_prism18.C src/geom/cell_prism20.C \ + src/geom/cell_prism21.C src/geom/cell_prism6.C \ + src/geom/cell_pyramid.C src/geom/cell_pyramid13.C \ + src/geom/cell_pyramid14.C src/geom/cell_pyramid18.C \ + src/geom/cell_pyramid5.C src/geom/cell_tet.C \ + src/geom/cell_tet10.C src/geom/cell_tet14.C \ + src/geom/cell_tet4.C src/geom/edge.C src/geom/edge_edge2.C \ + src/geom/edge_edge3.C src/geom/edge_edge4.C \ + src/geom/edge_inf_edge2.C src/geom/elem.C \ + src/geom/elem_cutter.C src/geom/elem_quality.C \ + src/geom/elem_refinement.C src/geom/elem_side_builder.C \ + src/geom/face.C src/geom/face_c0polygon.C \ + src/geom/face_inf_quad.C src/geom/face_inf_quad4.C \ + src/geom/face_inf_quad6.C src/geom/face_polygon.C \ + src/geom/face_quad.C src/geom/face_quad4.C \ + src/geom/face_quad4_shell.C src/geom/face_quad8.C \ + src/geom/face_quad8_shell.C src/geom/face_quad9.C \ + src/geom/face_quad9_shell.C src/geom/face_tri.C \ + src/geom/face_tri3.C src/geom/face_tri3_shell.C \ + src/geom/face_tri3_subdivision.C src/geom/face_tri6.C \ + src/geom/face_tri7.C src/geom/node.C src/geom/node_elem.C \ + src/geom/plane.C src/geom/point.C src/geom/reference_elem.C \ + src/geom/reference_elem.data src/geom/remote_elem.C \ + src/geom/sphere.C src/geom/surface.C \ + src/ghosting/default_coupling.C \ + src/ghosting/ghost_point_neighbors.C \ + src/ghosting/non_manifold_coupling.C \ + src/ghosting/overlap_coupling.C \ + src/ghosting/point_neighbor_coupling.C \ + src/ghosting/sibling_coupling.C src/mesh/abaqus_io.C \ + src/mesh/boundary_info.C src/mesh/boundary_mesh.C \ + src/mesh/checkpoint_io.C src/mesh/distributed_mesh.C \ + src/mesh/dyna_io.C src/mesh/ensight_io.C \ + src/mesh/exodusII_io.C src/mesh/exodusII_io_helper.C \ + src/mesh/fro_io.C src/mesh/gmsh_io.C src/mesh/gmv_io.C \ + src/mesh/gnuplot_io.C src/mesh/inf_elem_builder.C \ + src/mesh/matlab_io.C src/mesh/medit_io.C src/mesh/mesh_base.C \ + src/mesh/mesh_communication.C \ + src/mesh/mesh_communication_global_indices.C \ + src/mesh/mesh_function.C src/mesh/mesh_generation.C \ + src/mesh/mesh_iterators.C src/mesh/mesh_modification.C \ + src/mesh/mesh_netgen_interface.C src/mesh/mesh_output.C \ + src/mesh/mesh_refinement.C src/mesh/mesh_refinement_flagging.C \ + src/mesh/mesh_refinement_smoothing.C \ + src/mesh/mesh_serializer.C src/mesh/mesh_smoother.C \ + src/mesh/mesh_smoother_laplace.C \ + src/mesh/mesh_smoother_vsmoother.C \ + src/mesh/mesh_subdivision_support.C \ + src/mesh/mesh_tet_interface.C src/mesh/mesh_tetgen_interface.C \ + src/mesh/mesh_tetgen_wrapper.C src/mesh/mesh_tools.C \ + src/mesh/mesh_triangle_holes.C \ + src/mesh/mesh_triangle_interface.C \ + src/mesh/mesh_triangle_wrapper.C src/mesh/namebased_io.C \ + src/mesh/nemesis_io.C src/mesh/nemesis_io_helper.C \ + src/mesh/off_io.C src/mesh/patch.C \ + src/mesh/poly2tri_triangulator.C src/mesh/postscript_io.C \ + src/mesh/replicated_mesh.C src/mesh/sides_to_elem_map.C \ + src/mesh/simplex_refiner.C src/mesh/stl_io.C \ + src/mesh/tecplot_io.C src/mesh/tetgen_io.C \ + src/mesh/triangulator_interface.C src/mesh/ucd_io.C \ + src/mesh/unstructured_mesh.C src/mesh/unv_io.C \ + src/mesh/vtk_io.C src/mesh/xdr_io.C \ + src/numerics/coupling_matrix.C src/numerics/dense_matrix.C \ + src/numerics/dense_matrix_base.C \ + src/numerics/dense_matrix_blas_lapack.C \ + src/numerics/dense_submatrix.C src/numerics/dense_subvector.C \ + src/numerics/dense_vector.C src/numerics/dense_vector_base.C \ + src/numerics/diagonal_matrix.C \ + src/numerics/distributed_vector.C \ + src/numerics/eigen_preconditioner.C \ + src/numerics/eigen_sparse_matrix.C \ + src/numerics/eigen_sparse_vector.C \ + src/numerics/laspack_matrix.C src/numerics/laspack_vector.C \ + src/numerics/lumped_mass_matrix.C \ + src/numerics/numeric_vector.C src/numerics/petsc_matrix.C \ + src/numerics/petsc_matrix_base.C \ + src/numerics/petsc_matrix_shell_matrix.C \ + src/numerics/petsc_preconditioner.C \ + src/numerics/petsc_shell_matrix.C src/numerics/petsc_vector.C \ + src/numerics/preconditioner.C src/numerics/shell_matrix.C \ + src/numerics/sparse_matrix.C \ + src/numerics/sparse_shell_matrix.C \ + src/numerics/static_condensation.C \ + src/numerics/static_condensation_dof_map.C \ + src/numerics/sum_shell_matrix.C \ + src/numerics/tensor_shell_matrix.C src/numerics/tensor_tools.C \ + src/numerics/trilinos_epetra_matrix.C \ + src/numerics/trilinos_epetra_vector.C \ + src/numerics/trilinos_preconditioner.C \ + src/numerics/type_tensor.C src/numerics/type_vector.C \ + src/numerics/wrapped_petsc.C \ + src/parallel/parallel_bin_sorter.C \ + src/parallel/parallel_elem.C \ + src/parallel/parallel_ghost_sync.C \ + src/parallel/parallel_histogram.C src/parallel/parallel_node.C \ + src/parallel/parallel_sort.C src/parallel/threads.C \ + src/partitioning/centroid_partitioner.C \ + src/partitioning/linear_partitioner.C \ + src/partitioning/mapped_subdomain_partitioner.C \ + src/partitioning/metis_partitioner.C \ + src/partitioning/parmetis_partitioner.C \ + src/partitioning/partitioner.C \ + src/partitioning/partitioner_factory.C \ + src/partitioning/sfc_partitioner.C \ + src/partitioning/subdomain_partitioner.C \ + src/physics/diff_physics.C src/physics/diff_qoi.C \ + src/physics/fem_physics.C src/quadrature/quadrature.C \ + src/quadrature/quadrature_build.C \ + src/quadrature/quadrature_clough.C \ + src/quadrature/quadrature_clough_1D.C \ + src/quadrature/quadrature_clough_2D.C \ + src/quadrature/quadrature_clough_3D.C \ + src/quadrature/quadrature_composite.C \ + src/quadrature/quadrature_conical.C \ + src/quadrature/quadrature_conical_2D.C \ + src/quadrature/quadrature_conical_3D.C \ + src/quadrature/quadrature_gauss.C \ + src/quadrature/quadrature_gauss_1D.C \ + src/quadrature/quadrature_gauss_2D.C \ + src/quadrature/quadrature_gauss_3D.C \ + src/quadrature/quadrature_gauss_lobatto.C \ + src/quadrature/quadrature_gauss_lobatto_1D.C \ + src/quadrature/quadrature_gauss_lobatto_2D.C \ + src/quadrature/quadrature_gauss_lobatto_3D.C \ + src/quadrature/quadrature_gm.C \ + src/quadrature/quadrature_gm_2D.C \ + src/quadrature/quadrature_gm_3D.C \ + src/quadrature/quadrature_grid.C \ + src/quadrature/quadrature_grid_1D.C \ + src/quadrature/quadrature_grid_2D.C \ + src/quadrature/quadrature_grid_3D.C \ + src/quadrature/quadrature_jacobi.C \ + src/quadrature/quadrature_jacobi_1D.C \ + src/quadrature/quadrature_monomial.C \ + src/quadrature/quadrature_monomial_1D.C \ + src/quadrature/quadrature_monomial_2D.C \ + src/quadrature/quadrature_monomial_3D.C \ + src/quadrature/quadrature_nodal.C \ + src/quadrature/quadrature_nodal_1D.C \ + src/quadrature/quadrature_nodal_2D.C \ + src/quadrature/quadrature_nodal_3D.C \ + src/quadrature/quadrature_simpson.C \ + src/quadrature/quadrature_simpson_1D.C \ + src/quadrature/quadrature_simpson_2D.C \ + src/quadrature/quadrature_simpson_3D.C \ + src/quadrature/quadrature_trap.C \ + src/quadrature/quadrature_trap_1D.C \ + src/quadrature/quadrature_trap_2D.C \ + src/quadrature/quadrature_trap_3D.C \ + src/reduced_basis/rb_assembly_expansion.C \ + src/reduced_basis/rb_construction.C \ + src/reduced_basis/rb_construction_base.C \ + src/reduced_basis/rb_data_deserialization.C \ + src/reduced_basis/rb_data_serialization.C \ + src/reduced_basis/rb_eim_assembly.C \ + src/reduced_basis/rb_eim_construction.C \ + src/reduced_basis/rb_eim_evaluation.C \ + src/reduced_basis/rb_eim_theta.C \ + src/reduced_basis/rb_evaluation.C \ + src/reduced_basis/rb_parameters.C \ + src/reduced_basis/rb_parametrized.C \ + src/reduced_basis/rb_parametrized_function.C \ + src/reduced_basis/rb_scm_construction.C \ + src/reduced_basis/rb_scm_evaluation.C \ + src/reduced_basis/rb_temporal_discretization.C \ + src/reduced_basis/rb_theta.C \ + src/reduced_basis/rb_theta_expansion.C \ + src/reduced_basis/transient_rb_assembly_expansion.C \ + src/reduced_basis/transient_rb_construction.C \ + src/reduced_basis/transient_rb_evaluation.C \ + src/reduced_basis/transient_rb_theta_expansion.C \ + src/solution_transfer/boundary_volume_solution_transfer.C \ + src/solution_transfer/direct_solution_transfer.C \ + src/solution_transfer/dtk_adapter.C \ + src/solution_transfer/dtk_evaluator.C \ + src/solution_transfer/dtk_solution_transfer.C \ + src/solution_transfer/meshfree_interpolation.C \ + src/solution_transfer/meshfree_interpolation_function.C \ + src/solution_transfer/meshfree_solution_transfer.C \ + src/solution_transfer/meshfunction_solution_transfer.C \ + src/solution_transfer/radial_basis_interpolation.C \ + src/solution_transfer/solution_transfer.C \ + src/solvers/adaptive_time_solver.C src/solvers/diff_solver.C \ + src/solvers/eigen_solver.C \ + src/solvers/eigen_sparse_linear_solver.C \ + src/solvers/eigen_time_solver.C src/solvers/euler2_solver.C \ + src/solvers/euler_solver.C src/solvers/file_history_data.C \ + src/solvers/file_solution_history.C \ + src/solvers/first_order_unsteady_solver.C \ + src/solvers/laspack_linear_solver.C \ + src/solvers/linear_solver.C src/solvers/memory_history_data.C \ + src/solvers/memory_solution_history.C \ + src/solvers/newmark_solver.C src/solvers/newton_solver.C \ + src/solvers/nlopt_optimization_solver.C \ + src/solvers/no_solution_history.C \ + src/solvers/nonlinear_solver.C \ + src/solvers/optimization_solver.C \ + src/solvers/petsc_auto_fieldsplit.C \ + src/solvers/petsc_diff_solver.C src/solvers/petsc_dm_wrapper.C \ + src/solvers/petsc_linear_solver.C \ + src/solvers/petsc_nonlinear_solver.C \ + src/solvers/petscdmlibmesh.C src/solvers/petscdmlibmeshimpl.C \ + src/solvers/second_order_unsteady_solver.C \ + src/solvers/slepc_eigen_solver.C \ + src/solvers/solution_history.C src/solvers/steady_solver.C \ + src/solvers/tao_optimization_solver.C \ + src/solvers/time_solver.C \ + src/solvers/trilinos_aztec_linear_solver.C \ + src/solvers/trilinos_nox_nonlinear_solver.C \ + src/solvers/twostep_time_solver.C \ + src/solvers/unsteady_solver.C \ + src/systems/condensed_eigen_system.C \ + src/systems/continuation_system.C src/systems/dg_fem_context.C \ + src/systems/diff_context.C src/systems/diff_system.C \ + src/systems/eigen_system.C src/systems/equation_systems.C \ + src/systems/equation_systems_io.C \ + src/systems/explicit_system.C src/systems/fem_context.C \ + src/systems/fem_system.C src/systems/frequency_system.C \ + src/systems/implicit_system.C \ + src/systems/inter_mesh_projection.C \ + src/systems/linear_implicit_system.C \ + src/systems/newmark_system.C \ + src/systems/nonlinear_implicit_system.C \ + src/systems/optimization_system.C \ + src/systems/parameter_vector.C src/systems/qoi_set.C \ + src/systems/steady_system.C src/systems/system.C \ + src/systems/system_io.C src/systems/system_norm.C \ + src/systems/system_projection.C src/systems/system_subset.C \ + src/systems/system_subset_by_subdomain.C \ + src/systems/transient_system.C \ + src/systems/variational_smoother_constraint.C \ + src/systems/variational_smoother_system.C \ + src/utils/error_vector.C src/utils/hashword.C \ + src/utils/location_maps.C src/utils/number_lookups.C \ + src/utils/perf_log.C src/utils/plt_loader.C \ + src/utils/plt_loader_read.C src/utils/plt_loader_write.C \ + src/utils/point_locator_base.C \ + src/utils/point_locator_nanoflann.C \ + src/utils/point_locator_tree.C src/utils/statistics.C \ + src/utils/string_to_enum.C src/utils/thread_buffered_syncbuf.C \ + src/utils/timestamp.C src/utils/topology_map.C \ + src/utils/tree.C src/utils/tree_node.C src/utils/utility.C \ + src/utils/xdr_cxx.C $(am__append_11) # A convenience library to hold proper libMesh # objects. This will get appended with any contributed # sources to create the final library. -lib_LTLIBRARIES = $(am__append_11) $(am__append_12) $(am__append_13) \ - $(am__append_14) $(am__append_15) +lib_LTLIBRARIES = $(am__append_13) $(am__append_14) $(am__append_15) \ + $(am__append_16) $(am__append_17) @LIBMESH_DBG_MODE_TRUE@libmesh_dbg_la_SOURCES = $(libmesh_SOURCES) @LIBMESH_DBG_MODE_TRUE@libmesh_dbg_la_CPPFLAGS = $(CPPFLAGS_DBG) $(AM_CPPFLAGS) @LIBMESH_DBG_MODE_TRUE@libmesh_dbg_la_CXXFLAGS = $(CXXFLAGS_DBG) @@ -8371,7 +8231,7 @@ lib_LTLIBRARIES = $(am__append_11) $(am__append_12) $(am__append_13) \ @LIBMESH_OPROF_MODE_TRUE@libmesh_oprof_la_CFLAGS = $(CFLAGS_OPROF) @LIBMESH_OPROF_MODE_TRUE@libmesh_oprof_la_LIBADD = contrib/libcontrib_oprof.la $(LIBS) bin_SCRIPTS = # empty, append below -CLEANFILES = $(am__append_21) +CLEANFILES = $(am__append_23) ########################################################### # Utility programs @@ -10069,6 +9929,14 @@ src/utils/libmesh_dbg_la-utility.lo: src/utils/$(am__dirstamp) \ src/utils/$(DEPDIR)/$(am__dirstamp) src/utils/libmesh_dbg_la-xdr_cxx.lo: src/utils/$(am__dirstamp) \ src/utils/$(DEPDIR)/$(am__dirstamp) +src/kokkos/$(am__dirstamp): + @$(MKDIR_P) src/kokkos + @: >>src/kokkos/$(am__dirstamp) +src/kokkos/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/kokkos/$(DEPDIR) + @: >>src/kokkos/$(DEPDIR)/$(am__dirstamp) +src/kokkos/libmesh_dbg_la-fe_types.lo: src/kokkos/$(am__dirstamp) \ + src/kokkos/$(DEPDIR)/$(am__dirstamp) libmesh_dbg.la: $(libmesh_dbg_la_OBJECTS) $(libmesh_dbg_la_DEPENDENCIES) $(EXTRA_libmesh_dbg_la_DEPENDENCIES) $(AM_V_CXXLD)$(libmesh_dbg_la_LINK) $(am_libmesh_dbg_la_rpath) $(libmesh_dbg_la_OBJECTS) $(libmesh_dbg_la_LIBADD) $(LIBS) @@ -11243,6 +11111,8 @@ src/utils/libmesh_devel_la-utility.lo: src/utils/$(am__dirstamp) \ src/utils/$(DEPDIR)/$(am__dirstamp) src/utils/libmesh_devel_la-xdr_cxx.lo: src/utils/$(am__dirstamp) \ src/utils/$(DEPDIR)/$(am__dirstamp) +src/kokkos/libmesh_devel_la-fe_types.lo: src/kokkos/$(am__dirstamp) \ + src/kokkos/$(DEPDIR)/$(am__dirstamp) libmesh_devel.la: $(libmesh_devel_la_OBJECTS) $(libmesh_devel_la_DEPENDENCIES) $(EXTRA_libmesh_devel_la_DEPENDENCIES) $(AM_V_CXXLD)$(libmesh_devel_la_LINK) $(am_libmesh_devel_la_rpath) $(libmesh_devel_la_OBJECTS) $(libmesh_devel_la_LIBADD) $(LIBS) @@ -12417,6 +12287,8 @@ src/utils/libmesh_oprof_la-utility.lo: src/utils/$(am__dirstamp) \ src/utils/$(DEPDIR)/$(am__dirstamp) src/utils/libmesh_oprof_la-xdr_cxx.lo: src/utils/$(am__dirstamp) \ src/utils/$(DEPDIR)/$(am__dirstamp) +src/kokkos/libmesh_oprof_la-fe_types.lo: src/kokkos/$(am__dirstamp) \ + src/kokkos/$(DEPDIR)/$(am__dirstamp) libmesh_oprof.la: $(libmesh_oprof_la_OBJECTS) $(libmesh_oprof_la_DEPENDENCIES) $(EXTRA_libmesh_oprof_la_DEPENDENCIES) $(AM_V_CXXLD)$(libmesh_oprof_la_LINK) $(am_libmesh_oprof_la_rpath) $(libmesh_oprof_la_OBJECTS) $(libmesh_oprof_la_LIBADD) $(LIBS) @@ -13588,6 +13460,8 @@ src/utils/libmesh_opt_la-utility.lo: src/utils/$(am__dirstamp) \ src/utils/$(DEPDIR)/$(am__dirstamp) src/utils/libmesh_opt_la-xdr_cxx.lo: src/utils/$(am__dirstamp) \ src/utils/$(DEPDIR)/$(am__dirstamp) +src/kokkos/libmesh_opt_la-fe_types.lo: src/kokkos/$(am__dirstamp) \ + src/kokkos/$(DEPDIR)/$(am__dirstamp) libmesh_opt.la: $(libmesh_opt_la_OBJECTS) $(libmesh_opt_la_DEPENDENCIES) $(EXTRA_libmesh_opt_la_DEPENDENCIES) $(AM_V_CXXLD)$(libmesh_opt_la_LINK) $(am_libmesh_opt_la_rpath) $(libmesh_opt_la_OBJECTS) $(libmesh_opt_la_LIBADD) $(LIBS) @@ -14760,6 +14634,8 @@ src/utils/libmesh_prof_la-utility.lo: src/utils/$(am__dirstamp) \ src/utils/$(DEPDIR)/$(am__dirstamp) src/utils/libmesh_prof_la-xdr_cxx.lo: src/utils/$(am__dirstamp) \ src/utils/$(DEPDIR)/$(am__dirstamp) +src/kokkos/libmesh_prof_la-fe_types.lo: src/kokkos/$(am__dirstamp) \ + src/kokkos/$(DEPDIR)/$(am__dirstamp) libmesh_prof.la: $(libmesh_prof_la_OBJECTS) $(libmesh_prof_la_DEPENDENCIES) $(EXTRA_libmesh_prof_la_DEPENDENCIES) $(AM_V_CXXLD)$(libmesh_prof_la_LINK) $(am_libmesh_prof_la_rpath) $(libmesh_prof_la_OBJECTS) $(libmesh_prof_la_LIBADD) $(LIBS) @@ -15236,6 +15112,8 @@ mostlyclean-compile: -rm -f src/geom/*.lo -rm -f src/ghosting/*.$(OBJEXT) -rm -f src/ghosting/*.lo + -rm -f src/kokkos/*.$(OBJEXT) + -rm -f src/kokkos/*.lo -rm -f src/mesh/*.$(OBJEXT) -rm -f src/mesh/*.lo -rm -f src/numerics/*.$(OBJEXT) @@ -16307,6 +16185,11 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/ghosting/$(DEPDIR)/libmesh_prof_la-overlap_coupling.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/ghosting/$(DEPDIR)/libmesh_prof_la-point_neighbor_coupling.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/ghosting/$(DEPDIR)/libmesh_prof_la-sibling_coupling.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/kokkos/$(DEPDIR)/libmesh_dbg_la-fe_types.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/kokkos/$(DEPDIR)/libmesh_devel_la-fe_types.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/kokkos/$(DEPDIR)/libmesh_oprof_la-fe_types.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/kokkos/$(DEPDIR)/libmesh_opt_la-fe_types.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/kokkos/$(DEPDIR)/libmesh_prof_la-fe_types.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/mesh/$(DEPDIR)/libmesh_dbg_la-abaqus_io.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/mesh/$(DEPDIR)/libmesh_dbg_la-boundary_info.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/mesh/$(DEPDIR)/libmesh_dbg_la-boundary_mesh.Plo@am__quote@ # am--include-marker @@ -21065,6 +20948,13 @@ src/utils/libmesh_dbg_la-xdr_cxx.lo: src/utils/xdr_cxx.C @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmesh_dbg_la_CPPFLAGS) $(CPPFLAGS) $(libmesh_dbg_la_CXXFLAGS) $(CXXFLAGS) -c -o src/utils/libmesh_dbg_la-xdr_cxx.lo `test -f 'src/utils/xdr_cxx.C' || echo '$(srcdir)/'`src/utils/xdr_cxx.C +src/kokkos/libmesh_dbg_la-fe_types.lo: src/kokkos/fe_types.C +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmesh_dbg_la_CPPFLAGS) $(CPPFLAGS) $(libmesh_dbg_la_CXXFLAGS) $(CXXFLAGS) -MT src/kokkos/libmesh_dbg_la-fe_types.lo -MD -MP -MF src/kokkos/$(DEPDIR)/libmesh_dbg_la-fe_types.Tpo -c -o src/kokkos/libmesh_dbg_la-fe_types.lo `test -f 'src/kokkos/fe_types.C' || echo '$(srcdir)/'`src/kokkos/fe_types.C +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/kokkos/$(DEPDIR)/libmesh_dbg_la-fe_types.Tpo src/kokkos/$(DEPDIR)/libmesh_dbg_la-fe_types.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/kokkos/fe_types.C' object='src/kokkos/libmesh_dbg_la-fe_types.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmesh_dbg_la_CPPFLAGS) $(CPPFLAGS) $(libmesh_dbg_la_CXXFLAGS) $(CXXFLAGS) -c -o src/kokkos/libmesh_dbg_la-fe_types.lo `test -f 'src/kokkos/fe_types.C' || echo '$(srcdir)/'`src/kokkos/fe_types.C + src/base/libmesh_devel_la-dirichlet_boundary.lo: src/base/dirichlet_boundary.C @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmesh_devel_la_CPPFLAGS) $(CPPFLAGS) $(libmesh_devel_la_CXXFLAGS) $(CXXFLAGS) -MT src/base/libmesh_devel_la-dirichlet_boundary.lo -MD -MP -MF src/base/$(DEPDIR)/libmesh_devel_la-dirichlet_boundary.Tpo -c -o src/base/libmesh_devel_la-dirichlet_boundary.lo `test -f 'src/base/dirichlet_boundary.C' || echo '$(srcdir)/'`src/base/dirichlet_boundary.C @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/base/$(DEPDIR)/libmesh_devel_la-dirichlet_boundary.Tpo src/base/$(DEPDIR)/libmesh_devel_la-dirichlet_boundary.Plo @@ -24397,6 +24287,13 @@ src/utils/libmesh_devel_la-xdr_cxx.lo: src/utils/xdr_cxx.C @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmesh_devel_la_CPPFLAGS) $(CPPFLAGS) $(libmesh_devel_la_CXXFLAGS) $(CXXFLAGS) -c -o src/utils/libmesh_devel_la-xdr_cxx.lo `test -f 'src/utils/xdr_cxx.C' || echo '$(srcdir)/'`src/utils/xdr_cxx.C +src/kokkos/libmesh_devel_la-fe_types.lo: src/kokkos/fe_types.C +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmesh_devel_la_CPPFLAGS) $(CPPFLAGS) $(libmesh_devel_la_CXXFLAGS) $(CXXFLAGS) -MT src/kokkos/libmesh_devel_la-fe_types.lo -MD -MP -MF src/kokkos/$(DEPDIR)/libmesh_devel_la-fe_types.Tpo -c -o src/kokkos/libmesh_devel_la-fe_types.lo `test -f 'src/kokkos/fe_types.C' || echo '$(srcdir)/'`src/kokkos/fe_types.C +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/kokkos/$(DEPDIR)/libmesh_devel_la-fe_types.Tpo src/kokkos/$(DEPDIR)/libmesh_devel_la-fe_types.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/kokkos/fe_types.C' object='src/kokkos/libmesh_devel_la-fe_types.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmesh_devel_la_CPPFLAGS) $(CPPFLAGS) $(libmesh_devel_la_CXXFLAGS) $(CXXFLAGS) -c -o src/kokkos/libmesh_devel_la-fe_types.lo `test -f 'src/kokkos/fe_types.C' || echo '$(srcdir)/'`src/kokkos/fe_types.C + src/base/libmesh_oprof_la-dirichlet_boundary.lo: src/base/dirichlet_boundary.C @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmesh_oprof_la_CPPFLAGS) $(CPPFLAGS) $(libmesh_oprof_la_CXXFLAGS) $(CXXFLAGS) -MT src/base/libmesh_oprof_la-dirichlet_boundary.lo -MD -MP -MF src/base/$(DEPDIR)/libmesh_oprof_la-dirichlet_boundary.Tpo -c -o src/base/libmesh_oprof_la-dirichlet_boundary.lo `test -f 'src/base/dirichlet_boundary.C' || echo '$(srcdir)/'`src/base/dirichlet_boundary.C @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/base/$(DEPDIR)/libmesh_oprof_la-dirichlet_boundary.Tpo src/base/$(DEPDIR)/libmesh_oprof_la-dirichlet_boundary.Plo @@ -27729,6 +27626,13 @@ src/utils/libmesh_oprof_la-xdr_cxx.lo: src/utils/xdr_cxx.C @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmesh_oprof_la_CPPFLAGS) $(CPPFLAGS) $(libmesh_oprof_la_CXXFLAGS) $(CXXFLAGS) -c -o src/utils/libmesh_oprof_la-xdr_cxx.lo `test -f 'src/utils/xdr_cxx.C' || echo '$(srcdir)/'`src/utils/xdr_cxx.C +src/kokkos/libmesh_oprof_la-fe_types.lo: src/kokkos/fe_types.C +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmesh_oprof_la_CPPFLAGS) $(CPPFLAGS) $(libmesh_oprof_la_CXXFLAGS) $(CXXFLAGS) -MT src/kokkos/libmesh_oprof_la-fe_types.lo -MD -MP -MF src/kokkos/$(DEPDIR)/libmesh_oprof_la-fe_types.Tpo -c -o src/kokkos/libmesh_oprof_la-fe_types.lo `test -f 'src/kokkos/fe_types.C' || echo '$(srcdir)/'`src/kokkos/fe_types.C +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/kokkos/$(DEPDIR)/libmesh_oprof_la-fe_types.Tpo src/kokkos/$(DEPDIR)/libmesh_oprof_la-fe_types.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/kokkos/fe_types.C' object='src/kokkos/libmesh_oprof_la-fe_types.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmesh_oprof_la_CPPFLAGS) $(CPPFLAGS) $(libmesh_oprof_la_CXXFLAGS) $(CXXFLAGS) -c -o src/kokkos/libmesh_oprof_la-fe_types.lo `test -f 'src/kokkos/fe_types.C' || echo '$(srcdir)/'`src/kokkos/fe_types.C + src/base/libmesh_opt_la-dirichlet_boundary.lo: src/base/dirichlet_boundary.C @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmesh_opt_la_CPPFLAGS) $(CPPFLAGS) $(libmesh_opt_la_CXXFLAGS) $(CXXFLAGS) -MT src/base/libmesh_opt_la-dirichlet_boundary.lo -MD -MP -MF src/base/$(DEPDIR)/libmesh_opt_la-dirichlet_boundary.Tpo -c -o src/base/libmesh_opt_la-dirichlet_boundary.lo `test -f 'src/base/dirichlet_boundary.C' || echo '$(srcdir)/'`src/base/dirichlet_boundary.C @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/base/$(DEPDIR)/libmesh_opt_la-dirichlet_boundary.Tpo src/base/$(DEPDIR)/libmesh_opt_la-dirichlet_boundary.Plo @@ -31061,6 +30965,13 @@ src/utils/libmesh_opt_la-xdr_cxx.lo: src/utils/xdr_cxx.C @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmesh_opt_la_CPPFLAGS) $(CPPFLAGS) $(libmesh_opt_la_CXXFLAGS) $(CXXFLAGS) -c -o src/utils/libmesh_opt_la-xdr_cxx.lo `test -f 'src/utils/xdr_cxx.C' || echo '$(srcdir)/'`src/utils/xdr_cxx.C +src/kokkos/libmesh_opt_la-fe_types.lo: src/kokkos/fe_types.C +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmesh_opt_la_CPPFLAGS) $(CPPFLAGS) $(libmesh_opt_la_CXXFLAGS) $(CXXFLAGS) -MT src/kokkos/libmesh_opt_la-fe_types.lo -MD -MP -MF src/kokkos/$(DEPDIR)/libmesh_opt_la-fe_types.Tpo -c -o src/kokkos/libmesh_opt_la-fe_types.lo `test -f 'src/kokkos/fe_types.C' || echo '$(srcdir)/'`src/kokkos/fe_types.C +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/kokkos/$(DEPDIR)/libmesh_opt_la-fe_types.Tpo src/kokkos/$(DEPDIR)/libmesh_opt_la-fe_types.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/kokkos/fe_types.C' object='src/kokkos/libmesh_opt_la-fe_types.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmesh_opt_la_CPPFLAGS) $(CPPFLAGS) $(libmesh_opt_la_CXXFLAGS) $(CXXFLAGS) -c -o src/kokkos/libmesh_opt_la-fe_types.lo `test -f 'src/kokkos/fe_types.C' || echo '$(srcdir)/'`src/kokkos/fe_types.C + src/base/libmesh_prof_la-dirichlet_boundary.lo: src/base/dirichlet_boundary.C @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmesh_prof_la_CPPFLAGS) $(CPPFLAGS) $(libmesh_prof_la_CXXFLAGS) $(CXXFLAGS) -MT src/base/libmesh_prof_la-dirichlet_boundary.lo -MD -MP -MF src/base/$(DEPDIR)/libmesh_prof_la-dirichlet_boundary.Tpo -c -o src/base/libmesh_prof_la-dirichlet_boundary.lo `test -f 'src/base/dirichlet_boundary.C' || echo '$(srcdir)/'`src/base/dirichlet_boundary.C @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/base/$(DEPDIR)/libmesh_prof_la-dirichlet_boundary.Tpo src/base/$(DEPDIR)/libmesh_prof_la-dirichlet_boundary.Plo @@ -34393,6 +34304,13 @@ src/utils/libmesh_prof_la-xdr_cxx.lo: src/utils/xdr_cxx.C @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmesh_prof_la_CPPFLAGS) $(CPPFLAGS) $(libmesh_prof_la_CXXFLAGS) $(CXXFLAGS) -c -o src/utils/libmesh_prof_la-xdr_cxx.lo `test -f 'src/utils/xdr_cxx.C' || echo '$(srcdir)/'`src/utils/xdr_cxx.C +src/kokkos/libmesh_prof_la-fe_types.lo: src/kokkos/fe_types.C +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmesh_prof_la_CPPFLAGS) $(CPPFLAGS) $(libmesh_prof_la_CXXFLAGS) $(CXXFLAGS) -MT src/kokkos/libmesh_prof_la-fe_types.lo -MD -MP -MF src/kokkos/$(DEPDIR)/libmesh_prof_la-fe_types.Tpo -c -o src/kokkos/libmesh_prof_la-fe_types.lo `test -f 'src/kokkos/fe_types.C' || echo '$(srcdir)/'`src/kokkos/fe_types.C +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/kokkos/$(DEPDIR)/libmesh_prof_la-fe_types.Tpo src/kokkos/$(DEPDIR)/libmesh_prof_la-fe_types.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/kokkos/fe_types.C' object='src/kokkos/libmesh_prof_la-fe_types.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmesh_prof_la_CPPFLAGS) $(CPPFLAGS) $(libmesh_prof_la_CXXFLAGS) $(CXXFLAGS) -c -o src/kokkos/libmesh_prof_la-fe_types.lo `test -f 'src/kokkos/fe_types.C' || echo '$(srcdir)/'`src/kokkos/fe_types.C + src/apps/amr_dbg-amr.o: src/apps/amr.C @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(amr_dbg_CPPFLAGS) $(CPPFLAGS) $(amr_dbg_CXXFLAGS) $(CXXFLAGS) -MT src/apps/amr_dbg-amr.o -MD -MP -MF src/apps/$(DEPDIR)/amr_dbg-amr.Tpo -c -o src/apps/amr_dbg-amr.o `test -f 'src/apps/amr.C' || echo '$(srcdir)/'`src/apps/amr.C @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/apps/$(DEPDIR)/amr_dbg-amr.Tpo src/apps/$(DEPDIR)/amr_dbg-amr.Po @@ -35243,6 +35161,7 @@ clean-libtool: -rm -rf src/fe/.libs src/fe/_libs -rm -rf src/geom/.libs src/geom/_libs -rm -rf src/ghosting/.libs src/ghosting/_libs + -rm -rf src/kokkos/.libs src/kokkos/_libs -rm -rf src/mesh/.libs src/mesh/_libs -rm -rf src/numerics/.libs src/numerics/_libs -rm -rf src/parallel/.libs src/parallel/_libs @@ -35684,6 +35603,8 @@ distclean-generic: -$(am__rm_f) src/geom/$(am__dirstamp) -$(am__rm_f) src/ghosting/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) src/ghosting/$(am__dirstamp) + -$(am__rm_f) src/kokkos/$(DEPDIR)/$(am__dirstamp) + -$(am__rm_f) src/kokkos/$(am__dirstamp) -$(am__rm_f) src/mesh/$(DEPDIR)/$(am__dirstamp) -$(am__rm_f) src/mesh/$(am__dirstamp) -$(am__rm_f) src/numerics/$(DEPDIR)/$(am__dirstamp) @@ -36762,6 +36683,11 @@ distclean: distclean-recursive -rm -f src/ghosting/$(DEPDIR)/libmesh_prof_la-overlap_coupling.Plo -rm -f src/ghosting/$(DEPDIR)/libmesh_prof_la-point_neighbor_coupling.Plo -rm -f src/ghosting/$(DEPDIR)/libmesh_prof_la-sibling_coupling.Plo + -rm -f src/kokkos/$(DEPDIR)/libmesh_dbg_la-fe_types.Plo + -rm -f src/kokkos/$(DEPDIR)/libmesh_devel_la-fe_types.Plo + -rm -f src/kokkos/$(DEPDIR)/libmesh_oprof_la-fe_types.Plo + -rm -f src/kokkos/$(DEPDIR)/libmesh_opt_la-fe_types.Plo + -rm -f src/kokkos/$(DEPDIR)/libmesh_prof_la-fe_types.Plo -rm -f src/mesh/$(DEPDIR)/libmesh_dbg_la-abaqus_io.Plo -rm -f src/mesh/$(DEPDIR)/libmesh_dbg_la-boundary_info.Plo -rm -f src/mesh/$(DEPDIR)/libmesh_dbg_la-boundary_mesh.Plo @@ -39253,6 +39179,11 @@ maintainer-clean: maintainer-clean-recursive -rm -f src/ghosting/$(DEPDIR)/libmesh_prof_la-overlap_coupling.Plo -rm -f src/ghosting/$(DEPDIR)/libmesh_prof_la-point_neighbor_coupling.Plo -rm -f src/ghosting/$(DEPDIR)/libmesh_prof_la-sibling_coupling.Plo + -rm -f src/kokkos/$(DEPDIR)/libmesh_dbg_la-fe_types.Plo + -rm -f src/kokkos/$(DEPDIR)/libmesh_devel_la-fe_types.Plo + -rm -f src/kokkos/$(DEPDIR)/libmesh_oprof_la-fe_types.Plo + -rm -f src/kokkos/$(DEPDIR)/libmesh_opt_la-fe_types.Plo + -rm -f src/kokkos/$(DEPDIR)/libmesh_prof_la-fe_types.Plo -rm -f src/mesh/$(DEPDIR)/libmesh_dbg_la-abaqus_io.Plo -rm -f src/mesh/$(DEPDIR)/libmesh_dbg_la-boundary_info.Plo -rm -f src/mesh/$(DEPDIR)/libmesh_dbg_la-boundary_mesh.Plo diff --git a/configure b/configure index d351986b57..9ec8e2f98c 100755 --- a/configure +++ b/configure @@ -672,6 +672,8 @@ libmesh_contrib_LDFLAGS libmesh_contrib_INCLUDES libmesh_optional_LIBS libmesh_optional_INCLUDES +LIBMESH_ENABLE_KOKKOS_FALSE +LIBMESH_ENABLE_KOKKOS_TRUE LIBMESH_ENABLE_METAPHYSICL_FALSE LIBMESH_ENABLE_METAPHYSICL_TRUE METAPHYSICL_INCLUDE @@ -1347,6 +1349,7 @@ enable_metaphysicl with_metaphysicl with_metaphysicl_include enable_metaphysicl_required +with_kokkos ' ac_precious_vars='build_alias host_alias @@ -2273,6 +2276,7 @@ Optional Packages: internal: build from contrib --with-metaphysicl-include= + --with-kokkos=DIR Enable Kokkos support using the installation at DIR Some influential environment variables: PETSC_DIR path to PETSc installation @@ -63889,6 +63893,81 @@ fi +# ------------------------------------------------------------- +# Kokkos -- optional, enables the native Kokkos FE math path +# ------------------------------------------------------------- + +# Check whether --with-kokkos was given. +if test ${with_kokkos+y} +then : + withval=$with_kokkos; KOKKOS_DIR="$withval" +else case e in #( + e) KOKKOS_DIR="no" ;; +esac +fi + + +if test "x$KOKKOS_DIR" != "xno" +then : + + as_ac_File=`printf "%s\n" "ac_cv_file_$KOKKOS_DIR/include/Kokkos_Core.hpp" | sed "$as_sed_sh"` +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $KOKKOS_DIR/include/Kokkos_Core.hpp" >&5 +printf %s "checking for $KOKKOS_DIR/include/Kokkos_Core.hpp... " >&6; } +if eval test \${$as_ac_File+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) test "$cross_compiling" = yes && + as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 +if test -r "$KOKKOS_DIR/include/Kokkos_Core.hpp"; then + eval "$as_ac_File=yes" +else + eval "$as_ac_File=no" +fi ;; +esac +fi +eval ac_res=\$$as_ac_File + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } +if eval test \"x\$"$as_ac_File"\" = x"yes" +then : + + enablekokkos=yes + libmesh_optional_INCLUDES="$libmesh_optional_INCLUDES -I$KOKKOS_DIR/include" + libmesh_optional_LIBS="$libmesh_optional_LIBS -L$KOKKOS_DIR/lib -lkokkoscore" + +printf "%s\n" "#define HAVE_KOKKOS 1" >>confdefs.h + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: <<< Configuring library with Kokkos support >>>" >&5 +printf "%s\n" "<<< Configuring library with Kokkos support >>>" >&6; } + +else case e in #( + e) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Kokkos not found at $KOKKOS_DIR -- disabling Kokkos FE support" >&5 +printf "%s\n" "$as_me: WARNING: Kokkos not found at $KOKKOS_DIR -- disabling Kokkos FE support" >&2;} + enablekokkos=no + ;; +esac +fi + + +else case e in #( + e) enablekokkos=no ;; +esac +fi + + if test x$enablekokkos = xyes; then + LIBMESH_ENABLE_KOKKOS_TRUE= + LIBMESH_ENABLE_KOKKOS_FALSE='#' +else + LIBMESH_ENABLE_KOKKOS_TRUE='#' + LIBMESH_ENABLE_KOKKOS_FALSE= +fi + +# ------------------------------------------------------------- + + + if test "$enableoptional" != no then : @@ -65158,6 +65237,10 @@ if test -z "${LIBMESH_ENABLE_METAPHYSICL_TRUE}" && test -z "${LIBMESH_ENABLE_MET as_fn_error $? "conditional \"LIBMESH_ENABLE_METAPHYSICL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${LIBMESH_ENABLE_KOKKOS_TRUE}" && test -z "${LIBMESH_ENABLE_KOKKOS_FALSE}"; then + as_fn_error $? "conditional \"LIBMESH_ENABLE_KOKKOS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${GIT_CHECKOUT_TRUE}" && test -z "${GIT_CHECKOUT_FALSE}"; then as_fn_error $? "conditional \"GIT_CHECKOUT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/contrib/metaphysicl b/contrib/metaphysicl index 5664a7a8ef..8fb6b91cac 160000 --- a/contrib/metaphysicl +++ b/contrib/metaphysicl @@ -1 +1 @@ -Subproject commit 5664a7a8efab281203a080dc27fee7a0f0fe42df +Subproject commit 8fb6b91cac2c7edf4517ac82f062c4e96fb219dc diff --git a/include/Makefile.am b/include/Makefile.am index a8ace90467..1eb5f27574 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,5 +1,23 @@ SUBDIRS = libmesh +# GPU (Kokkos) FE math headers — installed preserving the gpu/ subdirectory so +# downstream code can use #include "libmesh/gpu/kokkos_fe_types.h" etc. +# nobase_ is used instead of the standard flat install to keep the namespace. +if LIBMESH_ENABLE_KOKKOS +nobase_include_HEADERS = \ + gpu/kokkos_scalar_types.h \ + gpu/kokkos_fe_types.h \ + gpu/kokkos_fe_base.h \ + gpu/kokkos_fe_evaluator.h \ + gpu/kokkos_fe_lagrange_1d.h \ + gpu/kokkos_fe_lagrange_2d.h \ + gpu/kokkos_fe_lagrange_3d.h \ + gpu/kokkos_fe_monomial.h \ + gpu/kokkos_fe_face_map.h \ + gpu/kokkos_fe_map.h \ + gpu/kokkos_quadrature.h +endif + # special handholding for prefix_config.m4 generated files # so that 'make clean ; make' works as does 'make distcheck' # libmesh_config.h is made by ./configure, so it should get diff --git a/include/Makefile.in b/include/Makefile.in index 234ec0c2e3..df5d01e9b3 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -157,7 +157,8 @@ am__aclocal_m4_deps = \ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(include_HEADERS) \ - $(noinst_HEADERS) $(am__DIST_COMMON) + $(am__nobase_include_HEADERS_DIST) $(noinst_HEADERS) \ + $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = libmesh_config.h.tmp CONFIG_CLEAN_FILES = @@ -215,8 +216,14 @@ am__uninstall_files_from_dir = { \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && echo $$files | $(am__xargs_n) 40 $(am__rm_f); }; \ } -am__installdirs = "$(DESTDIR)$(includedir)" -HEADERS = $(include_HEADERS) $(noinst_HEADERS) +am__installdirs = "$(DESTDIR)$(includedir)" "$(DESTDIR)$(includedir)" +am__nobase_include_HEADERS_DIST = gpu/kokkos_scalar_types.h \ + gpu/kokkos_fe_types.h gpu/kokkos_fe_base.h \ + gpu/kokkos_fe_evaluator.h gpu/kokkos_fe_lagrange_1d.h \ + gpu/kokkos_fe_lagrange_2d.h gpu/kokkos_fe_lagrange_3d.h \ + gpu/kokkos_fe_monomial.h gpu/kokkos_fe_face_map.h +HEADERS = $(include_HEADERS) $(nobase_include_HEADERS) \ + $(noinst_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ @@ -598,6 +605,21 @@ vtkmajor = @vtkmajor@ vtkversion = @vtkversion@ SUBDIRS = libmesh +# GPU (Kokkos) FE math headers — installed preserving the gpu/ subdirectory so +# downstream code can use #include "libmesh/gpu/kokkos_fe_types.h" etc. +# nobase_ is used instead of the standard flat install to keep the namespace. +@LIBMESH_ENABLE_KOKKOS_TRUE@nobase_include_HEADERS = \ +@LIBMESH_ENABLE_KOKKOS_TRUE@ gpu/kokkos_scalar_types.h \ +@LIBMESH_ENABLE_KOKKOS_TRUE@ gpu/kokkos_fe_types.h \ +@LIBMESH_ENABLE_KOKKOS_TRUE@ gpu/kokkos_fe_base.h \ +@LIBMESH_ENABLE_KOKKOS_TRUE@ gpu/kokkos_fe_evaluator.h \ +@LIBMESH_ENABLE_KOKKOS_TRUE@ gpu/kokkos_fe_lagrange_1d.h \ +@LIBMESH_ENABLE_KOKKOS_TRUE@ gpu/kokkos_fe_lagrange_2d.h \ +@LIBMESH_ENABLE_KOKKOS_TRUE@ gpu/kokkos_fe_lagrange_3d.h \ +@LIBMESH_ENABLE_KOKKOS_TRUE@ gpu/kokkos_fe_monomial.h \ +@LIBMESH_ENABLE_KOKKOS_TRUE@ gpu/kokkos_fe_face_map.h + + # special handholding for prefix_config.m4 generated files # so that 'make clean ; make' works as does 'make distcheck' # libmesh_config.h is made by ./configure, so it should get @@ -635,6 +657,7 @@ include_HEADERS = \ base/libmesh_abort.h \ base/libmesh_base.h \ base/libmesh_common.h \ + base/libmesh_device.h \ base/libmesh_documentation.h \ base/libmesh_exceptions.h \ base/libmesh_logging.h \ @@ -656,6 +679,7 @@ include_HEADERS = \ enums/enum_elem_quality.h \ enums/enum_elem_type.h \ enums/enum_error_estimator_type.h \ + enums/enum_fe_elem_class.h \ enums/enum_fe_family.h \ enums/enum_inf_map_type.h \ enums/enum_io_package.h \ @@ -1214,6 +1238,30 @@ uninstall-includeHEADERS: @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) +install-nobase_includeHEADERS: $(nobase_include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ + fi; \ + $(am__nobase_list) | while read dir files; do \ + xfiles=; for file in $$files; do \ + if test -f "$$file"; then xfiles="$$xfiles $$file"; \ + else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ + test -z "$$xfiles" || { \ + test "x$$dir" = x. || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(includedir)/$$dir'"; \ + $(MKDIR_P) "$(DESTDIR)$(includedir)/$$dir"; }; \ + echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(includedir)/$$dir'"; \ + $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(includedir)/$$dir" || exit $$?; }; \ + done + +uninstall-nobase_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \ + $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ + dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. @@ -1380,7 +1428,7 @@ check: check-recursive all-am: Makefile $(HEADERS) libmesh_config.h.tmp installdirs: installdirs-recursive installdirs-am: - for dir in "$(DESTDIR)$(includedir)"; do \ + for dir in "$(DESTDIR)$(includedir)" "$(DESTDIR)$(includedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive @@ -1434,7 +1482,7 @@ info: info-recursive info-am: -install-data-am: install-includeHEADERS +install-data-am: install-includeHEADERS install-nobase_includeHEADERS install-dvi: install-dvi-recursive @@ -1478,7 +1526,7 @@ ps: ps-recursive ps-am: -uninstall-am: uninstall-includeHEADERS +uninstall-am: uninstall-includeHEADERS uninstall-nobase_includeHEADERS .MAKE: $(am__recursive_targets) all install-am install-strip @@ -1490,12 +1538,13 @@ uninstall-am: uninstall-includeHEADERS install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am \ install-includeHEADERS install-info install-info-am \ - install-man install-pdf install-pdf-am install-ps \ - install-ps-am install-strip installcheck installcheck-am \ - installcheck-local installdirs installdirs-am maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-generic \ - mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ - uninstall-am uninstall-includeHEADERS + install-man install-nobase_includeHEADERS install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installcheck-local installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-includeHEADERS uninstall-nobase_includeHEADERS .PRECIOUS: Makefile diff --git a/include/base/libmesh_common.h b/include/base/libmesh_common.h index 1c7ace587e..98a201e329 100644 --- a/include/base/libmesh_common.h +++ b/include/base/libmesh_common.h @@ -30,6 +30,10 @@ // The library configuration options #include "libmesh/libmesh_config.h" +// Device compilation support — must be included before assert macros +// so that LIBMESH_DEVICE_ASSERT is available for the Kokkos path. +#include "libmesh/libmesh_device.h" + // Use actual timestamps or constant dummies (to aid ccache) #ifdef LIBMESH_ENABLE_TIMESTAMPS # define LIBMESH_TIME __TIME__ @@ -287,7 +291,13 @@ extern bool warned_about_auto_ptr; #endif // The libmesh_assert() macro acts like C's assert(), but throws a -// libmesh_error() (including stack trace, etc) instead of just exiting +// libmesh_error() (including stack trace, etc) instead of just exiting. +// +// In .K translation units (LIBMESH_KOKKOS_COMPILATION defined), +// LIBMESH_DEVICE_ASSERT is provided by libmesh_device.h using +// printf + Kokkos::abort() — device-safe across CUDA/HIP/SYCL. +// The assert macros delegate to it so that both host and device +// code in the same file get assertion checking. #ifdef NDEBUG #define libmesh_assert_msg(asserted, msg) ((void) 0) @@ -299,6 +309,18 @@ extern bool warned_about_auto_ptr; #define libmesh_assert_less_equal_msg(expr1,expr2, msg) ((void) 0) #define libmesh_assert_greater_equal_msg(expr1,expr2, msg) ((void) 0) +#elif defined(LIBMESH_DEVICE_ASSERT) + +// Kokkos compilation: use the device-safe assert from libmesh_device.h. +#define libmesh_assert_msg(asserted, msg) LIBMESH_DEVICE_ASSERT(asserted) +#define libmesh_exceptionless_assert_msg(asserted, msg) LIBMESH_DEVICE_ASSERT(asserted) +#define libmesh_assert_equal_to_msg(expr1,expr2, msg) LIBMESH_DEVICE_ASSERT((expr1) == (expr2)) +#define libmesh_assert_not_equal_to_msg(expr1,expr2, msg) LIBMESH_DEVICE_ASSERT((expr1) != (expr2)) +#define libmesh_assert_less_msg(expr1,expr2, msg) LIBMESH_DEVICE_ASSERT((expr1) < (expr2)) +#define libmesh_assert_greater_msg(expr1,expr2, msg) LIBMESH_DEVICE_ASSERT((expr1) > (expr2)) +#define libmesh_assert_less_equal_msg(expr1,expr2, msg) LIBMESH_DEVICE_ASSERT((expr1) <= (expr2)) +#define libmesh_assert_greater_equal_msg(expr1,expr2, msg) LIBMESH_DEVICE_ASSERT((expr1) >= (expr2)) + #else #define libmesh_assertion_types(expr1,expr2) \ diff --git a/include/base/libmesh_device.h b/include/base/libmesh_device.h new file mode 100644 index 0000000000..3dbf9fdcd0 --- /dev/null +++ b/include/base/libmesh_device.h @@ -0,0 +1,52 @@ +// The libMesh Finite Element Library. +// Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner + +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +#ifndef LIBMESH_LIBMESH_DEVICE_H +#define LIBMESH_LIBMESH_DEVICE_H + +// Defines LIBMESH_DEVICE_INLINE, mirroring MetaPhysicL's METAPHYSICL_INLINE +// pattern (metaphysicl_device.h / METAPHYSICL_KOKKOS_COMPILATION). +// +// When compiling a .K translation unit (LIBMESH_KOKKOS_COMPILATION is defined +// by kokkos.mk), this expands to KOKKOS_INLINE_FUNCTION so that annotated +// methods are callable from both host and device code. In all other +// translation units it expands to plain `inline`. +#ifdef LIBMESH_KOKKOS_COMPILATION +# include +# include +# define LIBMESH_DEVICE_INLINE KOKKOS_INLINE_FUNCTION + +// Device-safe assert: uses printf (supported on CUDA/HIP) and +// Kokkos::abort() for backend-portable device termination. +// Defined here (not in libmesh_common.h) because Kokkos headers +// are only available in .K translation units. +# ifndef NDEBUG +# define LIBMESH_DEVICE_ASSERT(asserted) \ + do { if (!(asserted)) { \ + printf("libMesh assert failed: %s, file %s, line %d\n", \ + #asserted, __FILE__, __LINE__); \ + ::Kokkos::abort("libmesh_assert failed"); \ + } } while (0) +# else +# define LIBMESH_DEVICE_ASSERT(asserted) ((void) 0) +# endif + +#else +# define LIBMESH_DEVICE_INLINE inline +#endif + +#endif // LIBMESH_LIBMESH_DEVICE_H diff --git a/include/base/libmesh_exceptions.h b/include/base/libmesh_exceptions.h index 6ca79b7b26..0e08b5cb39 100644 --- a/include/base/libmesh_exceptions.h +++ b/include/base/libmesh_exceptions.h @@ -212,7 +212,13 @@ class TerminationException #ifdef LIBMESH_ENABLE_EXCEPTIONS #define libmesh_noexcept noexcept +#if defined(__CUDA_ARCH__) || defined(__HIP_DEVICE_COMPILE__) +// GPU device code does not support C++ exceptions — print and abort. +#define LIBMESH_THROW(e) do { printf("libMesh exception: %s\n", e.what()); abort(); } while (0) +#else #define LIBMESH_THROW(e) do { throw e; } while (0) +#endif + #define libmesh_rethrow throw #define libmesh_try try #define libmesh_catch(e) catch(e) diff --git a/include/enums/enum_fe_elem_class.h b/include/enums/enum_fe_elem_class.h new file mode 100644 index 0000000000..2b1b2e96d1 --- /dev/null +++ b/include/enums/enum_fe_elem_class.h @@ -0,0 +1,50 @@ +// The libMesh Finite Element Library. +// Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner + +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + +#ifndef LIBMESH_ENUM_FE_ELEM_CLASS_H +#define LIBMESH_ENUM_FE_ELEM_CLASS_H + +namespace libMesh { + +/** + * \enum libMesh::FEElemClass groups element types by topological class, + * independent of polynomial order. + * + * e.g. QUAD4, QUAD8, QUAD9 all map to QUAD; TRI3, TRI6, TRI7 all map to TRI. + * Used together with FEFamily and polynomial order to uniquely identify a + * physics finite element space. + * + * The fixed type allows forward declaration as: + * enum class FEElemClass : unsigned int; + */ +enum class FEElemClass : unsigned int +{ + EDGE = 0, + TRI = 1, + QUAD = 2, + TET = 3, + HEX = 4, + PRISM = 5, + PYRAMID = 6, + N_CLASSES +}; + +} // namespace libMesh + +#endif // LIBMESH_ENUM_FE_ELEM_CLASS_H diff --git a/include/gpu/kokkos_fe_base.h b/include/gpu/kokkos_fe_base.h new file mode 100644 index 0000000000..5fa8eb7d6b --- /dev/null +++ b/include/gpu/kokkos_fe_base.h @@ -0,0 +1,43 @@ +// Primary FEEvaluator template for Kokkos device-compatible shape functions. +// +// Uses libMesh's own ElemType and FEFamily enums as non-type template +// parameters — no separate tag structs are needed. +// +// All uses must be explicit specializations defined in the kokkos_fe_lagrange_*.h +// and kokkos_fe_monomial.h headers. Every specialization must provide: +// +// static constexpr unsigned int n_dofs() +// +// LIBMESH_DEVICE_INLINE +// static Real shape(unsigned int i, Real xi, Real eta, Real zeta) +// +// LIBMESH_DEVICE_INLINE +// static Real3 grad_shape(unsigned int i, Real xi, Real eta, Real zeta) +// +// Reference-element coordinate conventions (matching libMesh): +// Edge: xi in [-1, 1] +// Quad: (xi, eta) in [-1,1]^2 +// Hex: (xi, eta, zeta) in [-1,1]^3 +// Tri: (xi, eta) in unit triangle, xi >= 0, eta >= 0, xi+eta <= 1 +// Tet: (xi, eta, zeta) in unit tetrahedron +// +// Unused coordinate arguments (e.g. zeta on a 2D element) are accepted but +// ignored, so call sites can always pass all three without special-casing. +// +#ifndef LIBMESH_KOKKOS_FE_BASE_H +#define LIBMESH_KOKKOS_FE_BASE_H + +#include "gpu/kokkos_scalar_types.h" +#include "libmesh/libmesh_device.h" +#include "libmesh/enum_elem_type.h" +#include "libmesh/enum_fe_family.h" + +namespace libMesh::Kokkos +{ + +template +struct FEEvaluator; // forward declaration only; instantiation requires a specialization + +} // namespace libMesh::Kokkos + +#endif // LIBMESH_KOKKOS_FE_BASE_H diff --git a/include/gpu/kokkos_fe_evaluator.h b/include/gpu/kokkos_fe_evaluator.h new file mode 100644 index 0000000000..d6f1804012 --- /dev/null +++ b/include/gpu/kokkos_fe_evaluator.h @@ -0,0 +1,417 @@ +// Kokkos on-device FE shape function dispatch (fe_evaluator.h). +// +// Provides: +// native_map_shape — isoparametric Lagrange shape (topology-based) +// native_grad_map_shape — isoparametric Lagrange gradient (topology-based) +// native_shape — physics FE shape (FEShapeKey-based) +// native_grad_shape — physics FE gradient (FEShapeKey-based) +// +// All functions are LIBMESH_DEVICE_INLINE and dispatch via switch statements +// that compile to fast GPU branch logic. +// +// These helpers are intended for Kokkos-enabled code paths. Device execution +// happens from .K translation units, but the header is also parsed by host code. + +#ifndef LIBMESH_KOKKOS_FE_EVALUATOR_H +#define LIBMESH_KOKKOS_FE_EVALUATOR_H + +#include "gpu/kokkos_fe_base.h" +#include "gpu/kokkos_fe_types.h" +#include "gpu/kokkos_fe_lagrange_1d.h" +#include "gpu/kokkos_fe_lagrange_2d.h" +#include "gpu/kokkos_fe_lagrange_3d.h" +#include "gpu/kokkos_fe_monomial.h" +#include "libmesh/enum_elem_type.h" +#include "libmesh/enum_fe_family.h" + +namespace libMesh::Kokkos +{ + +// ── On-device helpers: element class -> spatial dimension ───────────────────── + +LIBMESH_DEVICE_INLINE unsigned int +dim_from_class(FEElemClass cls) +{ + switch (cls) + { + case FEElemClass::EDGE: + return 1; + case FEElemClass::TRI: + case FEElemClass::QUAD: + return 2; + case FEElemClass::TET: + case FEElemClass::HEX: + case FEElemClass::PRISM: + case FEElemClass::PYRAMID: + return 3; + default: + detail::abort_unsupported("dim_from_class(): unsupported element class"); + return 0; + } +} + +LIBMESH_DEVICE_INLINE unsigned int +dim_from_topology(libMesh::ElemType topo) +{ + return dim_from_class(class_from_topology(topo)); +} + +// ── On-device helper: exact libMesh Lagrange key -> evaluator topology ───────── + +LIBMESH_DEVICE_INLINE libMesh::ElemType +lagrange_shape_topology_for_key(FEShapeKey key) +{ + switch (key.order) + { + case libMesh::FIRST: + switch (key.elem_type) + { + case libMesh::EDGE2: + case libMesh::EDGE3: + case libMesh::EDGE4: + return libMesh::EDGE2; + + case libMesh::TRI3: + case libMesh::TRI6: + case libMesh::TRI7: + return libMesh::TRI3; + + case libMesh::QUAD4: + case libMesh::QUAD8: + case libMesh::QUAD9: + return libMesh::QUAD4; + + case libMesh::TET4: + case libMesh::TET10: + case libMesh::TET14: + return libMesh::TET4; + + case libMesh::HEX8: + case libMesh::HEX20: + case libMesh::HEX27: + return libMesh::HEX8; + + default: + detail::abort_unsupported("lagrange_shape_topology_for_key(): requested FIRST-order LAGRANGE evaluator is not implemented for this element type"); + return libMesh::INVALID_ELEM; + } + + case libMesh::SECOND: + switch (key.elem_type) + { + case libMesh::EDGE3: + return libMesh::EDGE3; + + case libMesh::TRI6: + case libMesh::TRI7: + return libMesh::TRI6; + + case libMesh::QUAD8: + return libMesh::QUAD8; + + case libMesh::QUAD9: + return libMesh::QUAD9; + + case libMesh::TET10: + case libMesh::TET14: + return libMesh::TET10; + + case libMesh::HEX20: + return libMesh::HEX20; + + case libMesh::HEX27: + return libMesh::HEX27; + + default: + detail::abort_unsupported("lagrange_shape_topology_for_key(): requested SECOND-order LAGRANGE evaluator is not implemented for this element type"); + return libMesh::INVALID_ELEM; + } + + default: + detail::abort_unsupported("lagrange_shape_topology_for_key(): requested LAGRANGE evaluator order is not implemented"); + return libMesh::INVALID_ELEM; + } +} + +LIBMESH_DEVICE_INLINE Real +eval_lagrange_shape(libMesh::ElemType topo, + unsigned int i, + Real xi, + Real eta, + Real zeta) +{ + switch (topo) + { + case libMesh::EDGE2: + return FEEvaluator::shape(i, xi, eta, zeta); + case libMesh::EDGE3: + return FEEvaluator::shape(i, xi, eta, zeta); + case libMesh::TRI3: + return FEEvaluator::shape(i, xi, eta, zeta); + case libMesh::TRI6: + return FEEvaluator::shape(i, xi, eta, zeta); + case libMesh::QUAD4: + return FEEvaluator::shape(i, xi, eta, zeta); + case libMesh::QUAD8: + return FEEvaluator::shape(i, xi, eta, zeta); + case libMesh::QUAD9: + return FEEvaluator::shape(i, xi, eta, zeta); + case libMesh::TET4: + return FEEvaluator::shape(i, xi, eta, zeta); + case libMesh::TET10: + return FEEvaluator::shape(i, xi, eta, zeta); + case libMesh::HEX8: + return FEEvaluator::shape(i, xi, eta, zeta); + case libMesh::HEX20: + return FEEvaluator::shape(i, xi, eta, zeta); + case libMesh::HEX27: + return FEEvaluator::shape(i, xi, eta, zeta); + default: + detail::abort_unsupported("eval_lagrange_shape(): unsupported evaluator topology"); + return Real(0); + } +} + +LIBMESH_DEVICE_INLINE Real3 +eval_lagrange_grad_shape(libMesh::ElemType topo, + unsigned int i, + Real xi, + Real eta, + Real zeta) +{ + switch (topo) + { + case libMesh::EDGE2: + return FEEvaluator::grad_shape(i, xi, eta, zeta); + case libMesh::EDGE3: + return FEEvaluator::grad_shape(i, xi, eta, zeta); + case libMesh::TRI3: + return FEEvaluator::grad_shape(i, xi, eta, zeta); + case libMesh::TRI6: + return FEEvaluator::grad_shape(i, xi, eta, zeta); + case libMesh::QUAD4: + return FEEvaluator::grad_shape(i, xi, eta, zeta); + case libMesh::QUAD8: + return FEEvaluator::grad_shape(i, xi, eta, zeta); + case libMesh::QUAD9: + return FEEvaluator::grad_shape(i, xi, eta, zeta); + case libMesh::TET4: + return FEEvaluator::grad_shape(i, xi, eta, zeta); + case libMesh::TET10: + return FEEvaluator::grad_shape(i, xi, eta, zeta); + case libMesh::HEX8: + return FEEvaluator::grad_shape(i, xi, eta, zeta); + case libMesh::HEX20: + return FEEvaluator::grad_shape(i, xi, eta, zeta); + case libMesh::HEX27: + return FEEvaluator::grad_shape(i, xi, eta, zeta); + default: + detail::abort_unsupported("eval_lagrange_grad_shape(): unsupported evaluator topology"); + return Real3(0, 0, 0); + } +} + +// ── Geometry-only shape dispatch (mapping-type + topology) ──────────────────── +// +// Used by map_face_qp_to_parent() for the isoparametric mapping from face reference +// coordinates to parent reference coordinates. +// +// The mapping_type parameter selects the geometric map family. Currently only +// LAGRANGE_MAP is supported; RATIONAL_BERNSTEIN_MAP requires additional +// rational-weight data that is not yet threaded through the device path. + +// ── Compile-time topology versions (preferred for GPU) ─────────────────── +// Template on FEFamily and ElemType so nvcc only instantiates the specific +// FEEvaluator specialization. No topology switch means no stack pressure. + +/// Compile-time map shape evaluation. +template +LIBMESH_DEVICE_INLINE Real +native_map_shape(unsigned int i, Real xi, Real eta, Real zeta) +{ + return FEEvaluator::shape(i, xi, eta, zeta); +} + +/// Compile-time map gradient evaluation. +template +LIBMESH_DEVICE_INLINE Real3 +native_grad_map_shape(unsigned int i, Real xi, Real eta, Real zeta) +{ + return FEEvaluator::grad_shape(i, xi, eta, zeta); +} + +// ── Runtime topology versions (larger GPU stack usage) ─────────────────── + +/// Evaluate the i-th geometric map shape function at (xi, eta, zeta). +LIBMESH_DEVICE_INLINE Real +native_map_shape(libMesh::ElemMappingType mapping_type, + libMesh::ElemType topo, + unsigned int i, + Real xi, + Real eta, + Real zeta) +{ + switch (mapping_type) + { + case libMesh::LAGRANGE_MAP: + return eval_lagrange_shape(topo, i, xi, eta, zeta); + default: + detail::abort_unsupported("native_map_shape(): only LAGRANGE_MAP is implemented"); + return Real(0); + } +} + +/// Evaluate the reference-space gradient of the i-th geometric map shape function. +LIBMESH_DEVICE_INLINE Real3 +native_grad_map_shape(libMesh::ElemMappingType mapping_type, + libMesh::ElemType topo, + unsigned int i, + Real xi, + Real eta, + Real zeta) +{ + switch (mapping_type) + { + case libMesh::LAGRANGE_MAP: + return eval_lagrange_grad_shape(topo, i, xi, eta, zeta); + default: + detail::abort_unsupported("native_grad_map_shape(): only LAGRANGE_MAP is implemented"); + return Real3(0, 0, 0); + } +} + +// ── Physics shape dispatch (FEShapeKey-based) ───────────────────────────────── + +/// Evaluate the i-th physics shape function at (xi, eta, zeta). +LIBMESH_DEVICE_INLINE Real +native_shape(FEShapeKey key, unsigned int i, Real xi, Real eta, Real zeta) +{ + switch (key.family) + { + case libMesh::LAGRANGE: + return eval_lagrange_shape(lagrange_shape_topology_for_key(key), i, xi, eta, zeta); + + case libMesh::MONOMIAL: + { + switch (dim_from_topology(key.elem_type)) + { + case 1: + switch (key.order) + { + case 0: return MonomialImpl1D<0>::shape(i, xi, eta, zeta); + case 1: return MonomialImpl1D<1>::shape(i, xi, eta, zeta); + case 2: return MonomialImpl1D<2>::shape(i, xi, eta, zeta); + case 3: return MonomialImpl1D<3>::shape(i, xi, eta, zeta); + case 4: return MonomialImpl1D<4>::shape(i, xi, eta, zeta); + case 5: return MonomialImpl1D<5>::shape(i, xi, eta, zeta); + default: + detail::abort_unsupported("native_shape(): unsupported 1D MONOMIAL order"); + return Real(0); + } + case 2: + switch (key.order) + { + case 0: return MonomialImpl2D<0>::shape(i, xi, eta, zeta); + case 1: return MonomialImpl2D<1>::shape(i, xi, eta, zeta); + case 2: return MonomialImpl2D<2>::shape(i, xi, eta, zeta); + case 3: return MonomialImpl2D<3>::shape(i, xi, eta, zeta); + case 4: return MonomialImpl2D<4>::shape(i, xi, eta, zeta); + case 5: return MonomialImpl2D<5>::shape(i, xi, eta, zeta); + default: + detail::abort_unsupported("native_shape(): unsupported 2D MONOMIAL order"); + return Real(0); + } + case 3: + switch (key.order) + { + case 0: return MonomialImpl3D<0>::shape(i, xi, eta, zeta); + case 1: return MonomialImpl3D<1>::shape(i, xi, eta, zeta); + case 2: return MonomialImpl3D<2>::shape(i, xi, eta, zeta); + case 3: return MonomialImpl3D<3>::shape(i, xi, eta, zeta); + case 4: return MonomialImpl3D<4>::shape(i, xi, eta, zeta); + case 5: return MonomialImpl3D<5>::shape(i, xi, eta, zeta); + default: + detail::abort_unsupported("native_shape(): unsupported 3D MONOMIAL order"); + return Real(0); + } + default: + detail::abort_unsupported("native_shape(): unsupported MONOMIAL element topology"); + return Real(0); + } + } + + default: + detail::abort_unsupported("native_shape(): unsupported FE family"); + return Real(0); + } +} + +/// Evaluate the reference-space gradient of the i-th physics shape function. +/// With J from jacobian(), rows are reference derivatives, so +/// grad_ref = J * grad_phys and grad_phys = J.inverse(dim) * grad_ref. +LIBMESH_DEVICE_INLINE Real3 +native_grad_shape(FEShapeKey key, unsigned int i, Real xi, Real eta, Real zeta) +{ + switch (key.family) + { + case libMesh::LAGRANGE: + return eval_lagrange_grad_shape(lagrange_shape_topology_for_key(key), i, xi, eta, zeta); + + case libMesh::MONOMIAL: + { + switch (dim_from_topology(key.elem_type)) + { + case 1: + switch (key.order) + { + case 0: return MonomialImpl1D<0>::grad_shape(i, xi, eta, zeta); + case 1: return MonomialImpl1D<1>::grad_shape(i, xi, eta, zeta); + case 2: return MonomialImpl1D<2>::grad_shape(i, xi, eta, zeta); + case 3: return MonomialImpl1D<3>::grad_shape(i, xi, eta, zeta); + case 4: return MonomialImpl1D<4>::grad_shape(i, xi, eta, zeta); + case 5: return MonomialImpl1D<5>::grad_shape(i, xi, eta, zeta); + default: + detail::abort_unsupported("native_grad_shape(): unsupported 1D MONOMIAL order"); + return Real3(0, 0, 0); + } + case 2: + switch (key.order) + { + case 0: return MonomialImpl2D<0>::grad_shape(i, xi, eta, zeta); + case 1: return MonomialImpl2D<1>::grad_shape(i, xi, eta, zeta); + case 2: return MonomialImpl2D<2>::grad_shape(i, xi, eta, zeta); + case 3: return MonomialImpl2D<3>::grad_shape(i, xi, eta, zeta); + case 4: return MonomialImpl2D<4>::grad_shape(i, xi, eta, zeta); + case 5: return MonomialImpl2D<5>::grad_shape(i, xi, eta, zeta); + default: + detail::abort_unsupported("native_grad_shape(): unsupported 2D MONOMIAL order"); + return Real3(0, 0, 0); + } + case 3: + switch (key.order) + { + case 0: return MonomialImpl3D<0>::grad_shape(i, xi, eta, zeta); + case 1: return MonomialImpl3D<1>::grad_shape(i, xi, eta, zeta); + case 2: return MonomialImpl3D<2>::grad_shape(i, xi, eta, zeta); + case 3: return MonomialImpl3D<3>::grad_shape(i, xi, eta, zeta); + case 4: return MonomialImpl3D<4>::grad_shape(i, xi, eta, zeta); + case 5: return MonomialImpl3D<5>::grad_shape(i, xi, eta, zeta); + default: + detail::abort_unsupported("native_grad_shape(): unsupported 3D MONOMIAL order"); + return Real3(0, 0, 0); + } + default: + detail::abort_unsupported("native_grad_shape(): unsupported MONOMIAL element topology"); + return Real3(0, 0, 0); + } + } + + default: + detail::abort_unsupported("native_grad_shape(): unsupported FE family"); + return Real3(0, 0, 0); + } +} + +} // namespace libMesh::Kokkos + +#endif // LIBMESH_KOKKOS_FE_EVALUATOR_H diff --git a/include/gpu/kokkos_fe_face_map.h b/include/gpu/kokkos_fe_face_map.h new file mode 100644 index 0000000000..5075b2aa0c --- /dev/null +++ b/include/gpu/kokkos_fe_face_map.h @@ -0,0 +1,102 @@ +#ifndef LIBMESH_KOKKOS_FE_FACE_MAP_H +#define LIBMESH_KOKKOS_FE_FACE_MAP_H + +#ifdef LIBMESH_HAVE_KOKKOS + +#include "gpu/kokkos_fe_evaluator.h" +#include "libmesh/elem.h" + +namespace libMesh::Kokkos +{ + +inline unsigned int +recover_parent_side(const libMesh::Elem & parent, + const libMesh::Elem & side_in_parent) +{ + for (unsigned int side = 0; side < parent.n_sides(); ++side) + { + auto candidate = parent.build_side_ptr(side); + + if (candidate->type() != side_in_parent.type() || + candidate->n_nodes() != side_in_parent.n_nodes()) + continue; + + bool same_side = true; + for (unsigned int k = 0; k < candidate->n_nodes(); ++k) + if (candidate->node_ptr(k) != side_in_parent.node_ptr(k)) + { + same_side = false; + break; + } + + if (same_side) + return side; + } + + return libMesh::invalid_uint; +} + +/** + * Map a face quadrature point from the side element's reference coordinate system + * to the parent element's reference coordinate system. + * + * side_in_parent must be obtained via build_side_ptr() (not side_ptr()), so that + * second-order sides carry their midpoint nodes. Parent reference coordinates + * are reconstructed from the interior parent element's master-point data, not + * from side_in_parent.point(k), which lives in physical space. + * + * @param side_in_parent The side element as embedded in the parent (from build_side_ptr()) + * @param mapping_type Geometric mapping type (LAGRANGE_MAP, RATIONAL_BERNSTEIN_MAP) + * @param side_topo Topology of the side element (libMesh::ElemType) + * @param face_qpt Quadrature point in the side element's reference coordinates + * @returns Corresponding point in the parent element's reference coordinates + */ +inline Real3 +map_face_qp_to_parent(const libMesh::Elem & side_in_parent, + libMesh::ElemMappingType mapping_type, + libMesh::ElemType side_topo, + Real3 face_qpt) +{ + const libMesh::Elem * parent = side_in_parent.interior_parent(); + libmesh_error_msg_if(!parent, + "map_face_qp_to_parent(): side element must carry an interior_parent() from build_side_ptr()"); + + const unsigned int side = recover_parent_side(*parent, side_in_parent); + libmesh_error_msg_if(side == libMesh::invalid_uint, + "map_face_qp_to_parent(): could not recover parent side for the provided side element"); + + const unsigned int n = side_in_parent.n_nodes(); + Real3 parent_pt(0.0, 0.0, 0.0); + + // 1-D elements: the "side" is a single vertex node. There is only one + // point-side reference coordinate, (0,0,0), so we map directly to the + // corresponding parent vertex in the parent reference element. + if (n == 1) + { + const libMesh::Point pt = parent->master_point(parent->local_side_node(side, 0)); + parent_pt(0) = pt(0); + parent_pt(1) = pt(1); + parent_pt(2) = pt(2); + return parent_pt; + } + + for (unsigned int k = 0; k < n; ++k) + { + const Real s = face_qpt(0); + const Real t = face_qpt(1); + const Real psi = native_map_shape(mapping_type, side_topo, k, s, t, 0.0); + + const libMesh::Point pt = parent->master_point(parent->local_side_node(side, k)); + parent_pt(0) += psi * pt(0); + parent_pt(1) += psi * pt(1); + parent_pt(2) += psi * pt(2); + } + + return parent_pt; +} + +} // namespace libMesh::Kokkos + +#endif // LIBMESH_HAVE_KOKKOS + +#endif // LIBMESH_KOKKOS_FE_FACE_MAP_H diff --git a/include/gpu/kokkos_fe_lagrange_1d.h b/include/gpu/kokkos_fe_lagrange_1d.h new file mode 100644 index 0000000000..e3bd76508e --- /dev/null +++ b/include/gpu/kokkos_fe_lagrange_1d.h @@ -0,0 +1,92 @@ +// Kokkos FEEvaluator specializations for 1-D Lagrange elements. +// +// Covers EDGE2 (linear) and EDGE3 (quadratic). +// Reference-element coordinate convention (libMesh-compatible): +// EDGE2/EDGE3: xi in [-1, 1] +// +// EDGE3 node ordering (libMesh non-sequential): +// index 0 -> xi = -1 (left node) +// index 1 -> xi = +1 (right node) +// index 2 -> xi = 0 (midpoint) + +#ifndef LIBMESH_KOKKOS_FE_LAGRANGE_1D_H +#define LIBMESH_KOKKOS_FE_LAGRANGE_1D_H + +#include "gpu/kokkos_fe_base.h" + +namespace libMesh::Kokkos +{ + +// ── EDGE2 (linear edge, 2 nodes) ───────────────────────────────────────────── + +template <> +struct FEEvaluator +{ + static constexpr unsigned int n_dofs() { return 2; } + +#ifdef LIBMESH_HAVE_KOKKOS + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real /*eta*/, Real /*zeta*/) + { + switch (i) + { + case 0: return 0.5 * (1.0 - xi); + case 1: return 0.5 * (1.0 + xi); + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real /*xi*/, Real /*eta*/, Real /*zeta*/) + { + switch (i) + { + case 0: return Real3(-0.5, 0.0, 0.0); + case 1: return Real3( 0.5, 0.0, 0.0); + default: return Real3(0.0, 0.0, 0.0); + } + } +#endif +}; + +// ── EDGE3 (quadratic edge, 3 nodes) ────────────────────────────────────────── +// Node ordering matches libMesh: 0->left(-1), 1->right(+1), 2->mid(0) +// L_0(xi) = 0.5*xi*(xi-1) dL_0/dxi = xi - 0.5 +// L_1(xi) = 0.5*xi*(xi+1) dL_1/dxi = xi + 0.5 +// L_2(xi) = 1 - xi² dL_2/dxi = -2*xi + +template <> +struct FEEvaluator +{ + static constexpr unsigned int n_dofs() { return 3; } + +#ifdef LIBMESH_HAVE_KOKKOS + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real /*eta*/, Real /*zeta*/) + { + switch (i) + { + case 0: return 0.5 * xi * (xi - 1.0); + case 1: return 0.5 * xi * (xi + 1.0); + case 2: return 1.0 - xi * xi; + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real xi, Real /*eta*/, Real /*zeta*/) + { + switch (i) + { + case 0: return Real3(xi - 0.5, 0.0, 0.0); + case 1: return Real3(xi + 0.5, 0.0, 0.0); + case 2: return Real3(-2.0 * xi, 0.0, 0.0); + default: return Real3(0.0, 0.0, 0.0); + } + } +#endif +}; + +} // namespace libMesh::Kokkos + +#endif // LIBMESH_KOKKOS_FE_LAGRANGE_1D_H diff --git a/include/gpu/kokkos_fe_lagrange_2d.h b/include/gpu/kokkos_fe_lagrange_2d.h new file mode 100644 index 0000000000..0db73c99f8 --- /dev/null +++ b/include/gpu/kokkos_fe_lagrange_2d.h @@ -0,0 +1,253 @@ +// Kokkos FEEvaluator specializations for 2-D Lagrange elements. +// +// Covers TRI3, TRI6, QUAD4, QUAD8, QUAD9. +// Reference-element coordinate conventions (libMesh-compatible): +// Tri: xi >= 0, eta >= 0, xi+eta <= 1 (unit triangle) +// Quad: (xi, eta) in [-1,1]² + +#ifndef LIBMESH_KOKKOS_FE_LAGRANGE_2D_H +#define LIBMESH_KOKKOS_FE_LAGRANGE_2D_H + +#include "gpu/kokkos_fe_base.h" + +namespace libMesh::Kokkos +{ + +// ── TRI3 (linear triangle, 3 nodes) ────────────────────────────────────────── +// Barycentric: zeta0 = 1-xi-eta, zeta1 = xi, zeta2 = eta + +template <> +struct FEEvaluator +{ + static constexpr unsigned int n_dofs() { return 3; } + +#ifdef LIBMESH_HAVE_KOKKOS + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real eta, Real /*zeta*/) + { + switch (i) + { + case 0: return 1.0 - xi - eta; + case 1: return xi; + case 2: return eta; + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real /*xi*/, Real /*eta*/, Real /*zeta*/) + { + switch (i) + { + case 0: return Real3(-1.0, -1.0, 0.0); + case 1: return Real3( 1.0, 0.0, 0.0); + case 2: return Real3( 0.0, 1.0, 0.0); + default: return Real3(0.0, 0.0, 0.0); + } + } +#endif +}; + +// ── TRI6 (quadratic triangle, 6 nodes) ─────────────────────────────────────── +// Barycentric: z0=1-xi-eta, z1=xi, z2=eta +// phi_0 = z0*(2*z0-1) = (1-xi-eta)*(1-2*xi-2*eta) +// phi_1 = z1*(2*z1-1) = xi*(2*xi-1) +// phi_2 = z2*(2*z2-1) = eta*(2*eta-1) +// phi_3 = 4*z0*z1 = 4*(1-xi-eta)*xi +// phi_4 = 4*z1*z2 = 4*xi*eta +// phi_5 = 4*z2*z0 = 4*eta*(1-xi-eta) + +template <> +struct FEEvaluator +{ + static constexpr unsigned int n_dofs() { return 6; } + +#ifdef LIBMESH_HAVE_KOKKOS + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real eta, Real /*zeta*/) + { + const Real z0 = 1.0 - xi - eta; + switch (i) + { + case 0: return z0 * (2.0 * z0 - 1.0); + case 1: return xi * (2.0 * xi - 1.0); + case 2: return eta * (2.0 * eta - 1.0); + case 3: return 4.0 * z0 * xi; + case 4: return 4.0 * xi * eta; + case 5: return 4.0 * eta * z0; + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real xi, Real eta, Real /*zeta*/) + { + switch (i) + { + case 0: return Real3(4.0*xi + 4.0*eta - 3.0, 4.0*xi + 4.0*eta - 3.0, 0.0); + case 1: return Real3(4.0*xi - 1.0, 0.0, 0.0); + case 2: return Real3(0.0, 4.0*eta - 1.0, 0.0); + case 3: return Real3(4.0*(1.0 - 2.0*xi - eta), -4.0*xi, 0.0); + case 4: return Real3(4.0*eta, 4.0*xi, 0.0); + case 5: return Real3(-4.0*eta, 4.0*(1.0 - xi - 2.0*eta), 0.0); + default: return Real3(0.0, 0.0, 0.0); + } + } +#endif +}; + +// ── QUAD4 (bilinear quadrilateral, 4 nodes) ─────────────────────────────────── +// Tensor product of two EDGE2 bases. libMesh node ordering: +// node 0: (-1,-1) node 1: (+1,-1) +// node 2: (+1,+1) node 3: (-1,+1) + +template <> +struct FEEvaluator +{ + static constexpr unsigned int n_dofs() { return 4; } + +#ifdef LIBMESH_HAVE_KOKKOS + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real eta, Real /*zeta*/) + { + switch (i) + { + case 0: return 0.25 * (1.0 - xi) * (1.0 - eta); + case 1: return 0.25 * (1.0 + xi) * (1.0 - eta); + case 2: return 0.25 * (1.0 + xi) * (1.0 + eta); + case 3: return 0.25 * (1.0 - xi) * (1.0 + eta); + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real xi, Real eta, Real /*zeta*/) + { + switch (i) + { + case 0: return Real3(-0.25*(1.0-eta), -0.25*(1.0-xi), 0.0); + case 1: return Real3( 0.25*(1.0-eta), -0.25*(1.0+xi), 0.0); + case 2: return Real3( 0.25*(1.0+eta), 0.25*(1.0+xi), 0.0); + case 3: return Real3(-0.25*(1.0+eta), 0.25*(1.0-xi), 0.0); + default: return Real3(0.0, 0.0, 0.0); + } + } +#endif +}; + +// ── QUAD8 (serendipity quadrilateral, 8 nodes) ──────────────────────────────── +// Node ordering: +// 0: (-1,-1) 1: (+1,-1) 2: (+1,+1) 3: (-1,+1) +// 4: ( 0,-1) 5: (+1, 0) 6: ( 0,+1) 7: (-1, 0) + +template <> +struct FEEvaluator +{ + static constexpr unsigned int n_dofs() { return 8; } + +#ifdef LIBMESH_HAVE_KOKKOS + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real eta, Real /*zeta*/) + { + switch (i) + { + case 0: return 0.25 * (1.0-xi) * (1.0-eta) * (-1.0-xi-eta); + case 1: return 0.25 * (1.0+xi) * (1.0-eta) * (-1.0+xi-eta); + case 2: return 0.25 * (1.0+xi) * (1.0+eta) * (-1.0+xi+eta); + case 3: return 0.25 * (1.0-xi) * (1.0+eta) * (-1.0-xi+eta); + case 4: return 0.5 * (1.0-xi*xi) * (1.0-eta); + case 5: return 0.5 * (1.0+xi) * (1.0-eta*eta); + case 6: return 0.5 * (1.0-xi*xi) * (1.0+eta); + case 7: return 0.5 * (1.0-xi) * (1.0-eta*eta); + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real xi, Real eta, Real /*zeta*/) + { + switch (i) + { + case 0: return Real3(0.25*(1.0-eta)*(2.0*xi+eta), + 0.25*(1.0-xi)*(xi+2.0*eta), + 0.0); + case 1: return Real3(0.25*(1.0-eta)*(2.0*xi-eta), + 0.25*(1.0+xi)*(2.0*eta-xi), + 0.0); + case 2: return Real3(0.25*(1.0+eta)*(2.0*xi+eta), + 0.25*(1.0+xi)*(xi+2.0*eta), + 0.0); + case 3: return Real3(0.25*(1.0+eta)*(2.0*xi-eta), + 0.25*(1.0-xi)*(2.0*eta-xi), + 0.0); + case 4: return Real3(-xi*(1.0-eta), -0.5*(1.0-xi*xi), 0.0); + case 5: return Real3(0.5*(1.0-eta*eta), -eta*(1.0+xi), 0.0); + case 6: return Real3(-xi*(1.0+eta), 0.5*(1.0-xi*xi), 0.0); + case 7: return Real3(-0.5*(1.0-eta*eta), -eta*(1.0-xi), 0.0); + default: return Real3(0.0, 0.0, 0.0); + } + } +#endif +}; + +// ── QUAD9 (biquadratic quadrilateral, 9 nodes) ──────────────────────────────── +// Tensor product of two EDGE3 bases. libMesh node ordering: +// i0[] = {0,1,1,0, 2,1,2,0, 2} +// i1[] = {0,0,1,1, 0,2,1,2, 2} +// +// 1D basis (libMesh non-sequential ordering): +// L_0(t) = 0.5*t*(t-1) dL_0/dt = t - 0.5 +// L_1(t) = 0.5*t*(t+1) dL_1/dt = t + 0.5 +// L_2(t) = 1 - t² dL_2/dt = -2*t + +template <> +struct FEEvaluator +{ + static constexpr unsigned int n_dofs() { return 9; } + +#ifdef LIBMESH_HAVE_KOKKOS + LIBMESH_DEVICE_INLINE static Real L(unsigned int k, Real t) + { + switch (k) + { + case 0: return 0.5 * t * (t - 1.0); + case 1: return 0.5 * t * (t + 1.0); + case 2: return 1.0 - t * t; + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real dL(unsigned int k, Real t) + { + switch (k) + { + case 0: return t - 0.5; + case 1: return t + 0.5; + case 2: return -2.0 * t; + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real eta, Real /*zeta*/) + { + static const unsigned int i0[] = {0, 1, 1, 0, 2, 1, 2, 0, 2}; + static const unsigned int i1[] = {0, 0, 1, 1, 0, 2, 1, 2, 2}; + return L(i0[i], xi) * L(i1[i], eta); + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real xi, Real eta, Real /*zeta*/) + { + static const unsigned int i0[] = {0, 1, 1, 0, 2, 1, 2, 0, 2}; + static const unsigned int i1[] = {0, 0, 1, 1, 0, 2, 1, 2, 2}; + const Real dxi = dL(i0[i], xi) * L(i1[i], eta); + const Real deta = L(i0[i], xi) * dL(i1[i], eta); + return Real3(dxi, deta, 0.0); + } +#endif +}; + +} // namespace libMesh::Kokkos + +#endif // LIBMESH_KOKKOS_FE_LAGRANGE_2D_H diff --git a/include/gpu/kokkos_fe_lagrange_3d.h b/include/gpu/kokkos_fe_lagrange_3d.h new file mode 100644 index 0000000000..39aa389ee7 --- /dev/null +++ b/include/gpu/kokkos_fe_lagrange_3d.h @@ -0,0 +1,367 @@ +// Kokkos FEEvaluator specializations for 3-D Lagrange elements. +// +// Covers TET4, TET10, HEX8, HEX20, HEX27. +// Reference-element coordinate conventions (libMesh-compatible): +// Tet: xi >= 0, eta >= 0, zeta >= 0, xi+eta+zeta <= 1 (unit tetrahedron) +// Hex: (xi, eta, zeta) in [-1,1]³ + +#ifndef LIBMESH_KOKKOS_FE_LAGRANGE_3D_H +#define LIBMESH_KOKKOS_FE_LAGRANGE_3D_H + +#include "gpu/kokkos_fe_base.h" + +namespace libMesh::Kokkos +{ + +// ── TET4 (linear tetrahedron, 4 nodes) ─────────────────────────────────────── +// Barycentric: z0=1-xi-eta-zeta, z1=xi, z2=eta, z3=zeta + +template <> +struct FEEvaluator +{ + static constexpr unsigned int n_dofs() { return 4; } + +#ifdef LIBMESH_HAVE_KOKKOS + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real eta, Real zeta) + { + switch (i) + { + case 0: return 1.0 - xi - eta - zeta; + case 1: return xi; + case 2: return eta; + case 3: return zeta; + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real /*xi*/, Real /*eta*/, Real /*zeta*/) + { + switch (i) + { + case 0: return Real3(-1.0, -1.0, -1.0); + case 1: return Real3( 1.0, 0.0, 0.0); + case 2: return Real3( 0.0, 1.0, 0.0); + case 3: return Real3( 0.0, 0.0, 1.0); + default: return Real3(0.0, 0.0, 0.0); + } + } +#endif +}; + +// ── TET10 (quadratic tetrahedron, 10 nodes) ─────────────────────────────────── +// Barycentric: z0=1-xi-eta-zeta, z1=xi, z2=eta, z3=zeta +// phi_0 = z0*(2*z0-1) +// phi_1 = z1*(2*z1-1) = xi*(2*xi-1) +// phi_2 = z2*(2*z2-1) = eta*(2*eta-1) +// phi_3 = z3*(2*z3-1) = zeta*(2*zeta-1) +// phi_4 = 4*z0*z1 = 4*(1-xi-eta-zeta)*xi +// phi_5 = 4*z1*z2 = 4*xi*eta +// phi_6 = 4*z2*z0 = 4*eta*(1-xi-eta-zeta) +// phi_7 = 4*z0*z3 = 4*(1-xi-eta-zeta)*zeta +// phi_8 = 4*z1*z3 = 4*xi*zeta +// phi_9 = 4*z2*z3 = 4*eta*zeta + +template <> +struct FEEvaluator +{ + static constexpr unsigned int n_dofs() { return 10; } + +#ifdef LIBMESH_HAVE_KOKKOS + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real eta, Real zeta) + { + const Real z0 = 1.0 - xi - eta - zeta; + switch (i) + { + case 0: return z0 * (2.0*z0 - 1.0); + case 1: return xi * (2.0*xi - 1.0); + case 2: return eta * (2.0*eta - 1.0); + case 3: return zeta* (2.0*zeta - 1.0); + case 4: return 4.0 * z0 * xi; + case 5: return 4.0 * xi * eta; + case 6: return 4.0 * eta * z0; + case 7: return 4.0 * z0 * zeta; + case 8: return 4.0 * xi * zeta; + case 9: return 4.0 * eta * zeta; + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real xi, Real eta, Real zeta) + { + switch (i) + { + case 0: + { + const Real v = 4.0*(xi + eta + zeta) - 3.0; + return Real3(v, v, v); + } + case 1: return Real3(4.0*xi - 1.0, 0.0, 0.0); + case 2: return Real3(0.0, 4.0*eta - 1.0, 0.0); + case 3: return Real3(0.0, 0.0, 4.0*zeta - 1.0); + case 4: return Real3( 4.0*(1.0-2.0*xi-eta-zeta), -4.0*xi, -4.0*xi); + case 5: return Real3( 4.0*eta, 4.0*xi, 0.0); + case 6: return Real3(-4.0*eta, 4.0*(1.0-xi-2.0*eta-zeta), -4.0*eta); + case 7: return Real3(-4.0*zeta, -4.0*zeta, 4.0*(1.0-xi-eta-2.0*zeta)); + case 8: return Real3(4.0*zeta, 0.0, 4.0*xi); + case 9: return Real3(0.0, 4.0*zeta, 4.0*eta); + default: return Real3(0.0, 0.0, 0.0); + } + } +#endif +}; + +// ── HEX8 (trilinear hexahedron, 8 nodes) ───────────────────────────────────── +// Tensor product of three EDGE2 bases. +// Node ordering (same as libMesh): +// 0:(-1,-1,-1) 1:(+1,-1,-1) 2:(+1,+1,-1) 3:(-1,+1,-1) +// 4:(-1,-1,+1) 5:(+1,-1,+1) 6:(+1,+1,+1) 7:(-1,+1,+1) + +template <> +struct FEEvaluator +{ + static constexpr unsigned int n_dofs() { return 8; } + +#ifdef LIBMESH_HAVE_KOKKOS + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real eta, Real zeta) + { + switch (i) + { + case 0: return 0.125*(1.0-xi)*(1.0-eta)*(1.0-zeta); + case 1: return 0.125*(1.0+xi)*(1.0-eta)*(1.0-zeta); + case 2: return 0.125*(1.0+xi)*(1.0+eta)*(1.0-zeta); + case 3: return 0.125*(1.0-xi)*(1.0+eta)*(1.0-zeta); + case 4: return 0.125*(1.0-xi)*(1.0-eta)*(1.0+zeta); + case 5: return 0.125*(1.0+xi)*(1.0-eta)*(1.0+zeta); + case 6: return 0.125*(1.0+xi)*(1.0+eta)*(1.0+zeta); + case 7: return 0.125*(1.0-xi)*(1.0+eta)*(1.0+zeta); + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real xi, Real eta, Real zeta) + { + switch (i) + { + case 0: return Real3(-0.125*(1.0-eta)*(1.0-zeta), + -0.125*(1.0-xi) *(1.0-zeta), + -0.125*(1.0-xi) *(1.0-eta)); + case 1: return Real3( 0.125*(1.0-eta)*(1.0-zeta), + -0.125*(1.0+xi) *(1.0-zeta), + -0.125*(1.0+xi) *(1.0-eta)); + case 2: return Real3( 0.125*(1.0+eta)*(1.0-zeta), + 0.125*(1.0+xi) *(1.0-zeta), + -0.125*(1.0+xi) *(1.0+eta)); + case 3: return Real3(-0.125*(1.0+eta)*(1.0-zeta), + 0.125*(1.0-xi) *(1.0-zeta), + -0.125*(1.0-xi) *(1.0+eta)); + case 4: return Real3(-0.125*(1.0-eta)*(1.0+zeta), + -0.125*(1.0-xi) *(1.0+zeta), + 0.125*(1.0-xi) *(1.0-eta)); + case 5: return Real3( 0.125*(1.0-eta)*(1.0+zeta), + -0.125*(1.0+xi) *(1.0+zeta), + 0.125*(1.0+xi) *(1.0-eta)); + case 6: return Real3( 0.125*(1.0+eta)*(1.0+zeta), + 0.125*(1.0+xi) *(1.0+zeta), + 0.125*(1.0+xi) *(1.0+eta)); + case 7: return Real3(-0.125*(1.0+eta)*(1.0+zeta), + 0.125*(1.0-xi) *(1.0+zeta), + 0.125*(1.0-xi) *(1.0+eta)); + default: return Real3(0.0, 0.0, 0.0); + } + } +#endif +}; + +// ── HEX20 (serendipity hexahedron, 20 nodes) ───────────────────────────────── +// Corner nodes: phi = 0.125*(1+sx*xi)*(1+sy*eta)*(1+sz*zeta)*(sx*xi+sy*eta+sz*zeta-2) +// Node ordering follows libMesh (nodes 0-7 corners, 8-19 midside). + +template <> +struct FEEvaluator +{ + static constexpr unsigned int n_dofs() { return 20; } + +#ifdef LIBMESH_HAVE_KOKKOS + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real eta, Real zeta) + { + switch (i) + { + case 0: return 0.125*(1.0-xi)*(1.0-eta)*(1.0-zeta)*(-xi-eta-zeta-2.0); + case 1: return 0.125*(1.0+xi)*(1.0-eta)*(1.0-zeta)*( xi-eta-zeta-2.0); + case 2: return 0.125*(1.0+xi)*(1.0+eta)*(1.0-zeta)*( xi+eta-zeta-2.0); + case 3: return 0.125*(1.0-xi)*(1.0+eta)*(1.0-zeta)*(-xi+eta-zeta-2.0); + case 4: return 0.125*(1.0-xi)*(1.0-eta)*(1.0+zeta)*(-xi-eta+zeta-2.0); + case 5: return 0.125*(1.0+xi)*(1.0-eta)*(1.0+zeta)*( xi-eta+zeta-2.0); + case 6: return 0.125*(1.0+xi)*(1.0+eta)*(1.0+zeta)*( xi+eta+zeta-2.0); + case 7: return 0.125*(1.0-xi)*(1.0+eta)*(1.0+zeta)*(-xi+eta+zeta-2.0); + case 8: return 0.25*(1.0-xi*xi)*(1.0-eta)*(1.0-zeta); + case 10: return 0.25*(1.0-xi*xi)*(1.0+eta)*(1.0-zeta); + case 16: return 0.25*(1.0-xi*xi)*(1.0-eta)*(1.0+zeta); + case 18: return 0.25*(1.0-xi*xi)*(1.0+eta)*(1.0+zeta); + case 9: return 0.25*(1.0+xi)*(1.0-eta*eta)*(1.0-zeta); + case 11: return 0.25*(1.0-xi)*(1.0-eta*eta)*(1.0-zeta); + case 17: return 0.25*(1.0+xi)*(1.0-eta*eta)*(1.0+zeta); + case 19: return 0.25*(1.0-xi)*(1.0-eta*eta)*(1.0+zeta); + case 12: return 0.25*(1.0-xi)*(1.0-eta)*(1.0-zeta*zeta); + case 13: return 0.25*(1.0+xi)*(1.0-eta)*(1.0-zeta*zeta); + case 14: return 0.25*(1.0+xi)*(1.0+eta)*(1.0-zeta*zeta); + case 15: return 0.25*(1.0-xi)*(1.0+eta)*(1.0-zeta*zeta); + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real xi, Real eta, Real zeta) + { + switch (i) + { + case 0: return Real3( + -0.125*(1.0-eta)*(1.0-zeta)*(-2.0*xi-eta-zeta-1.0), + -0.125*(1.0-xi) *(1.0-zeta)*(-xi-2.0*eta-zeta-1.0), + -0.125*(1.0-xi) *(1.0-eta) *(-xi-eta-2.0*zeta-1.0)); + case 1: return Real3( + 0.125*(1.0-eta)*(1.0-zeta)*(2.0*xi-eta-zeta-1.0), + -0.125*(1.0+xi) *(1.0-zeta)*(xi-2.0*eta-zeta-1.0), + -0.125*(1.0+xi) *(1.0-eta) *(xi-eta-2.0*zeta-1.0)); + case 2: return Real3( + 0.125*(1.0+eta)*(1.0-zeta)*(2.0*xi+eta-zeta-1.0), + 0.125*(1.0+xi) *(1.0-zeta)*(xi+2.0*eta-zeta-1.0), + -0.125*(1.0+xi) *(1.0+eta) *(xi+eta-2.0*zeta-1.0)); + case 3: return Real3( + -0.125*(1.0+eta)*(1.0-zeta)*(-2.0*xi+eta-zeta-1.0), + 0.125*(1.0-xi) *(1.0-zeta)*(-xi+2.0*eta-zeta-1.0), + -0.125*(1.0-xi) *(1.0+eta) *(-xi+eta-2.0*zeta-1.0)); + case 4: return Real3( + -0.125*(1.0-eta)*(1.0+zeta)*(-2.0*xi-eta+zeta-1.0), + -0.125*(1.0-xi) *(1.0+zeta)*(-xi-2.0*eta+zeta-1.0), + 0.125*(1.0-xi) *(1.0-eta) *(-xi-eta+2.0*zeta-1.0)); + case 5: return Real3( + 0.125*(1.0-eta)*(1.0+zeta)*(2.0*xi-eta+zeta-1.0), + -0.125*(1.0+xi) *(1.0+zeta)*(xi-2.0*eta+zeta-1.0), + 0.125*(1.0+xi) *(1.0-eta) *(xi-eta+2.0*zeta-1.0)); + case 6: return Real3( + 0.125*(1.0+eta)*(1.0+zeta)*(2.0*xi+eta+zeta-1.0), + 0.125*(1.0+xi) *(1.0+zeta)*(xi+2.0*eta+zeta-1.0), + 0.125*(1.0+xi) *(1.0+eta) *(xi+eta+2.0*zeta-1.0)); + case 7: return Real3( + -0.125*(1.0+eta)*(1.0+zeta)*(-2.0*xi+eta+zeta-1.0), + 0.125*(1.0-xi) *(1.0+zeta)*(-xi+2.0*eta+zeta-1.0), + 0.125*(1.0-xi) *(1.0+eta) *(-xi+eta+2.0*zeta-1.0)); + case 8: return Real3(-0.5*xi*(1.0-eta)*(1.0-zeta), + -0.25*(1.0-xi*xi)*(1.0-zeta), + -0.25*(1.0-xi*xi)*(1.0-eta)); + case 10: return Real3(-0.5*xi*(1.0+eta)*(1.0-zeta), + 0.25*(1.0-xi*xi)*(1.0-zeta), + -0.25*(1.0-xi*xi)*(1.0+eta)); + case 16: return Real3(-0.5*xi*(1.0-eta)*(1.0+zeta), + -0.25*(1.0-xi*xi)*(1.0+zeta), + 0.25*(1.0-xi*xi)*(1.0-eta)); + case 18: return Real3(-0.5*xi*(1.0+eta)*(1.0+zeta), + 0.25*(1.0-xi*xi)*(1.0+zeta), + 0.25*(1.0-xi*xi)*(1.0+eta)); + case 9: return Real3( 0.25*(1.0-eta*eta)*(1.0-zeta), + -0.5*eta*(1.0+xi)*(1.0-zeta), + -0.25*(1.0+xi)*(1.0-eta*eta)); + case 11: return Real3(-0.25*(1.0-eta*eta)*(1.0-zeta), + -0.5*eta*(1.0-xi)*(1.0-zeta), + -0.25*(1.0-xi)*(1.0-eta*eta)); + case 17: return Real3( 0.25*(1.0-eta*eta)*(1.0+zeta), + -0.5*eta*(1.0+xi)*(1.0+zeta), + 0.25*(1.0+xi)*(1.0-eta*eta)); + case 19: return Real3(-0.25*(1.0-eta*eta)*(1.0+zeta), + -0.5*eta*(1.0-xi)*(1.0+zeta), + 0.25*(1.0-xi)*(1.0-eta*eta)); + case 12: return Real3(-0.25*(1.0-eta)*(1.0-zeta*zeta), + -0.25*(1.0-xi)*(1.0-zeta*zeta), + -0.5*zeta*(1.0-xi)*(1.0-eta)); + case 13: return Real3( 0.25*(1.0-eta)*(1.0-zeta*zeta), + -0.25*(1.0+xi)*(1.0-zeta*zeta), + -0.5*zeta*(1.0+xi)*(1.0-eta)); + case 14: return Real3( 0.25*(1.0+eta)*(1.0-zeta*zeta), + 0.25*(1.0+xi)*(1.0-zeta*zeta), + -0.5*zeta*(1.0+xi)*(1.0+eta)); + case 15: return Real3(-0.25*(1.0+eta)*(1.0-zeta*zeta), + 0.25*(1.0-xi)*(1.0-zeta*zeta), + -0.5*zeta*(1.0-xi)*(1.0+eta)); + default: return Real3(0.0, 0.0, 0.0); + } + } +#endif +}; + +// ── HEX27 (triquadratic hexahedron, 27 nodes) ───────────────────────────────── +// Tensor product of three EDGE3 bases. +// Index tables (libMesh fe_lagrange_shape_3D.C): +// i0[] = {0,1,1,0, 0,1,1,0, 2,1,2,0, 0,1,1,0, 2,1,2,0, 2,2,1,2,0,2,2} +// i1[] = {0,0,1,1, 0,0,1,1, 0,2,1,2, 0,0,1,1, 0,2,1,2, 2,0,2,1,2,2,2} +// i2[] = {0,0,0,0, 1,1,1,1, 0,0,0,0, 2,2,2,2, 1,1,1,1, 0,2,2,2,2,1,2} + +template <> +struct FEEvaluator +{ + static constexpr unsigned int n_dofs() { return 27; } + +#ifdef LIBMESH_HAVE_KOKKOS + LIBMESH_DEVICE_INLINE static Real L(unsigned int k, Real t) + { + switch (k) + { + case 0: return 0.5 * t * (t - 1.0); + case 1: return 0.5 * t * (t + 1.0); + case 2: return 1.0 - t * t; + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real dL(unsigned int k, Real t) + { + switch (k) + { + case 0: return t - 0.5; + case 1: return t + 0.5; + case 2: return -2.0 * t; + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real eta, Real zeta) + { + static const unsigned int i0[] = + {0,1,1,0, 0,1,1,0, 2,1,2,0, 0,1,1,0, 2,1,2,0, 2,2,1,2,0,2,2}; + static const unsigned int i1[] = + {0,0,1,1, 0,0,1,1, 0,2,1,2, 0,0,1,1, 0,2,1,2, 2,0,2,1,2,2,2}; + static const unsigned int i2[] = + {0,0,0,0, 1,1,1,1, 0,0,0,0, 2,2,2,2, 1,1,1,1, 0,2,2,2,2,1,2}; + return L(i0[i], xi) * L(i1[i], eta) * L(i2[i], zeta); + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real xi, Real eta, Real zeta) + { + static const unsigned int i0[] = + {0,1,1,0, 0,1,1,0, 2,1,2,0, 0,1,1,0, 2,1,2,0, 2,2,1,2,0,2,2}; + static const unsigned int i1[] = + {0,0,1,1, 0,0,1,1, 0,2,1,2, 0,0,1,1, 0,2,1,2, 2,0,2,1,2,2,2}; + static const unsigned int i2[] = + {0,0,0,0, 1,1,1,1, 0,0,0,0, 2,2,2,2, 1,1,1,1, 0,2,2,2,2,1,2}; + const Real lxi = L(i0[i], xi); + const Real leta = L(i1[i], eta); + const Real lzeta = L(i2[i], zeta); + return Real3(dL(i0[i], xi) * leta * lzeta, + lxi * dL(i1[i], eta) * lzeta, + lxi * leta * dL(i2[i], zeta)); + } +#endif +}; + +} // namespace libMesh::Kokkos + +#endif // LIBMESH_KOKKOS_FE_LAGRANGE_3D_H diff --git a/include/gpu/kokkos_fe_map.h b/include/gpu/kokkos_fe_map.h new file mode 100644 index 0000000000..500fa1b669 --- /dev/null +++ b/include/gpu/kokkos_fe_map.h @@ -0,0 +1,213 @@ +// Kokkos device-compatible physical map evaluation. +// +// All functions are LIBMESH_DEVICE_INLINE — callable from both host and GPU. +// +// Two API levels: +// 1. Template on ElemType (preferred): eliminates the topology switch at +// compile time, producing small inlined functions with no stack pressure. +// 2. Runtime ElemType dispatch: convenient but requires increased CUDA +// stack size due to the large switch in native_map_shape. +// +// Given node coordinates and a reference-space point, these functions compute: +// - Physical coordinates (xyz) +// - Jacobian matrix (reference -> physical) +// - Determinant and JxW +// - Outward normal (for face integrals) + +#ifndef LIBMESH_KOKKOS_FE_MAP_H +#define LIBMESH_KOKKOS_FE_MAP_H + +#include "gpu/kokkos_fe_evaluator.h" +#include "gpu/kokkos_scalar_types.h" + +namespace libMesh::Kokkos +{ + +// ========================================================================= +// Compile-time dispatch (preferred for GPU — no switch overhead) +// +// Template on FEFamily and ElemType so nvcc only instantiates the specific +// FEEvaluator specialization. No topology switch means no stack pressure. +// ========================================================================= + +/// Compute physical coordinate: xyz = sum_i( phi_i(ref) * node_i ) +template +LIBMESH_DEVICE_INLINE Real3 +physical_point(const Real3 * nodes, + unsigned int n_nodes, + Real xi, Real eta, Real zeta) +{ + Real3 xyz(0, 0, 0); + for (unsigned int i = 0; i < n_nodes; ++i) + xyz += native_map_shape(i, xi, eta, zeta) * nodes[i]; + return xyz; +} + +/// Compute Jacobian matrix with rows d(x)/d(xi_r): +/// J(r, c) = d(x_c)/d(xi_r). +template +LIBMESH_DEVICE_INLINE Real33 +jacobian(const Real3 * nodes, + unsigned int n_nodes, + Real xi, Real eta, Real zeta) +{ + Real33 J(0.0); + for (unsigned int k = 0; k < n_nodes; ++k) + J += libMesh::outer_product(native_grad_map_shape(k, xi, eta, zeta), nodes[k]); + return J; +} + +/// Compute physical point and Jacobian together (single node loop). +template +LIBMESH_DEVICE_INLINE void +physical_point_and_jacobian(const Real3 * nodes, + unsigned int n_nodes, + Real xi, Real eta, Real zeta, + Real3 & xyz, + Real33 & J) +{ + xyz = Real3(0, 0, 0); + J = Real33(0.0); + for (unsigned int k = 0; k < n_nodes; ++k) + { + const Real phi = native_map_shape(k, xi, eta, zeta); + const Real3 grad = native_grad_map_shape(k, xi, eta, zeta); + xyz += phi * nodes[k]; + J += libMesh::outer_product(grad, nodes[k]); + } +} + +/// Face Jacobian from side node positions. +template +LIBMESH_DEVICE_INLINE Real33 +face_jacobian(const Real3 * face_nodes, + unsigned int n_face_nodes, + Real xi, Real eta, Real zeta) +{ + Real33 J(0.0); + for (unsigned int k = 0; k < n_face_nodes; ++k) + J += libMesh::outer_product(native_grad_map_shape(k, xi, eta, zeta), + face_nodes[k]); + return J; +} + +// ========================================================================= +// Runtime topology dispatch (convenient, but larger GPU stack usage) +// ========================================================================= + +/// Compute physical coordinate (runtime topology). +LIBMESH_DEVICE_INLINE Real3 +physical_point(libMesh::ElemMappingType mapping_type, + libMesh::ElemType topo, + const Real3 * nodes, + unsigned int n_nodes, + Real xi, Real eta, Real zeta) +{ + Real3 xyz(0, 0, 0); + for (unsigned int i = 0; i < n_nodes; ++i) + xyz += native_map_shape(mapping_type, topo, i, xi, eta, zeta) * nodes[i]; + return xyz; +} + +/// Compute Jacobian matrix (runtime topology), with rows d(x)/d(xi_r). +LIBMESH_DEVICE_INLINE Real33 +jacobian(libMesh::ElemMappingType mapping_type, + libMesh::ElemType topo, + const Real3 * nodes, + unsigned int n_nodes, + Real xi, Real eta, Real zeta) +{ + Real33 J(0.0); + for (unsigned int k = 0; k < n_nodes; ++k) + J += libMesh::outer_product(native_grad_map_shape(mapping_type, topo, k, xi, eta, zeta), + nodes[k]); + return J; +} + +/// Compute physical point and Jacobian together (runtime topology). +LIBMESH_DEVICE_INLINE void +physical_point_and_jacobian(libMesh::ElemMappingType mapping_type, + libMesh::ElemType topo, + const Real3 * nodes, + unsigned int n_nodes, + Real xi, Real eta, Real zeta, + Real3 & xyz, + Real33 & J) +{ + xyz = Real3(0, 0, 0); + J = Real33(0.0); + for (unsigned int k = 0; k < n_nodes; ++k) + { + const Real phi = native_map_shape(mapping_type, topo, k, xi, eta, zeta); + const Real3 grad = native_grad_map_shape(mapping_type, topo, k, xi, eta, zeta); + xyz += phi * nodes[k]; + J += libMesh::outer_product(grad, nodes[k]); + } +} + +/// Face Jacobian (runtime topology). +LIBMESH_DEVICE_INLINE Real33 +face_jacobian(libMesh::ElemMappingType mapping_type, + libMesh::ElemType face_topo, + const Real3 * face_nodes, + unsigned int n_face_nodes, + Real xi, Real eta, Real zeta) +{ + Real33 J(0.0); + for (unsigned int k = 0; k < n_face_nodes; ++k) + J += libMesh::outer_product(native_grad_map_shape(mapping_type, face_topo, k, xi, eta, zeta), + face_nodes[k]); + return J; +} + +// ========================================================================= +// Geometry helpers (topology-independent) +// ========================================================================= + +/// Signed volume element det(J) * quadrature_weight. +/// For correctly oriented elements this should be positive. +LIBMESH_DEVICE_INLINE Real +volume_jxw(const Real33 & J, unsigned int dim, Real quad_weight) +{ + return J.determinant(dim) * quad_weight; +} + +/// Face JxW: surface measure * quadrature_weight +/// 3D: ||J_row0 x J_row1|| * weight +/// 2D: ||J_row0|| * weight +/// 1D: weight (face is a point) +LIBMESH_DEVICE_INLINE Real +face_jxw(const Real33 & J, unsigned int parent_dim, Real quad_weight) +{ + if (parent_dim == 3) + return J.row(0).cross(J.row(1)).norm() * quad_weight; + else if (parent_dim == 2) + return J.row(0).norm() * quad_weight; + else + return quad_weight; +} + +/// Outward unit normal from the face Jacobian. +LIBMESH_DEVICE_INLINE Real3 +face_normal(const Real33 & J, unsigned int parent_dim) +{ + Real3 n(0, 0, 0); + if (parent_dim == 3) + n = J.row(0).cross(J.row(1)); + else if (parent_dim == 2) + { + const Real3 t = J.row(0); + n = Real3(-t(1), t(0), 0.0); + } + else + return Real3(1.0, 0.0, 0.0); + + const Real len = n.norm(); + if (len > 0.0) + n *= 1.0 / len; + return n; +} + +} // namespace libMesh::Kokkos + +#endif // LIBMESH_KOKKOS_FE_MAP_H diff --git a/include/gpu/kokkos_fe_monomial.h b/include/gpu/kokkos_fe_monomial.h new file mode 100644 index 0000000000..c348cd192b --- /dev/null +++ b/include/gpu/kokkos_fe_monomial.h @@ -0,0 +1,941 @@ +// Kokkos FEEvaluator specializations for MONOMIAL elements. +// +// MONOMIAL uses the complete total-degree polynomial space P_p. Following +// libMesh's FE, the basis is parameterised by spatial dimension, +// not element class — TRI and QUAD share MonomialImpl2D; TET/HEX/PRISM/PYRAMID +// share MonomialImpl3D. This gives 3 x 6 = 18 impl specializations (dims 1/2/3, +// orders 0-5), then per-topology FEEvaluator delegating specializations wire each +// libMesh::ElemType to the matching impl. +// +// Basis ordering: graded-lex (total degree first, then lexicographic by +// decreasing xi exponent). Matches libMesh::FE::shape ordering. + +#ifndef LIBMESH_KOKKOS_FE_MONOMIAL_H +#define LIBMESH_KOKKOS_FE_MONOMIAL_H + +#include "gpu/kokkos_fe_base.h" +#include "libmesh/enum_elem_type.h" + +namespace libMesh::Kokkos +{ + +// ═══════════════════════════════════════════════════════════════════════════ +// MonomialImpl1D — 1-D MONOMIAL basis, order N +// n_dofs = N + 1 +// Basis: {1, xi, xi², xi³, ...} +// ═══════════════════════════════════════════════════════════════════════════ + +template +struct MonomialImpl1D; + +template <> +struct MonomialImpl1D<0> +{ + static constexpr unsigned int n_dofs() { return 1; } + + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int /*i*/, Real /*xi*/, Real /*eta*/, Real /*zeta*/) + { + return 1.0; + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int /*i*/, Real /*xi*/, Real /*eta*/, Real /*zeta*/) + { + return {0.0, 0.0, 0.0}; + } +}; + +template <> +struct MonomialImpl1D<1> +{ + static constexpr unsigned int n_dofs() { return 2; } + + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real /*eta*/, Real /*zeta*/) + { + switch (i) + { + case 0: return 1.0; + case 1: return xi; + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real /*xi*/, Real /*eta*/, Real /*zeta*/) + { + switch (i) + { + case 0: return {0.0, 0.0, 0.0}; + case 1: return {1.0, 0.0, 0.0}; + default: return {0.0, 0.0, 0.0}; + } + } +}; + +template <> +struct MonomialImpl1D<2> +{ + static constexpr unsigned int n_dofs() { return 3; } + + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real /*eta*/, Real /*zeta*/) + { + switch (i) + { + case 0: return 1.0; + case 1: return xi; + case 2: return xi * xi; + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real xi, Real /*eta*/, Real /*zeta*/) + { + switch (i) + { + case 0: return {0.0, 0.0, 0.0}; + case 1: return {1.0, 0.0, 0.0}; + case 2: return {2.0 * xi, 0.0, 0.0}; + default: return {0.0, 0.0, 0.0}; + } + } +}; + +template <> +struct MonomialImpl1D<3> +{ + static constexpr unsigned int n_dofs() { return 4; } + + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real /*eta*/, Real /*zeta*/) + { + switch (i) + { + case 0: return 1.0; + case 1: return xi; + case 2: return xi * xi; + case 3: return xi * xi * xi; + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real xi, Real /*eta*/, Real /*zeta*/) + { + switch (i) + { + case 0: return {0.0, 0.0, 0.0}; + case 1: return {1.0, 0.0, 0.0}; + case 2: return {2.0 * xi, 0.0, 0.0}; + case 3: return {3.0 * xi * xi, 0.0, 0.0}; + default: return {0.0, 0.0, 0.0}; + } + } +}; + +template <> +struct MonomialImpl1D<4> +{ + static constexpr unsigned int n_dofs() { return 5; } + + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real /*eta*/, Real /*zeta*/) + { + switch (i) + { + case 0: return 1.0; + case 1: return xi; + case 2: return xi * xi; + case 3: return xi * xi * xi; + case 4: return xi * xi * xi * xi; + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real xi, Real /*eta*/, Real /*zeta*/) + { + switch (i) + { + case 0: return {0.0, 0.0, 0.0}; + case 1: return {1.0, 0.0, 0.0}; + case 2: return {2.0 * xi, 0.0, 0.0}; + case 3: return {3.0 * xi * xi, 0.0, 0.0}; + case 4: return {4.0 * xi * xi * xi, 0.0, 0.0}; + default: return {0.0, 0.0, 0.0}; + } + } +}; + +template <> +struct MonomialImpl1D<5> +{ + static constexpr unsigned int n_dofs() { return 6; } + + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real /*eta*/, Real /*zeta*/) + { + switch (i) + { + case 0: return 1.0; + case 1: return xi; + case 2: return xi * xi; + case 3: return xi * xi * xi; + case 4: return xi * xi * xi * xi; + case 5: return xi * xi * xi * xi * xi; + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real xi, Real /*eta*/, Real /*zeta*/) + { + switch (i) + { + case 0: return {0.0, 0.0, 0.0}; + case 1: return {1.0, 0.0, 0.0}; + case 2: return {2.0 * xi, 0.0, 0.0}; + case 3: return {3.0 * xi * xi, 0.0, 0.0}; + case 4: return {4.0 * xi * xi * xi, 0.0, 0.0}; + case 5: return {5.0 * xi * xi * xi * xi, 0.0, 0.0}; + default: return {0.0, 0.0, 0.0}; + } + } +}; + +// ═══════════════════════════════════════════════════════════════════════════ +// MonomialImpl2D — 2-D MONOMIAL basis, order N +// n_dofs = (N+1)(N+2)/2 +// Graded-lex basis: {1, xi, eta, xi², xi·eta, eta², ...} +// Shared by TRI and QUAD element classes. +// ═══════════════════════════════════════════════════════════════════════════ + +template +struct MonomialImpl2D; + +template <> +struct MonomialImpl2D<0> +{ + static constexpr unsigned int n_dofs() { return 1; } + + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int /*i*/, Real /*xi*/, Real /*eta*/, Real /*zeta*/) + { + return 1.0; + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int /*i*/, Real /*xi*/, Real /*eta*/, Real /*zeta*/) + { + return {0.0, 0.0, 0.0}; + } +}; + +template <> +struct MonomialImpl2D<1> +{ + static constexpr unsigned int n_dofs() { return 3; } + + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real eta, Real /*zeta*/) + { + switch (i) + { + case 0: return 1.0; + case 1: return xi; + case 2: return eta; + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real /*xi*/, Real /*eta*/, Real /*zeta*/) + { + switch (i) + { + case 0: return {0.0, 0.0, 0.0}; + case 1: return {1.0, 0.0, 0.0}; + case 2: return {0.0, 1.0, 0.0}; + default: return {0.0, 0.0, 0.0}; + } + } +}; + +template <> +struct MonomialImpl2D<2> +{ + static constexpr unsigned int n_dofs() { return 6; } + + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real eta, Real /*zeta*/) + { + switch (i) + { + case 0: return 1.0; + case 1: return xi; + case 2: return eta; + case 3: return xi * xi; + case 4: return xi * eta; + case 5: return eta * eta; + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real xi, Real eta, Real /*zeta*/) + { + switch (i) + { + case 0: return {0.0, 0.0, 0.0}; + case 1: return {1.0, 0.0, 0.0}; + case 2: return {0.0, 1.0, 0.0}; + case 3: return {2.0 * xi, 0.0, 0.0}; + case 4: return {eta, xi, 0.0}; + case 5: return {0.0, 2.0 * eta, 0.0}; + default: return {0.0, 0.0, 0.0}; + } + } +}; + +template <> +struct MonomialImpl2D<3> +{ + static constexpr unsigned int n_dofs() { return 10; } + + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real eta, Real /*zeta*/) + { + switch (i) + { + case 0: return 1.0; + case 1: return xi; + case 2: return eta; + case 3: return xi * xi; + case 4: return xi * eta; + case 5: return eta * eta; + case 6: return xi * xi * xi; + case 7: return xi * xi * eta; + case 8: return xi * eta * eta; + case 9: return eta * eta * eta; + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real xi, Real eta, Real /*zeta*/) + { + switch (i) + { + case 0: return {0.0, 0.0, 0.0}; + case 1: return {1.0, 0.0, 0.0}; + case 2: return {0.0, 1.0, 0.0}; + case 3: return {2.0 * xi, 0.0, 0.0}; + case 4: return {eta, xi, 0.0}; + case 5: return {0.0, 2.0 * eta, 0.0}; + case 6: return {3.0 * xi * xi, 0.0, 0.0}; + case 7: return {2.0 * xi * eta, xi * xi, 0.0}; + case 8: return {eta * eta, 2.0 * xi * eta, 0.0}; + case 9: return {0.0, 3.0 * eta * eta, 0.0}; + default: return {0.0, 0.0, 0.0}; + } + } +}; + +template <> +struct MonomialImpl2D<4> +{ + static constexpr unsigned int n_dofs() { return 15; } + + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real eta, Real /*zeta*/) + { + switch (i) + { + case 0: return 1.0; + case 1: return xi; + case 2: return eta; + case 3: return xi * xi; + case 4: return xi * eta; + case 5: return eta * eta; + case 6: return xi * xi * xi; + case 7: return xi * xi * eta; + case 8: return xi * eta * eta; + case 9: return eta * eta * eta; + case 10: return xi * xi * xi * xi; + case 11: return xi * xi * xi * eta; + case 12: return xi * xi * eta * eta; + case 13: return xi * eta * eta * eta; + case 14: return eta * eta * eta * eta; + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real xi, Real eta, Real /*zeta*/) + { + switch (i) + { + case 0: return {0.0, 0.0, 0.0}; + case 1: return {1.0, 0.0, 0.0}; + case 2: return {0.0, 1.0, 0.0}; + case 3: return {2.0 * xi, 0.0, 0.0}; + case 4: return {eta, xi, 0.0}; + case 5: return {0.0, 2.0 * eta, 0.0}; + case 6: return {3.0 * xi * xi, 0.0, 0.0}; + case 7: return {2.0 * xi * eta, xi * xi, 0.0}; + case 8: return {eta * eta, 2.0 * xi * eta, 0.0}; + case 9: return {0.0, 3.0 * eta * eta, 0.0}; + case 10: return {4.0 * xi * xi * xi, 0.0, 0.0}; + case 11: return {3.0 * xi * xi * eta, xi * xi * xi, 0.0}; + case 12: return {2.0 * xi * eta * eta, 2.0 * xi * xi * eta, 0.0}; + case 13: return {eta * eta * eta, 3.0 * xi * eta * eta, 0.0}; + case 14: return {0.0, 4.0 * eta * eta * eta, 0.0}; + default: return {0.0, 0.0, 0.0}; + } + } +}; + +template <> +struct MonomialImpl2D<5> +{ + static constexpr unsigned int n_dofs() { return 21; } + + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real eta, Real /*zeta*/) + { + switch (i) + { + case 0: return 1.0; + case 1: return xi; + case 2: return eta; + case 3: return xi * xi; + case 4: return xi * eta; + case 5: return eta * eta; + case 6: return xi * xi * xi; + case 7: return xi * xi * eta; + case 8: return xi * eta * eta; + case 9: return eta * eta * eta; + case 10: return xi * xi * xi * xi; + case 11: return xi * xi * xi * eta; + case 12: return xi * xi * eta * eta; + case 13: return xi * eta * eta * eta; + case 14: return eta * eta * eta * eta; + case 15: return xi * xi * xi * xi * xi; + case 16: return xi * xi * xi * xi * eta; + case 17: return xi * xi * xi * eta * eta; + case 18: return xi * xi * eta * eta * eta; + case 19: return xi * eta * eta * eta * eta; + case 20: return eta * eta * eta * eta * eta; + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real xi, Real eta, Real /*zeta*/) + { + switch (i) + { + case 0: return {0.0, 0.0, 0.0}; + case 1: return {1.0, 0.0, 0.0}; + case 2: return {0.0, 1.0, 0.0}; + case 3: return {2.0 * xi, 0.0, 0.0}; + case 4: return {eta, xi, 0.0}; + case 5: return {0.0, 2.0 * eta, 0.0}; + case 6: return {3.0 * xi * xi, 0.0, 0.0}; + case 7: return {2.0 * xi * eta, xi * xi, 0.0}; + case 8: return {eta * eta, 2.0 * xi * eta, 0.0}; + case 9: return {0.0, 3.0 * eta * eta, 0.0}; + case 10: return {4.0 * xi * xi * xi, 0.0, 0.0}; + case 11: return {3.0 * xi * xi * eta, xi * xi * xi, 0.0}; + case 12: return {2.0 * xi * eta * eta, 2.0 * xi * xi * eta, 0.0}; + case 13: return {eta * eta * eta, 3.0 * xi * eta * eta, 0.0}; + case 14: return {0.0, 4.0 * eta * eta * eta, 0.0}; + case 15: return {5.0 * xi * xi * xi * xi, 0.0, 0.0}; + case 16: return {4.0 * xi * xi * xi * eta, xi * xi * xi * xi, 0.0}; + case 17: return {3.0 * xi * xi * eta * eta, 2.0 * xi * xi * xi * eta, 0.0}; + case 18: return {2.0 * xi * eta * eta * eta, 3.0 * xi * xi * eta * eta, 0.0}; + case 19: return {eta * eta * eta * eta, 4.0 * xi * eta * eta * eta, 0.0}; + case 20: return {0.0, 5.0 * eta * eta * eta * eta, 0.0}; + default: return {0.0, 0.0, 0.0}; + } + } +}; + +// ═══════════════════════════════════════════════════════════════════════════ +// MonomialImpl3D — 3-D MONOMIAL basis, order N +// n_dofs = (N+1)(N+2)(N+3)/6 +// Basis ordering: graded-lex; for each total degree d, iterate c (zeta +// exponent) from 0 to d, then a (xi exponent) from d-c down to 0 (b=d-c-a). +// Shared by TET, HEX, PRISM, and PYRAMID element classes. +// ═══════════════════════════════════════════════════════════════════════════ + +template +struct MonomialImpl3D; + +template <> +struct MonomialImpl3D<0> +{ + static constexpr unsigned int n_dofs() { return 1; } + + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int /*i*/, Real /*xi*/, Real /*eta*/, Real /*zeta*/) + { + return 1.0; + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int /*i*/, Real /*xi*/, Real /*eta*/, Real /*zeta*/) + { + return {0.0, 0.0, 0.0}; + } +}; + +template <> +struct MonomialImpl3D<1> +{ + static constexpr unsigned int n_dofs() { return 4; } + + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real eta, Real zeta) + { + switch (i) + { + case 0: return 1.0; + case 1: return xi; + case 2: return eta; + case 3: return zeta; + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real /*xi*/, Real /*eta*/, Real /*zeta*/) + { + switch (i) + { + case 0: return {0.0, 0.0, 0.0}; + case 1: return {1.0, 0.0, 0.0}; + case 2: return {0.0, 1.0, 0.0}; + case 3: return {0.0, 0.0, 1.0}; + default: return {0.0, 0.0, 0.0}; + } + } +}; + +template <> +struct MonomialImpl3D<2> +{ + static constexpr unsigned int n_dofs() { return 10; } + + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real eta, Real zeta) + { + switch (i) + { + case 0: return 1.0; + case 1: return xi; + case 2: return eta; + case 3: return zeta; + case 4: return xi * xi; + case 5: return xi * eta; + case 6: return eta * eta; + case 7: return xi * zeta; + case 8: return eta * zeta; + case 9: return zeta * zeta; + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real xi, Real eta, Real zeta) + { + switch (i) + { + case 0: return {0.0, 0.0, 0.0}; + case 1: return {1.0, 0.0, 0.0}; + case 2: return {0.0, 1.0, 0.0}; + case 3: return {0.0, 0.0, 1.0}; + case 4: return {2.0 * xi, 0.0, 0.0}; + case 5: return {eta, xi, 0.0}; + case 6: return {0.0, 2.0 * eta, 0.0}; + case 7: return {zeta, 0.0, xi}; + case 8: return {0.0, zeta, eta}; + case 9: return {0.0, 0.0, 2.0 * zeta}; + default: return {0.0, 0.0, 0.0}; + } + } +}; + +template <> +struct MonomialImpl3D<3> +{ + static constexpr unsigned int n_dofs() { return 20; } + + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real eta, Real zeta) + { + switch (i) + { + case 0: return 1.0; + case 1: return xi; + case 2: return eta; + case 3: return zeta; + case 4: return xi * xi; + case 5: return xi * eta; + case 6: return eta * eta; + case 7: return xi * zeta; + case 8: return eta * zeta; + case 9: return zeta * zeta; + case 10: return xi * xi * xi; + case 11: return xi * xi * eta; + case 12: return xi * eta * eta; + case 13: return eta * eta * eta; + case 14: return xi * xi * zeta; + case 15: return xi * eta * zeta; + case 16: return eta * eta * zeta; + case 17: return xi * zeta * zeta; + case 18: return eta * zeta * zeta; + case 19: return zeta * zeta * zeta; + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real xi, Real eta, Real zeta) + { + switch (i) + { + case 0: return {0.0, 0.0, 0.0}; + case 1: return {1.0, 0.0, 0.0}; + case 2: return {0.0, 1.0, 0.0}; + case 3: return {0.0, 0.0, 1.0}; + case 4: return {2.0*xi, 0.0, 0.0}; + case 5: return {eta, xi, 0.0}; + case 6: return {0.0, 2.0*eta, 0.0}; + case 7: return {zeta, 0.0, xi}; + case 8: return {0.0, zeta, eta}; + case 9: return {0.0, 0.0, 2.0*zeta}; + case 10: return {3.0*xi*xi, 0.0, 0.0}; + case 11: return {2.0*xi*eta, xi*xi, 0.0}; + case 12: return {eta*eta, 2.0*xi*eta, 0.0}; + case 13: return {0.0, 3.0*eta*eta, 0.0}; + case 14: return {2.0*xi*zeta, 0.0, xi*xi}; + case 15: return {eta*zeta, xi*zeta, xi*eta}; + case 16: return {0.0, 2.0*eta*zeta, eta*eta}; + case 17: return {zeta*zeta, 0.0, 2.0*xi*zeta}; + case 18: return {0.0, zeta*zeta, 2.0*eta*zeta}; + case 19: return {0.0, 0.0, 3.0*zeta*zeta}; + default: return {0.0, 0.0, 0.0}; + } + } +}; + +template <> +struct MonomialImpl3D<4> +{ + static constexpr unsigned int n_dofs() { return 35; } + + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real eta, Real zeta) + { + switch (i) + { + case 0: return 1.0; + case 1: return xi; + case 2: return eta; + case 3: return zeta; + case 4: return xi * xi; + case 5: return xi * eta; + case 6: return eta * eta; + case 7: return xi * zeta; + case 8: return eta * zeta; + case 9: return zeta * zeta; + case 10: return xi * xi * xi; + case 11: return xi * xi * eta; + case 12: return xi * eta * eta; + case 13: return eta * eta * eta; + case 14: return xi * xi * zeta; + case 15: return xi * eta * zeta; + case 16: return eta * eta * zeta; + case 17: return xi * zeta * zeta; + case 18: return eta * zeta * zeta; + case 19: return zeta * zeta * zeta; + case 20: return xi * xi * xi * xi; + case 21: return xi * xi * xi * eta; + case 22: return xi * xi * eta * eta; + case 23: return xi * eta * eta * eta; + case 24: return eta * eta * eta * eta; + case 25: return xi * xi * xi * zeta; + case 26: return xi * xi * eta * zeta; + case 27: return xi * eta * eta * zeta; + case 28: return eta * eta * eta * zeta; + case 29: return xi * xi * zeta * zeta; + case 30: return xi * eta * zeta * zeta; + case 31: return eta * eta * zeta * zeta; + case 32: return xi * zeta * zeta * zeta; + case 33: return eta * zeta * zeta * zeta; + case 34: return zeta * zeta * zeta * zeta; + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real xi, Real eta, Real zeta) + { + switch (i) + { + case 0: return {0.0, 0.0, 0.0}; + case 1: return {1.0, 0.0, 0.0}; + case 2: return {0.0, 1.0, 0.0}; + case 3: return {0.0, 0.0, 1.0}; + case 4: return {2.0*xi, 0.0, 0.0}; + case 5: return {eta, xi, 0.0}; + case 6: return {0.0, 2.0*eta, 0.0}; + case 7: return {zeta, 0.0, xi}; + case 8: return {0.0, zeta, eta}; + case 9: return {0.0, 0.0, 2.0*zeta}; + case 10: return {3.0*xi*xi, 0.0, 0.0}; + case 11: return {2.0*xi*eta, xi*xi, 0.0}; + case 12: return {eta*eta, 2.0*xi*eta, 0.0}; + case 13: return {0.0, 3.0*eta*eta, 0.0}; + case 14: return {2.0*xi*zeta, 0.0, xi*xi}; + case 15: return {eta*zeta, xi*zeta, xi*eta}; + case 16: return {0.0, 2.0*eta*zeta, eta*eta}; + case 17: return {zeta*zeta, 0.0, 2.0*xi*zeta}; + case 18: return {0.0, zeta*zeta, 2.0*eta*zeta}; + case 19: return {0.0, 0.0, 3.0*zeta*zeta}; + case 20: return {4.0*xi*xi*xi, 0.0, 0.0}; + case 21: return {3.0*xi*xi*eta, xi*xi*xi, 0.0}; + case 22: return {2.0*xi*eta*eta, 2.0*xi*xi*eta, 0.0}; + case 23: return {eta*eta*eta, 3.0*xi*eta*eta, 0.0}; + case 24: return {0.0, 4.0*eta*eta*eta, 0.0}; + case 25: return {3.0*xi*xi*zeta, 0.0, xi*xi*xi}; + case 26: return {2.0*xi*eta*zeta, xi*xi*zeta, xi*xi*eta}; + case 27: return {eta*eta*zeta, 2.0*xi*eta*zeta, xi*eta*eta}; + case 28: return {0.0, 3.0*eta*eta*zeta, eta*eta*eta}; + case 29: return {2.0*xi*zeta*zeta, 0.0, 2.0*xi*xi*zeta}; + case 30: return {eta*zeta*zeta, xi*zeta*zeta, 2.0*xi*eta*zeta}; + case 31: return {0.0, 2.0*eta*zeta*zeta, 2.0*eta*eta*zeta}; + case 32: return {zeta*zeta*zeta, 0.0, 3.0*xi*zeta*zeta}; + case 33: return {0.0, zeta*zeta*zeta, 3.0*eta*zeta*zeta}; + case 34: return {0.0, 0.0, 4.0*zeta*zeta*zeta}; + default: return {0.0, 0.0, 0.0}; + } + } +}; + +template <> +struct MonomialImpl3D<5> +{ + static constexpr unsigned int n_dofs() { return 56; } + + LIBMESH_DEVICE_INLINE static Real + shape(unsigned int i, Real xi, Real eta, Real zeta) + { + switch (i) + { + case 0: return 1.0; + case 1: return xi; + case 2: return eta; + case 3: return zeta; + case 4: return xi*xi; + case 5: return xi*eta; + case 6: return eta*eta; + case 7: return xi*zeta; + case 8: return eta*zeta; + case 9: return zeta*zeta; + case 10: return xi*xi*xi; + case 11: return xi*xi*eta; + case 12: return xi*eta*eta; + case 13: return eta*eta*eta; + case 14: return xi*xi*zeta; + case 15: return xi*eta*zeta; + case 16: return eta*eta*zeta; + case 17: return xi*zeta*zeta; + case 18: return eta*zeta*zeta; + case 19: return zeta*zeta*zeta; + case 20: return xi*xi*xi*xi; + case 21: return xi*xi*xi*eta; + case 22: return xi*xi*eta*eta; + case 23: return xi*eta*eta*eta; + case 24: return eta*eta*eta*eta; + case 25: return xi*xi*xi*zeta; + case 26: return xi*xi*eta*zeta; + case 27: return xi*eta*eta*zeta; + case 28: return eta*eta*eta*zeta; + case 29: return xi*xi*zeta*zeta; + case 30: return xi*eta*zeta*zeta; + case 31: return eta*eta*zeta*zeta; + case 32: return xi*zeta*zeta*zeta; + case 33: return eta*zeta*zeta*zeta; + case 34: return zeta*zeta*zeta*zeta; + case 35: return xi*xi*xi*xi*xi; + case 36: return xi*xi*xi*xi*eta; + case 37: return xi*xi*xi*eta*eta; + case 38: return xi*xi*eta*eta*eta; + case 39: return xi*eta*eta*eta*eta; + case 40: return eta*eta*eta*eta*eta; + case 41: return xi*xi*xi*xi*zeta; + case 42: return xi*xi*xi*eta*zeta; + case 43: return xi*xi*eta*eta*zeta; + case 44: return xi*eta*eta*eta*zeta; + case 45: return eta*eta*eta*eta*zeta; + case 46: return xi*xi*xi*zeta*zeta; + case 47: return xi*xi*eta*zeta*zeta; + case 48: return xi*eta*eta*zeta*zeta; + case 49: return eta*eta*eta*zeta*zeta; + case 50: return xi*xi*zeta*zeta*zeta; + case 51: return xi*eta*zeta*zeta*zeta; + case 52: return eta*eta*zeta*zeta*zeta; + case 53: return xi*zeta*zeta*zeta*zeta; + case 54: return eta*zeta*zeta*zeta*zeta; + case 55: return zeta*zeta*zeta*zeta*zeta; + default: return 0.0; + } + } + + LIBMESH_DEVICE_INLINE static Real3 + grad_shape(unsigned int i, Real xi, Real eta, Real zeta) + { + switch (i) + { + case 0: return {0.0, 0.0, 0.0}; + case 1: return {1.0, 0.0, 0.0}; + case 2: return {0.0, 1.0, 0.0}; + case 3: return {0.0, 0.0, 1.0}; + case 4: return {2.0*xi, 0.0, 0.0}; + case 5: return {eta, xi, 0.0}; + case 6: return {0.0, 2.0*eta, 0.0}; + case 7: return {zeta, 0.0, xi}; + case 8: return {0.0, zeta, eta}; + case 9: return {0.0, 0.0, 2.0*zeta}; + case 10: return {3.0*xi*xi, 0.0, 0.0}; + case 11: return {2.0*xi*eta, xi*xi, 0.0}; + case 12: return {eta*eta, 2.0*xi*eta, 0.0}; + case 13: return {0.0, 3.0*eta*eta, 0.0}; + case 14: return {2.0*xi*zeta, 0.0, xi*xi}; + case 15: return {eta*zeta, xi*zeta, xi*eta}; + case 16: return {0.0, 2.0*eta*zeta, eta*eta}; + case 17: return {zeta*zeta, 0.0, 2.0*xi*zeta}; + case 18: return {0.0, zeta*zeta, 2.0*eta*zeta}; + case 19: return {0.0, 0.0, 3.0*zeta*zeta}; + case 20: return {4.0*xi*xi*xi, 0.0, 0.0}; + case 21: return {3.0*xi*xi*eta, xi*xi*xi, 0.0}; + case 22: return {2.0*xi*eta*eta, 2.0*xi*xi*eta, 0.0}; + case 23: return {eta*eta*eta, 3.0*xi*eta*eta, 0.0}; + case 24: return {0.0, 4.0*eta*eta*eta, 0.0}; + case 25: return {3.0*xi*xi*zeta, 0.0, xi*xi*xi}; + case 26: return {2.0*xi*eta*zeta, xi*xi*zeta, xi*xi*eta}; + case 27: return {eta*eta*zeta, 2.0*xi*eta*zeta, xi*eta*eta}; + case 28: return {0.0, 3.0*eta*eta*zeta, eta*eta*eta}; + case 29: return {2.0*xi*zeta*zeta, 0.0, 2.0*xi*xi*zeta}; + case 30: return {eta*zeta*zeta, xi*zeta*zeta, 2.0*xi*eta*zeta}; + case 31: return {0.0, 2.0*eta*zeta*zeta, 2.0*eta*eta*zeta}; + case 32: return {zeta*zeta*zeta, 0.0, 3.0*xi*zeta*zeta}; + case 33: return {0.0, zeta*zeta*zeta, 3.0*eta*zeta*zeta}; + case 34: return {0.0, 0.0, 4.0*zeta*zeta*zeta}; + case 35: return {5.0*xi*xi*xi*xi, 0.0, 0.0}; + case 36: return {4.0*xi*xi*xi*eta, xi*xi*xi*xi, 0.0}; + case 37: return {3.0*xi*xi*eta*eta, 2.0*xi*xi*xi*eta, 0.0}; + case 38: return {2.0*xi*eta*eta*eta, 3.0*xi*xi*eta*eta, 0.0}; + case 39: return {eta*eta*eta*eta, 4.0*xi*eta*eta*eta, 0.0}; + case 40: return {0.0, 5.0*eta*eta*eta*eta, 0.0}; + case 41: return {4.0*xi*xi*xi*zeta, 0.0, xi*xi*xi*xi}; + case 42: return {3.0*xi*xi*eta*zeta, xi*xi*xi*zeta, xi*xi*xi*eta}; + case 43: return {2.0*xi*eta*eta*zeta, 2.0*xi*xi*eta*zeta, xi*xi*eta*eta}; + case 44: return {eta*eta*eta*zeta, 3.0*xi*eta*eta*zeta, xi*eta*eta*eta}; + case 45: return {0.0, 4.0*eta*eta*eta*zeta, eta*eta*eta*eta}; + case 46: return {3.0*xi*xi*zeta*zeta, 0.0, 2.0*xi*xi*xi*zeta}; + case 47: return {2.0*xi*eta*zeta*zeta, xi*xi*zeta*zeta, 2.0*xi*xi*eta*zeta}; + case 48: return {eta*eta*zeta*zeta, 2.0*xi*eta*zeta*zeta, 2.0*xi*eta*eta*zeta}; + case 49: return {0.0, 3.0*eta*eta*zeta*zeta, 2.0*eta*eta*eta*zeta}; + case 50: return {2.0*xi*zeta*zeta*zeta, 0.0, 3.0*xi*xi*zeta*zeta}; + case 51: return {eta*zeta*zeta*zeta, xi*zeta*zeta*zeta, 3.0*xi*eta*zeta*zeta}; + case 52: return {0.0, 2.0*eta*zeta*zeta*zeta, 3.0*eta*eta*zeta*zeta}; + case 53: return {zeta*zeta*zeta*zeta, 0.0, 4.0*xi*zeta*zeta*zeta}; + case 54: return {0.0, zeta*zeta*zeta*zeta, 4.0*eta*zeta*zeta*zeta}; + case 55: return {0.0, 0.0, 5.0*zeta*zeta*zeta*zeta}; + default: return {0.0, 0.0, 0.0}; + } + } +}; + +// ═══════════════════════════════════════════════════════════════════════════ +// Per-topology FEEvaluator delegating specializations +// +// Each partial specialization fixes family=MONOMIAL and elem_type, leaving the +// polynomial Order as a template parameter, then inherits the matching impl. +// ═══════════════════════════════════════════════════════════════════════════ + +// ── 1-D ────────────────────────────────────────────────────────────────────── + +template +struct FEEvaluator : MonomialImpl1D {}; + +template +struct FEEvaluator : MonomialImpl1D {}; + +// ── 2-D ────────────────────────────────────────────────────────────────────── + +template +struct FEEvaluator : MonomialImpl2D {}; + +template +struct FEEvaluator : MonomialImpl2D {}; + +template +struct FEEvaluator : MonomialImpl2D {}; + +template +struct FEEvaluator : MonomialImpl2D {}; + +template +struct FEEvaluator : MonomialImpl2D {}; + +template +struct FEEvaluator : MonomialImpl2D {}; + +// ── 3-D ────────────────────────────────────────────────────────────────────── + +template +struct FEEvaluator : MonomialImpl3D {}; + +template +struct FEEvaluator : MonomialImpl3D {}; + +template +struct FEEvaluator : MonomialImpl3D {}; + +template +struct FEEvaluator : MonomialImpl3D {}; + +template +struct FEEvaluator : MonomialImpl3D {}; + +template +struct FEEvaluator : MonomialImpl3D {}; + +template +struct FEEvaluator : MonomialImpl3D {}; + +template +struct FEEvaluator : MonomialImpl3D {}; + +template +struct FEEvaluator : MonomialImpl3D {}; + +template +struct FEEvaluator : MonomialImpl3D {}; + +template +struct FEEvaluator : MonomialImpl3D {}; + +template +struct FEEvaluator : MonomialImpl3D {}; + +} // namespace libMesh::Kokkos + +#endif // LIBMESH_KOKKOS_FE_MONOMIAL_H diff --git a/include/gpu/kokkos_fe_types.h b/include/gpu/kokkos_fe_types.h new file mode 100644 index 0000000000..ade79c88dd --- /dev/null +++ b/include/gpu/kokkos_fe_types.h @@ -0,0 +1,544 @@ +// Kokkos FE type helpers. +// +// Defines the FEShapeKey aggregate and device-callable dispatch functions used +// by both host-side assembly setup and device-side evaluation. +// +// Uses libMesh's own ElemType, FEFamily, and FEElemClass enums directly — +// no wrapper enums are needed. + +#ifndef LIBMESH_KOKKOS_FE_TYPES_H +#define LIBMESH_KOKKOS_FE_TYPES_H + +#include "libmesh/enum_elem_type.h" +#include "libmesh/enum_fe_family.h" +#include "libmesh/enum_fe_elem_class.h" +#include "libmesh/enum_order.h" +// ElemMappingType (LAGRANGE_MAP, RATIONAL_BERNSTEIN_MAP) is defined in enum_elem_type.h +#include "libmesh/libmesh_device.h" +#ifndef LIBMESH_KOKKOS_COMPILATION +# include "libmesh/libmesh_common.h" +#endif + +namespace libMesh::Kokkos +{ + +// Bring FEElemClass into this namespace so existing unqualified uses compile. +using libMesh::FEElemClass; + +namespace detail +{ + +LIBMESH_DEVICE_INLINE void +abort_unsupported(const char * msg) +{ +#ifdef LIBMESH_KOKKOS_COMPILATION + ::Kokkos::abort(msg); +#else + libmesh_error_msg(msg); +#endif +} + +} // namespace detail + +LIBMESH_DEVICE_INLINE bool +is_monomial_2d_elem_type(libMesh::ElemType elem_type) +{ + switch (elem_type) + { + case libMesh::C0POLYGON: + case libMesh::TRI3: + case libMesh::TRISHELL3: + case libMesh::TRI6: + case libMesh::TRI7: + case libMesh::QUAD4: + case libMesh::QUADSHELL4: + case libMesh::QUAD8: + case libMesh::QUADSHELL8: + case libMesh::QUAD9: + case libMesh::QUADSHELL9: + return true; + default: + return false; + } +} + +LIBMESH_DEVICE_INLINE bool +is_monomial_3d_elem_type(libMesh::ElemType elem_type, + bool include_pyramid18 = true) +{ + switch (elem_type) + { + case libMesh::TET4: + case libMesh::TET10: + case libMesh::TET14: + case libMesh::HEX8: + case libMesh::HEX20: + case libMesh::HEX27: + case libMesh::PRISM6: + case libMesh::PRISM15: + case libMesh::PRISM18: + case libMesh::PRISM20: + case libMesh::PRISM21: + case libMesh::PYRAMID5: + case libMesh::PYRAMID13: + case libMesh::PYRAMID14: + case libMesh::C0POLYHEDRON: + return true; + case libMesh::PYRAMID18: + return include_pyramid18; + default: + return false; + } +} + +// ── Shape function space key ────────────────────────────────────────────────── +// Uniquely identifies a libMesh FE space, including the exact element topology. +// This must be exact for LAGRANGE spaces, since libMesh distinguishes e.g. +// QUAD8 from QUAD9 and HEX20 from HEX27 at the same polynomial order. +// +// Trivially copyable; fits in a register (enum + enum + enum, no heap). + +struct FEShapeKey +{ + libMesh::FEFamily family; + libMesh::ElemType elem_type; + libMesh::Order order; +}; + +// ── Device-callable conversion helpers ─────────────────────────────────────── + +/// Return the Kokkos side topology used for dispatch for any side of parent +/// element type \p parent. +/// This helper is valid only for elements whose side topology is uniform. +/// Mixed-face elements such as prisms and pyramids require side-specific logic. +/// In 1D, libMesh sides are NODEELEM objects; this helper returns EDGE2 as the +/// internal surrogate topology used by the Kokkos map/shape path. +LIBMESH_DEVICE_INLINE libMesh::ElemType +get_side_topology(libMesh::ElemType parent) +{ + switch (parent) + { + // 1D: libMesh sides are NodeElem, but Kokkos dispatches them through + // a degenerate EDGE2 surrogate. + case libMesh::EDGE2: + case libMesh::EDGE3: + case libMesh::EDGE4: + return libMesh::EDGE2; + + // 2D first-order: sides are linear edges + case libMesh::TRI3: + case libMesh::QUAD4: + return libMesh::EDGE2; + + // 2D second-order: sides are quadratic edges + case libMesh::TRI6: + case libMesh::TRI7: + case libMesh::QUAD8: + case libMesh::QUAD9: + return libMesh::EDGE3; + + // 3D first-order: uniform-side-topology elements only + case libMesh::TET4: + return libMesh::TRI3; + case libMesh::HEX8: + return libMesh::QUAD4; + + // 3D second-order: uniform-side-topology elements only + case libMesh::TET10: + return libMesh::TRI6; + case libMesh::TET14: + return libMesh::TRI7; + case libMesh::HEX20: + return libMesh::QUAD8; + case libMesh::HEX27: + return libMesh::QUAD9; + + case libMesh::PRISM15: + case libMesh::PRISM18: + case libMesh::PYRAMID13: + case libMesh::PYRAMID14: + case libMesh::PRISM6: + case libMesh::PRISM20: + case libMesh::PRISM21: + case libMesh::PYRAMID5: + case libMesh::PYRAMID18: + detail::abort_unsupported("get_side_topology(): mixed-face elements require side-specific topology"); + return libMesh::INVALID_ELEM; + + default: + detail::abort_unsupported("get_side_topology(): unsupported element type"); + return libMesh::INVALID_ELEM; // unreachable after abort + } +} + +/// Map an ElemType to its base geometric class (order-independent). +/// e.g. QUAD4 / QUAD8 / QUAD9 all return FEElemClass::QUAD. +LIBMESH_DEVICE_INLINE libMesh::FEElemClass +class_from_topology(libMesh::ElemType topo) +{ + switch (topo) + { + case libMesh::EDGE2: + case libMesh::EDGE3: + case libMesh::EDGE4: + return libMesh::FEElemClass::EDGE; + + case libMesh::TRI3: + case libMesh::TRI6: + case libMesh::TRI7: + return libMesh::FEElemClass::TRI; + + case libMesh::QUAD4: + case libMesh::QUAD8: + case libMesh::QUAD9: + return libMesh::FEElemClass::QUAD; + + case libMesh::TET4: + case libMesh::TET10: + case libMesh::TET14: + return libMesh::FEElemClass::TET; + + case libMesh::HEX8: + case libMesh::HEX20: + case libMesh::HEX27: + return libMesh::FEElemClass::HEX; + + case libMesh::PRISM6: + case libMesh::PRISM15: + case libMesh::PRISM18: + case libMesh::PRISM20: + case libMesh::PRISM21: + return libMesh::FEElemClass::PRISM; + + case libMesh::PYRAMID5: + case libMesh::PYRAMID13: + case libMesh::PYRAMID14: + case libMesh::PYRAMID18: + return libMesh::FEElemClass::PYRAMID; + + default: + detail::abort_unsupported("class_from_topology(): unsupported element type"); + return libMesh::FEElemClass::N_CLASSES; // unreachable after abort + } +} + +LIBMESH_DEVICE_INLINE unsigned int +lagrange_n_dofs_for_elem_type_and_order(libMesh::ElemType elem_type, + libMesh::Order order) +{ + switch (order) + { + case libMesh::CONSTANT: + switch (elem_type) + { + case libMesh::NODEELEM: + return 1; + default: + detail::abort_unsupported("lagrange_n_dofs_for_elem_type_and_order(): unsupported CONSTANT LAGRANGE element type"); + return 0; + } + + case libMesh::FIRST: + switch (elem_type) + { + case libMesh::NODEELEM: + return 1; + + case libMesh::EDGE2: + case libMesh::EDGE3: + case libMesh::EDGE4: + return 2; + + case libMesh::TRI3: + case libMesh::TRI6: + case libMesh::TRI7: + return 3; + + case libMesh::QUAD4: + case libMesh::QUAD8: + case libMesh::QUAD9: + return 4; + + case libMesh::TET4: + case libMesh::TET10: + case libMesh::TET14: + return 4; + + case libMesh::HEX8: + case libMesh::HEX20: + case libMesh::HEX27: + return 8; + + case libMesh::PRISM6: + case libMesh::PRISM15: + case libMesh::PRISM18: + case libMesh::PRISM20: + case libMesh::PRISM21: + return 6; + + case libMesh::PYRAMID5: + case libMesh::PYRAMID13: + case libMesh::PYRAMID14: + case libMesh::PYRAMID18: + return 5; + + default: + detail::abort_unsupported("lagrange_n_dofs_for_elem_type_and_order(): unsupported FIRST LAGRANGE element type"); + return 0; + } + + case libMesh::SECOND: + switch (elem_type) + { + case libMesh::NODEELEM: + return 1; + + case libMesh::EDGE3: + return 3; + + case libMesh::TRI6: + case libMesh::TRI7: + return 6; + + case libMesh::QUAD8: + return 8; + + case libMesh::QUAD9: + return 9; + + case libMesh::TET10: + case libMesh::TET14: + return 10; + + case libMesh::HEX20: + return 20; + + case libMesh::HEX27: + return 27; + + case libMesh::PRISM15: + return 15; + + case libMesh::PRISM18: + case libMesh::PRISM20: + case libMesh::PRISM21: + return 18; + + case libMesh::PYRAMID13: + return 13; + + case libMesh::PYRAMID14: + case libMesh::PYRAMID18: + return 14; + + default: + detail::abort_unsupported("lagrange_n_dofs_for_elem_type_and_order(): unsupported SECOND LAGRANGE element type"); + return 0; + } + + case libMesh::THIRD: + switch (elem_type) + { + case libMesh::NODEELEM: + return 1; + + case libMesh::EDGE4: + return 4; + + case libMesh::TRI7: + return 7; + + case libMesh::TET14: + return 14; + + case libMesh::PRISM20: + return 20; + + case libMesh::PRISM21: + return 21; + + case libMesh::PYRAMID18: + return 18; + + default: + detail::abort_unsupported("lagrange_n_dofs_for_elem_type_and_order(): unsupported THIRD LAGRANGE element type"); + return 0; + } + + default: + detail::abort_unsupported("lagrange_n_dofs_for_elem_type_and_order(): unsupported LAGRANGE order"); + return 0; + } +} + +LIBMESH_DEVICE_INLINE unsigned int +monomial_n_dofs_for_elem_type_and_order(libMesh::ElemType elem_type, + libMesh::Order order) +{ + if (elem_type == libMesh::INVALID_ELEM) + return 0; + + switch (order) + { + case libMesh::CONSTANT: + return 1; + + case libMesh::FIRST: + switch (elem_type) + { + case libMesh::NODEELEM: + return 1; + + case libMesh::EDGE2: + case libMesh::EDGE3: + case libMesh::EDGE4: + return 2; + + default: + break; + } + + if (is_monomial_2d_elem_type(elem_type)) + return 3; + if (is_monomial_3d_elem_type(elem_type)) + return 4; + + detail::abort_unsupported("monomial_n_dofs_for_elem_type_and_order(): unsupported FIRST MONOMIAL element type"); + return 0; + + case libMesh::SECOND: + switch (elem_type) + { + case libMesh::NODEELEM: + return 1; + + case libMesh::EDGE2: + case libMesh::EDGE3: + case libMesh::EDGE4: + return 3; + + default: + break; + } + + if (is_monomial_2d_elem_type(elem_type)) + return 6; + if (is_monomial_3d_elem_type(elem_type)) + return 10; + + detail::abort_unsupported("monomial_n_dofs_for_elem_type_and_order(): unsupported SECOND MONOMIAL element type"); + return 0; + + case libMesh::THIRD: + switch (elem_type) + { + case libMesh::NODEELEM: + return 1; + + case libMesh::EDGE2: + case libMesh::EDGE3: + case libMesh::EDGE4: + return 4; + + default: + break; + } + + if (is_monomial_2d_elem_type(elem_type)) + return 10; + if (is_monomial_3d_elem_type(elem_type)) + return 20; + + detail::abort_unsupported("monomial_n_dofs_for_elem_type_and_order(): unsupported THIRD MONOMIAL element type"); + return 0; + + case libMesh::FOURTH: + switch (elem_type) + { + case libMesh::NODEELEM: + return 1; + + case libMesh::EDGE2: + case libMesh::EDGE3: + return 5; + + default: + break; + } + + if (is_monomial_2d_elem_type(elem_type)) + return 15; + if (is_monomial_3d_elem_type(elem_type, false)) + return 35; + + detail::abort_unsupported("monomial_n_dofs_for_elem_type_and_order(): unsupported FOURTH MONOMIAL element type"); + return 0; + + case libMesh::FIFTH: + switch (elem_type) + { + case libMesh::NODEELEM: + return 1; + + case libMesh::EDGE2: + case libMesh::EDGE3: + return 6; + + default: + break; + } + + if (is_monomial_2d_elem_type(elem_type)) + return 21; + if (is_monomial_3d_elem_type(elem_type, false)) + return 56; + + detail::abort_unsupported("monomial_n_dofs_for_elem_type_and_order(): unsupported FIFTH MONOMIAL element type"); + return 0; + + default: + { + const unsigned int p = static_cast(order); + + switch (elem_type) + { + case libMesh::NODEELEM: + return 1; + + case libMesh::EDGE2: + case libMesh::EDGE3: + return p + 1; + + default: + break; + } + + if (is_monomial_2d_elem_type(elem_type)) + return (p + 1) * (p + 2) / 2; + if (is_monomial_3d_elem_type(elem_type, false)) + return (p + 1) * (p + 2) * (p + 3) / 6; + + detail::abort_unsupported("monomial_n_dofs_for_elem_type_and_order(): unsupported MONOMIAL element type/order pair"); + return 0; + } + } +} + +/// Return the number of DOFs for a physics FE space described by \p key. +/// Supports LAGRANGE and MONOMIAL using the same exact ElemType/order +/// accept/reject rules as CPU libMesh. +LIBMESH_DEVICE_INLINE unsigned int +n_dofs(FEShapeKey key) +{ + if (key.family == libMesh::LAGRANGE) + return lagrange_n_dofs_for_elem_type_and_order(key.elem_type, key.order); + else if (key.family == libMesh::MONOMIAL) + return monomial_n_dofs_for_elem_type_and_order(key.elem_type, key.order); + + detail::abort_unsupported("n_dofs(FEShapeKey): unsupported FE family"); + return 0; // unreachable after abort +} + +} // namespace libMesh::Kokkos + +#endif // LIBMESH_KOKKOS_FE_TYPES_H diff --git a/include/gpu/kokkos_quadrature.h b/include/gpu/kokkos_quadrature.h new file mode 100644 index 0000000000..a966713f2c --- /dev/null +++ b/include/gpu/kokkos_quadrature.h @@ -0,0 +1,199 @@ +// Kokkos device-compatible Gauss quadrature rules. +// +// All evaluation functions are LIBMESH_DEVICE_INLINE — callable from both +// host and GPU device code. +// +// GaussLegendre1D: 1-D Gauss-Legendre on [-1,1], 1-7 point rules. +// GaussQuadrature: Full quadrature dispatcher for all supported topologies. +// - n_points(topo, order): number of quadrature points +// - point(topo, order, qp): reference coordinate of qp-th point +// - weight(topo, order, qp): weight of qp-th point +// +// Values match the libMesh QGauss implementation. + +#ifndef LIBMESH_KOKKOS_QUADRATURE_H +#define LIBMESH_KOKKOS_QUADRATURE_H + +#include "gpu/kokkos_scalar_types.h" +#include "libmesh/enum_elem_type.h" +#include "libmesh/quadrature_gauss_data.h" +#include + +namespace libMesh::Kokkos +{ + +// --------------------------------------------------------------------------- +// 1-D Gauss-Legendre quadrature on [-1, 1] +// --------------------------------------------------------------------------- + +struct GaussLegendre1D +{ + LIBMESH_DEVICE_INLINE static unsigned int n_points(unsigned int alg_order) + { + return libMesh::gauss_rule_data::gauss_legendre_n_points(alg_order); + } + + LIBMESH_DEVICE_INLINE static Real point(unsigned int n, unsigned int i) + { + return libMesh::gauss_rule_data::gauss_legendre_point(n, i); + } + + LIBMESH_DEVICE_INLINE static Real weight(unsigned int n, unsigned int i) + { + return libMesh::gauss_rule_data::gauss_legendre_weight(n, i); + } +}; + +// --------------------------------------------------------------------------- +// GaussQuadrature — device-callable quadrature for all supported topologies +// +// Coordinate conventions (same as libMesh): +// EDGE: xi in [-1,1] +// QUAD: (xi,eta) in [-1,1]^2, tensor product +// HEX: (xi,eta,zeta) in [-1,1]^3, tensor product +// TRI: (x,y) on unit triangle {(0,0),(1,0),(0,1)} +// TET: (x,y,z) on unit tet {(0,0,0),(1,0,0),(0,1,0),(0,0,1)} +// --------------------------------------------------------------------------- + +struct GaussQuadrature +{ + /// Number of quadrature points for a given topology and polynomial order. + LIBMESH_DEVICE_INLINE static unsigned int + n_points(libMesh::ElemType topo, unsigned int order) + { + switch (topo) + { + case libMesh::EDGE2: case libMesh::EDGE3: + return GaussLegendre1D::n_points(order); + + case libMesh::QUAD4: case libMesh::QUAD8: case libMesh::QUAD9: + { + const unsigned int n = GaussLegendre1D::n_points(order); + return n * n; + } + + case libMesh::HEX8: case libMesh::HEX20: case libMesh::HEX27: + { + const unsigned int n = GaussLegendre1D::n_points(order); + return n * n * n; + } + + case libMesh::TRI3: case libMesh::TRI6: + return libMesh::gauss_rule_data::tri_n_points((order <= 6u) ? order : 7u); + + case libMesh::TET4: case libMesh::TET10: + return libMesh::gauss_rule_data::tet_n_points((order <= 5u) ? order : 6u); + + default: return 0; + } + } + + /// Reference coordinate of the qp-th quadrature point. + LIBMESH_DEVICE_INLINE static Real3 + point(libMesh::ElemType topo, unsigned int order, unsigned int qp) + { + switch (topo) + { + case libMesh::EDGE2: case libMesh::EDGE3: + return Real3(GaussLegendre1D::point(GaussLegendre1D::n_points(order), qp), 0.0, 0.0); + + case libMesh::QUAD4: case libMesh::QUAD8: case libMesh::QUAD9: + { + const unsigned int n = GaussLegendre1D::n_points(order); + const unsigned int i = qp % n; + const unsigned int j = qp / n; + return Real3(GaussLegendre1D::point(n, i), + GaussLegendre1D::point(n, j), 0.0); + } + + case libMesh::HEX8: case libMesh::HEX20: case libMesh::HEX27: + { + const unsigned int n = GaussLegendre1D::n_points(order); + const unsigned int i = qp % n; + const unsigned int j = (qp / n) % n; + const unsigned int k = qp / (n * n); + return Real3(GaussLegendre1D::point(n, i), + GaussLegendre1D::point(n, j), + GaussLegendre1D::point(n, k)); + } + + case libMesh::TRI3: case libMesh::TRI6: + { + const auto pt = libMesh::gauss_rule_data::tri_point((order <= 6u) ? order : 7u, qp); + return Real3(pt.x, pt.y, 0.0); + } + + case libMesh::TET4: case libMesh::TET10: + { + const auto pt = libMesh::gauss_rule_data::tet_point((order <= 5u) ? order : 6u, qp); + return Real3(pt.x, pt.y, pt.z); + } + + default: return Real3(0, 0, 0); + } + } + + /// Weight of the qp-th quadrature point. + LIBMESH_DEVICE_INLINE static Real + weight(libMesh::ElemType topo, unsigned int order, unsigned int qp) + { + switch (topo) + { + case libMesh::EDGE2: case libMesh::EDGE3: + { + const unsigned int n = GaussLegendre1D::n_points(order); + return GaussLegendre1D::weight(n, qp); + } + + case libMesh::QUAD4: case libMesh::QUAD8: case libMesh::QUAD9: + { + const unsigned int n = GaussLegendre1D::n_points(order); + return GaussLegendre1D::weight(n, qp % n) * + GaussLegendre1D::weight(n, qp / n); + } + + case libMesh::HEX8: case libMesh::HEX20: case libMesh::HEX27: + { + const unsigned int n = GaussLegendre1D::n_points(order); + return GaussLegendre1D::weight(n, qp % n) * + GaussLegendre1D::weight(n, (qp / n) % n) * + GaussLegendre1D::weight(n, qp / (n * n)); + } + + case libMesh::TRI3: case libMesh::TRI6: + return libMesh::gauss_rule_data::tri_weight((order <= 6u) ? order : 7u, qp); + + case libMesh::TET4: case libMesh::TET10: + return libMesh::gauss_rule_data::tet_weight((order <= 5u) ? order : 6u, qp); + + default: return 0.0; + } + } + +}; + +// --------------------------------------------------------------------------- +// fill_quadrature — host-side convenience wrapper +// +// Fills std::vectors using the device-callable GaussQuadrature functions. +// --------------------------------------------------------------------------- + +inline void +fill_quadrature(libMesh::ElemType topo, + unsigned int order, + std::vector & qpts, + std::vector & weights) +{ + const unsigned int nqp = GaussQuadrature::n_points(topo, order); + qpts.resize(nqp); + weights.resize(nqp); + for (unsigned int q = 0; q < nqp; ++q) + { + qpts[q] = GaussQuadrature::point(topo, order, q); + weights[q] = GaussQuadrature::weight(topo, order, q); + } +} + +} // namespace libMesh::Kokkos + +#endif // LIBMESH_KOKKOS_QUADRATURE_H diff --git a/include/gpu/kokkos_scalar_types.h b/include/gpu/kokkos_scalar_types.h new file mode 100644 index 0000000000..36740067f3 --- /dev/null +++ b/include/gpu/kokkos_scalar_types.h @@ -0,0 +1,102 @@ +// libMesh Kokkos device-compatible scalar types. +// +// Real3 is just libMesh::RealVectorValue. Real33 remains a small wrapper around +// TensorValue because the Kokkos map code still uses determinant(dim) and +// inverse(dim) helpers that are not part of the base tensor API. +// +// Access vector components via operator()(i); access tensor entries via +// operator()(i, j). The old .v[i] and .a[i][j] direct-field accesses are +// removed (they no longer exist). +// +// LIBMESH_DIM must be >= 3 for 3-component GPU vectors. + +#ifndef LIBMESH_KOKKOS_SCALAR_TYPES_H +#define LIBMESH_KOKKOS_SCALAR_TYPES_H + +#include "libmesh/libmesh_common.h" +#include "libmesh/libmesh_device.h" +#include "libmesh/vector_value.h" +#include "libmesh/tensor_value.h" + +static_assert(LIBMESH_DIM >= 3, + "Kokkos GPU builds require LIBMESH_DIM >= 3"); + +namespace libMesh::Kokkos +{ + +using Real = libMesh::Real; +using Real3 = libMesh::RealVectorValue; + +// --------------------------------------------------------------------------- +// Real33 — GPU-safe 3x3 real tensor +// --------------------------------------------------------------------------- +struct Real33 : public libMesh::TensorValue +{ + using Base = libMesh::TensorValue; + + LIBMESH_DEVICE_INLINE Real33() : Base() {} + + LIBMESH_DEVICE_INLINE Real33(const Real33 &) = default; + LIBMESH_DEVICE_INLINE Real33 & operator=(const Real33 &) = default; + + // Fill all entries with the same scalar. + LIBMESH_DEVICE_INLINE explicit Real33(const Real & scalar) : Base() + { + for (unsigned int i = 0; i < 3; ++i) + for (unsigned int j = 0; j < 3; ++j) + (*this)(i, j) = scalar; + } + + // Construct from base TypeTensor. + LIBMESH_DEVICE_INLINE Real33(const libMesh::TypeTensor & t) : Base(t) {} + + // ----------- Legacy API kept for backward compatibility ------------------ + + // Set to dim×dim identity (remaining entries zero). + LIBMESH_DEVICE_INLINE void identity(const unsigned int dim = 3) + { + this->zero(); + for (unsigned int i = 0; i < dim; ++i) + (*this)(i, i) = Real(1); + } + + // Determinant of the leading dim×dim sub-block. + LIBMESH_DEVICE_INLINE Real determinant(const unsigned int dim = 3) const + { + if (dim == 0) return Real(1); + if (dim == 1) return (*this)(0, 0); + if (dim == 2) + return (*this)(0,0) * (*this)(1,1) - (*this)(0,1) * (*this)(1,0); + // dim == 3: delegate to TypeTensor::det() + return this->det(); + } + + // Inverse of the leading dim×dim sub-block. + LIBMESH_DEVICE_INLINE Real33 inverse(const unsigned int dim = 3) const + { + Real inv_det = Real(1) / determinant(dim); + Real33 inv_mat; + if (dim == 1) + { + inv_mat(0, 0) = inv_det; + } + else if (dim == 2) + { + inv_mat(0, 0) = (*this)(1, 1) * inv_det; + inv_mat(0, 1) = -(*this)(0, 1) * inv_det; + inv_mat(1, 0) = -(*this)(1, 0) * inv_det; + inv_mat(1, 1) = (*this)(0, 0) * inv_det; + } + else // dim == 3 + { + return Real33(Base::inverse()); + } + return inv_mat; + } + + // row(i) is inherited from TypeTensor::row(i) and returns TypeVector. +}; + +} // namespace libMesh::Kokkos + +#endif // LIBMESH_KOKKOS_SCALAR_TYPES_H diff --git a/include/include_HEADERS b/include/include_HEADERS index 6c6ed12aa6..08be88ca00 100644 --- a/include/include_HEADERS +++ b/include/include_HEADERS @@ -28,6 +28,7 @@ include_HEADERS = \ base/libmesh_abort.h \ base/libmesh_base.h \ base/libmesh_common.h \ + base/libmesh_device.h \ base/libmesh_documentation.h \ base/libmesh_exceptions.h \ base/libmesh_logging.h \ @@ -49,6 +50,7 @@ include_HEADERS = \ enums/enum_elem_quality.h \ enums/enum_elem_type.h \ enums/enum_error_estimator_type.h \ + enums/enum_fe_elem_class.h \ enums/enum_fe_family.h \ enums/enum_inf_map_type.h \ enums/enum_io_package.h \ @@ -341,6 +343,7 @@ include_HEADERS = \ quadrature/quadrature_clough.h \ quadrature/quadrature_composite.h \ quadrature/quadrature_conical.h \ + quadrature/quadrature_gauss_data.h \ quadrature/quadrature_gauss.h \ quadrature/quadrature_gauss_lobatto.h \ quadrature/quadrature_gm.h \ diff --git a/include/libmesh/Makefile.am b/include/libmesh/Makefile.am index 8c49e7ba36..569d8a16ff 100644 --- a/include/libmesh/Makefile.am +++ b/include/libmesh/Makefile.am @@ -19,6 +19,7 @@ BUILT_SOURCES = \ libmesh_augment_std_namespace.h \ libmesh_base.h \ libmesh_common.h \ + libmesh_device.h \ libmesh_documentation.h \ libmesh_exceptions.h \ libmesh_logging.h \ @@ -40,6 +41,7 @@ BUILT_SOURCES = \ enum_elem_quality.h \ enum_elem_type.h \ enum_error_estimator_type.h \ + enum_fe_elem_class.h \ enum_fe_family.h \ enum_inf_map_type.h \ enum_io_package.h \ @@ -656,6 +658,9 @@ libmesh_base.h: $(top_srcdir)/include/base/libmesh_base.h libmesh_common.h: $(top_srcdir)/include/base/libmesh_common.h $(AM_V_GEN)rm -f $@ && $(LN_S) -f $< $@ +libmesh_device.h: $(top_srcdir)/include/base/libmesh_device.h + $(AM_V_GEN)rm -f $@ && $(LN_S) -f $< $@ + libmesh_documentation.h: $(top_srcdir)/include/base/libmesh_documentation.h $(AM_V_GEN)rm -f $@ && $(LN_S) -f $< $@ @@ -719,6 +724,9 @@ enum_elem_type.h: $(top_srcdir)/include/enums/enum_elem_type.h enum_error_estimator_type.h: $(top_srcdir)/include/enums/enum_error_estimator_type.h $(AM_V_GEN)rm -f $@ && $(LN_S) -f $< $@ +enum_fe_elem_class.h: $(top_srcdir)/include/enums/enum_fe_elem_class.h + $(AM_V_GEN)rm -f $@ && $(LN_S) -f $< $@ + enum_fe_family.h: $(top_srcdir)/include/enums/enum_fe_family.h $(AM_V_GEN)rm -f $@ && $(LN_S) -f $< $@ diff --git a/include/libmesh/Makefile.in b/include/libmesh/Makefile.in index d02b0ba154..60dc1dd409 100644 --- a/include/libmesh/Makefile.in +++ b/include/libmesh/Makefile.in @@ -530,21 +530,22 @@ EXTRA_DIST = rebuild_makefile.sh BUILT_SOURCES = dirichlet_boundaries.h dof_map.h dof_map_base.h \ dof_object.h factory.h float128_shims.h getpot.h id_types.h \ libmesh.h libmesh_abort.h libmesh_augment_std_namespace.h \ - libmesh_base.h libmesh_common.h libmesh_documentation.h \ - libmesh_exceptions.h libmesh_logging.h libmesh_singleton.h \ - libmesh_version.h multi_predicates.h periodic_boundaries.h \ - periodic_boundary.h periodic_boundary_base.h print_trace.h \ + libmesh_base.h libmesh_common.h libmesh_device.h \ + libmesh_documentation.h libmesh_exceptions.h libmesh_logging.h \ + libmesh_singleton.h libmesh_version.h multi_predicates.h \ + periodic_boundaries.h periodic_boundary.h \ + periodic_boundary_base.h print_trace.h \ reference_counted_object.h reference_counter.h \ single_predicates.h sparsity_pattern.h variable.h \ variant_filter_iterator.h enum_convergence_flags.h \ enum_eigen_solver_type.h enum_elem_quality.h enum_elem_type.h \ - enum_error_estimator_type.h enum_fe_family.h \ - enum_inf_map_type.h enum_io_package.h enum_matrix_build_type.h \ - enum_norm_type.h enum_order.h enum_parallel_type.h \ - enum_partitioner_type.h enum_point_locator_type.h \ - enum_preconditioner_type.h enum_quadrature_type.h \ - enum_solver_package.h enum_solver_type.h \ - enum_subset_solve_mode.h enum_xdr_mode.h \ + enum_error_estimator_type.h enum_fe_elem_class.h \ + enum_fe_family.h enum_inf_map_type.h enum_io_package.h \ + enum_matrix_build_type.h enum_norm_type.h enum_order.h \ + enum_parallel_type.h enum_partitioner_type.h \ + enum_point_locator_type.h enum_preconditioner_type.h \ + enum_quadrature_type.h enum_solver_package.h \ + enum_solver_type.h enum_subset_solve_mode.h enum_xdr_mode.h \ adjoint_refinement_estimator.h \ adjoint_residual_error_estimator.h discontinuity_measure.h \ error_estimator.h exact_error_estimator.h exact_solution.h \ @@ -992,6 +993,9 @@ libmesh_base.h: $(top_srcdir)/include/base/libmesh_base.h libmesh_common.h: $(top_srcdir)/include/base/libmesh_common.h $(AM_V_GEN)rm -f $@ && $(LN_S) -f $< $@ +libmesh_device.h: $(top_srcdir)/include/base/libmesh_device.h + $(AM_V_GEN)rm -f $@ && $(LN_S) -f $< $@ + libmesh_documentation.h: $(top_srcdir)/include/base/libmesh_documentation.h $(AM_V_GEN)rm -f $@ && $(LN_S) -f $< $@ @@ -1055,6 +1059,9 @@ enum_elem_type.h: $(top_srcdir)/include/enums/enum_elem_type.h enum_error_estimator_type.h: $(top_srcdir)/include/enums/enum_error_estimator_type.h $(AM_V_GEN)rm -f $@ && $(LN_S) -f $< $@ +enum_fe_elem_class.h: $(top_srcdir)/include/enums/enum_fe_elem_class.h + $(AM_V_GEN)rm -f $@ && $(LN_S) -f $< $@ + enum_fe_family.h: $(top_srcdir)/include/enums/enum_fe_family.h $(AM_V_GEN)rm -f $@ && $(LN_S) -f $< $@ diff --git a/include/libmesh/rebuild_makefile.sh b/include/libmesh/rebuild_makefile.sh index dcef53ce15..fe1f31bece 100755 --- a/include/libmesh/rebuild_makefile.sh +++ b/include/libmesh/rebuild_makefile.sh @@ -2,7 +2,7 @@ built_sources="" -headers=`find .. -name "*.h" -a -not -name libmesh_config.h -type f | LC_COLLATE=POSIX sort` +headers=`find .. -name "*.h" -a -not -name libmesh_config.h -a -not -path "../kokkos/*" -type f | LC_COLLATE=POSIX sort` for header_with_path in $headers ; do diff --git a/include/libmesh_config.h.in b/include/libmesh_config.h.in index 17c095ba2b..62256949fe 100644 --- a/include/libmesh_config.h.in +++ b/include/libmesh_config.h.in @@ -434,6 +434,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H +/* Define if Kokkos support is enabled in libMesh */ +#undef HAVE_KOKKOS + /* Flag indicating whether the library will be compiled with LASPACK support */ #undef HAVE_LASPACK diff --git a/include/numerics/tensor_value.h b/include/numerics/tensor_value.h index 3a0d680476..5578001aa9 100644 --- a/include/numerics/tensor_value.h +++ b/include/numerics/tensor_value.h @@ -22,6 +22,7 @@ // Local includes #include "libmesh/type_tensor.h" +#include "libmesh/libmesh_device.h" #include "libmesh/libmesh.h" // for pi #ifdef LIBMESH_HAVE_METAPHYSICL @@ -211,7 +212,7 @@ typedef NumberTensorValue Tensor; //------------------------------------------------------ // Inline functions template -inline +LIBMESH_DEVICE_INLINE TensorValue::TensorValue () : TypeTensor () { @@ -220,7 +221,7 @@ TensorValue::TensorValue () : template -inline +LIBMESH_DEVICE_INLINE TensorValue::TensorValue (const T & xx, const T & xy, const T & xz, @@ -237,7 +238,7 @@ TensorValue::TensorValue (const T & xx, template template -inline +LIBMESH_DEVICE_INLINE TensorValue::TensorValue (const Scalar & xx, const Scalar & xy, const Scalar & xz, @@ -257,7 +258,7 @@ TensorValue::TensorValue (const Scalar & xx, template template -inline +LIBMESH_DEVICE_INLINE TensorValue::TensorValue (const TensorValue & p) : TypeTensor (p) { @@ -267,7 +268,7 @@ TensorValue::TensorValue (const TensorValue & p) : template template -inline +LIBMESH_DEVICE_INLINE TensorValue::TensorValue (const TypeVector & vx) : TypeTensor (vx) { @@ -300,7 +301,7 @@ TensorValue::TensorValue (const TypeVector & vx, template template -inline +LIBMESH_DEVICE_INLINE TensorValue::TensorValue (const TypeTensor & p) : TypeTensor (p) { diff --git a/include/numerics/type_tensor.h b/include/numerics/type_tensor.h index 470b745f12..926c7ad81d 100644 --- a/include/numerics/type_tensor.h +++ b/include/numerics/type_tensor.h @@ -22,6 +22,7 @@ // Local includes #include "libmesh/libmesh_common.h" +#include "libmesh/libmesh_device.h" #include "libmesh/type_vector.h" // C++ includes @@ -513,7 +514,7 @@ class ConstTypeTensorColumn //------------------------------------------------------ // Inline functions template -inline +LIBMESH_DEVICE_INLINE TypeTensor::TypeTensor () { _coords[0] = {}; @@ -536,7 +537,7 @@ TypeTensor::TypeTensor () template -inline +LIBMESH_DEVICE_INLINE TypeTensor::TypeTensor (const T & xx, const T & xy, const T & xz, @@ -582,7 +583,7 @@ TypeTensor::TypeTensor (const T & xx, template template -inline +LIBMESH_DEVICE_INLINE TypeTensor::TypeTensor (const Scalar & xx, const Scalar & xy, const Scalar & xz, @@ -631,7 +632,7 @@ TypeTensor::TypeTensor (const Scalar & xx, template template -inline +LIBMESH_DEVICE_INLINE TypeTensor::TypeTensor (const TypeTensor & p) { // copy the nodes from vector p to me @@ -709,7 +710,7 @@ void TypeTensor::assign (const TypeTensor & p) template -inline +LIBMESH_DEVICE_INLINE const T & TypeTensor::operator () (const unsigned int i, const unsigned int j) const { @@ -728,7 +729,7 @@ const T & TypeTensor::operator () (const unsigned int i, template -inline +LIBMESH_DEVICE_INLINE T & TypeTensor::operator () (const unsigned int i, const unsigned int j) { @@ -767,7 +768,7 @@ TypeTensor::slice (const unsigned int i) template -inline +LIBMESH_DEVICE_INLINE TypeVector TypeTensor::row(const unsigned int r) const { @@ -796,7 +797,7 @@ TypeTensor::column(const unsigned int r) const template template -inline +LIBMESH_DEVICE_INLINE TypeTensor::supertype> TypeTensor::operator + (const TypeTensor & p) const { @@ -831,7 +832,7 @@ TypeTensor::operator + (const TypeTensor & p) const template template -inline +LIBMESH_DEVICE_INLINE const TypeTensor & TypeTensor::operator += (const TypeTensor & p) { this->add (p); @@ -843,7 +844,7 @@ const TypeTensor & TypeTensor::operator += (const TypeTensor & p) template template -inline +LIBMESH_DEVICE_INLINE void TypeTensor::add (const TypeTensor & p) { for (unsigned int i=0; i::add_scaled (const TypeTensor & p, const T & factor) template template -inline +LIBMESH_DEVICE_INLINE TypeTensor::supertype> TypeTensor::operator - (const TypeTensor & p) const { @@ -901,7 +902,7 @@ TypeTensor::operator - (const TypeTensor & p) const template template -inline +LIBMESH_DEVICE_INLINE const TypeTensor & TypeTensor::operator -= (const TypeTensor & p) { this->subtract (p); @@ -913,7 +914,7 @@ const TypeTensor & TypeTensor::operator -= (const TypeTensor & p) template template -inline +LIBMESH_DEVICE_INLINE void TypeTensor::subtract (const TypeTensor & p) { for (unsigned int i=0; i::subtract_scaled (const TypeTensor & p, const T & factor) template -inline +LIBMESH_DEVICE_INLINE TypeTensor TypeTensor::operator - () const { @@ -967,7 +968,7 @@ TypeTensor TypeTensor::operator - () const template template -inline +LIBMESH_DEVICE_INLINE auto TypeTensor::operator * (const Scalar & factor) const -> typename std::enable_if< ScalarTraits::value, @@ -1003,7 +1004,7 @@ TypeTensor::operator * (const Scalar & factor) const -> typename std::enable_ template -inline +LIBMESH_DEVICE_INLINE typename std::enable_if< ScalarTraits::value, TypeTensor::supertype>>::type @@ -1015,7 +1016,7 @@ operator * (const Scalar & factor, template template -inline +LIBMESH_DEVICE_INLINE typename std::enable_if< ScalarTraits::value, TypeTensor::supertype>>::type @@ -1053,7 +1054,7 @@ TypeTensor::operator / (const Scalar & factor) const template -inline +LIBMESH_DEVICE_INLINE TypeTensor TypeTensor::transpose() const { #if LIBMESH_DIM == 1 @@ -1083,7 +1084,7 @@ TypeTensor TypeTensor::transpose() const template -inline +LIBMESH_DEVICE_INLINE TypeTensor TypeTensor::inverse() const { #if LIBMESH_DIM == 1 @@ -1183,7 +1184,7 @@ void TypeTensor::solve(const TypeVector & b, TypeVector & x) const template -inline +LIBMESH_DEVICE_INLINE const TypeTensor & TypeTensor::operator /= (const T & factor) { libmesh_assert_not_equal_to (factor, static_cast(0.)); @@ -1199,7 +1200,7 @@ const TypeTensor & TypeTensor::operator /= (const T & factor) template template -inline +LIBMESH_DEVICE_INLINE TypeVector::supertype> TypeTensor::operator * (const TypeVector & p) const { @@ -1235,7 +1236,7 @@ operator * (const TypeVector & a, const TypeTensor & b) template template -inline +LIBMESH_DEVICE_INLINE TypeTensor::supertype> TypeTensor::operator * (const TypeTensor & p) const { @@ -1250,7 +1251,7 @@ TypeTensor::operator * (const TypeTensor & p) const template template -inline +LIBMESH_DEVICE_INLINE const TypeTensor & TypeTensor::operator *= (const TypeTensor & p) { TypeTensor temp; @@ -1283,7 +1284,7 @@ TypeTensor::contract (const TypeTensor & t) const template -inline +LIBMESH_DEVICE_INLINE auto TypeTensor::norm() const { using std::sqrt; @@ -1302,7 +1303,7 @@ bool TypeTensor::is_zero() const } template -inline +LIBMESH_DEVICE_INLINE T TypeTensor::det() const { #if LIBMESH_DIM == 1 @@ -1325,7 +1326,7 @@ T TypeTensor::det() const } template -inline +LIBMESH_DEVICE_INLINE T TypeTensor::tr() const { #if LIBMESH_DIM == 1 @@ -1352,7 +1353,7 @@ void TypeTensor::zero() template -inline +LIBMESH_DEVICE_INLINE auto TypeTensor::norm_sq () const { Real sum = 0.; @@ -1436,7 +1437,7 @@ void TypeTensor::print(std::ostream & os) const } template -inline +LIBMESH_DEVICE_INLINE TypeTensor::supertype> outer_product(const TypeVector & a, const TypeVector & b) { diff --git a/include/numerics/type_vector.h b/include/numerics/type_vector.h index aaf79a9fd2..edaf6afcaf 100644 --- a/include/numerics/type_vector.h +++ b/include/numerics/type_vector.h @@ -22,6 +22,7 @@ // Local includes #include "libmesh/libmesh_common.h" +#include "libmesh/libmesh_device.h" #include "libmesh/compare_types.h" #include "libmesh/tensor_tools.h" #include "libmesh/int_range.h" @@ -425,7 +426,7 @@ class TypeVector // Inline functions template -inline +LIBMESH_DEVICE_INLINE TypeVector::TypeVector () { _coords[0] = {}; @@ -442,7 +443,7 @@ TypeVector::TypeVector () template -inline +LIBMESH_DEVICE_INLINE TypeVector::TypeVector (const T & x, const T & y, const T & z) @@ -467,7 +468,7 @@ TypeVector::TypeVector (const T & x, template template -inline +LIBMESH_DEVICE_INLINE TypeVector::TypeVector (typename std::enable_if::value, const Scalar1>::type & x, @@ -497,7 +498,7 @@ TypeVector::TypeVector (typename template template -inline +LIBMESH_DEVICE_INLINE TypeVector::TypeVector (const Scalar & x, typename std::enable_if::value, @@ -518,7 +519,7 @@ TypeVector::TypeVector (const Scalar & x, template template -inline +LIBMESH_DEVICE_INLINE TypeVector::TypeVector (const TypeVector & p) { // copy the nodes from vector p to me @@ -540,7 +541,7 @@ void TypeVector::assign (const TypeVector & p) template -inline +LIBMESH_DEVICE_INLINE const T & TypeVector::operator () (const unsigned int i) const { libmesh_assert_less (i, LIBMESH_DIM); @@ -551,7 +552,7 @@ const T & TypeVector::operator () (const unsigned int i) const template -inline +LIBMESH_DEVICE_INLINE T & TypeVector::operator () (const unsigned int i) { libmesh_assert_less (i, LIBMESH_DIM); @@ -563,7 +564,7 @@ T & TypeVector::operator () (const unsigned int i) template template -inline +LIBMESH_DEVICE_INLINE TypeVector::supertype> TypeVector::operator + (const TypeVector & p) const { @@ -589,7 +590,7 @@ TypeVector::operator + (const TypeVector & p) const template template -inline +LIBMESH_DEVICE_INLINE const TypeVector & TypeVector::operator += (const TypeVector & p) { this->add (p); @@ -601,7 +602,7 @@ const TypeVector & TypeVector::operator += (const TypeVector & p) template template -inline +LIBMESH_DEVICE_INLINE void TypeVector::add (const TypeVector & p) { #if LIBMESH_DIM == 1 @@ -649,7 +650,7 @@ void TypeVector::add_scaled (const TypeVector & p, const T & factor) template template -inline +LIBMESH_DEVICE_INLINE TypeVector::supertype> TypeVector::operator - (const TypeVector & p) const { @@ -676,7 +677,7 @@ TypeVector::operator - (const TypeVector & p) const template template -inline +LIBMESH_DEVICE_INLINE const TypeVector & TypeVector::operator -= (const TypeVector & p) { this->subtract (p); @@ -688,7 +689,7 @@ const TypeVector & TypeVector::operator -= (const TypeVector & p) template template -inline +LIBMESH_DEVICE_INLINE void TypeVector::subtract (const TypeVector & p) { for (unsigned int i=0; i::subtract_scaled (const TypeVector & p, const T & factor) template -inline +LIBMESH_DEVICE_INLINE TypeVector TypeVector::operator - () const { @@ -734,7 +735,7 @@ TypeVector TypeVector::operator - () const template template -inline +LIBMESH_DEVICE_INLINE typename std::enable_if< ScalarTraits::value, TypeVector::supertype>>::type @@ -761,7 +762,7 @@ TypeVector::operator * (const Scalar & factor) const template -inline +LIBMESH_DEVICE_INLINE typename std::enable_if< ScalarTraits::value, TypeVector::supertype>>::type @@ -774,7 +775,7 @@ operator * (const Scalar & factor, template -inline +LIBMESH_DEVICE_INLINE const TypeVector & TypeVector::operator *= (const T & factor) { #if LIBMESH_DIM == 1 @@ -799,7 +800,7 @@ const TypeVector & TypeVector::operator *= (const T & factor) template template -inline +LIBMESH_DEVICE_INLINE typename std::enable_if< ScalarTraits::value, TypeVector::supertype>>::type @@ -830,7 +831,7 @@ TypeVector::operator / (const Scalar & factor) const template -inline +LIBMESH_DEVICE_INLINE const TypeVector & TypeVector::operator /= (const T & factor) { @@ -847,7 +848,7 @@ TypeVector::operator /= (const T & factor) template template -inline +LIBMESH_DEVICE_INLINE typename CompareTypes::supertype TypeVector::operator * (const TypeVector & p) const { @@ -880,6 +881,7 @@ TypeVector::contract(const TypeVector & p) const template template +LIBMESH_DEVICE_INLINE TypeVector::supertype> TypeVector::cross(const TypeVector & p) const { @@ -903,7 +905,7 @@ TypeVector::cross(const TypeVector & p) const template -inline +LIBMESH_DEVICE_INLINE auto TypeVector::norm() const { using std::sqrt; @@ -923,7 +925,7 @@ void TypeVector::zero() template -inline +LIBMESH_DEVICE_INLINE auto TypeVector::norm_sq() const { #if LIBMESH_DIM == 1 @@ -1167,6 +1169,7 @@ struct CompareTypes, TypeVector> }; template ::value, int>::type = 0> +LIBMESH_DEVICE_INLINE TypeVector::supertype> outer_product(const T & a, const TypeVector & b) { @@ -1178,6 +1181,7 @@ outer_product(const T & a, const TypeVector & b) } template ::value, int>::type = 0> +LIBMESH_DEVICE_INLINE TypeVector::supertype> outer_product(const TypeVector & a, const T2 & b) { diff --git a/include/numerics/vector_value.h b/include/numerics/vector_value.h index c93f17313d..5c8e36dfc8 100644 --- a/include/numerics/vector_value.h +++ b/include/numerics/vector_value.h @@ -22,6 +22,7 @@ // Local includes #include "libmesh/type_vector.h" +#include "libmesh/libmesh_device.h" #include "libmesh/compare_types.h" #ifdef LIBMESH_HAVE_METAPHYSICL @@ -146,7 +147,7 @@ typedef NumberVectorValue Gradient; // Inline functions template -inline +LIBMESH_DEVICE_INLINE VectorValue::VectorValue () : TypeVector () { @@ -154,7 +155,7 @@ VectorValue::VectorValue () : template -inline +LIBMESH_DEVICE_INLINE VectorValue::VectorValue (const T & x, const T & y, const T & z) : @@ -166,7 +167,7 @@ VectorValue::VectorValue (const T & x, template template -inline +LIBMESH_DEVICE_INLINE VectorValue::VectorValue (typename std::enable_if::value, const Scalar1>::type & x, @@ -183,7 +184,7 @@ VectorValue::VectorValue (typename template template -inline +LIBMESH_DEVICE_INLINE VectorValue::VectorValue (const Scalar & x, typename std::enable_if::value, @@ -194,7 +195,7 @@ VectorValue::VectorValue (const Scalar & x, template template -inline +LIBMESH_DEVICE_INLINE VectorValue::VectorValue (const VectorValue & p) : TypeVector (p) { @@ -204,7 +205,7 @@ VectorValue::VectorValue (const VectorValue & p) : template template -inline +LIBMESH_DEVICE_INLINE VectorValue::VectorValue (const TypeVector & p) : TypeVector (p) { diff --git a/include/quadrature/quadrature_gauss_data.h b/include/quadrature/quadrature_gauss_data.h new file mode 100644 index 0000000000..efac900462 --- /dev/null +++ b/include/quadrature/quadrature_gauss_data.h @@ -0,0 +1,600 @@ +// The libMesh Finite Element Library. +// Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner + +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +#ifndef LIBMESH_QUADRATURE_GAUSS_DATA_H +#define LIBMESH_QUADRATURE_GAUSS_DATA_H + +#include "libmesh/libmesh_common.h" + +namespace libMesh +{ + +namespace gauss_rule_data +{ + +struct point_2d +{ + Real x; + Real y; +}; + +struct point_3d +{ + Real x; + Real y; + Real z; +}; + +LIBMESH_DEVICE_INLINE unsigned int +gauss_legendre_n_points(unsigned int alg_order) +{ + const unsigned int n = (alg_order + 2u) / 2u; + return (n < 1u) ? 1u : (n > 7u ? 7u : n); +} + +LIBMESH_DEVICE_INLINE Real +gauss_legendre_point(unsigned int n, unsigned int i) +{ + libmesh_assert_greater_equal(n, 1u); + libmesh_assert_less_equal(n, 7u); + libmesh_assert_less(i, n); + + switch (n) + { + case 1: return 0.0; + case 2: + switch (i) + { + case 0: return -5.7735026918962576450914878050196e-01_R; + case 1: return 5.7735026918962576450914878050196e-01_R; + } + break; + case 3: + switch (i) + { + case 0: return -7.7459666924148337703585307995648e-01_R; + case 1: return 0.0; + case 2: return 7.7459666924148337703585307995648e-01_R; + } + break; + case 4: + switch (i) + { + case 0: return -8.6113631159405257522394648889281e-01_R; + case 1: return -3.3998104358485626480266575910324e-01_R; + case 2: return 3.3998104358485626480266575910324e-01_R; + case 3: return 8.6113631159405257522394648889281e-01_R; + } + break; + case 5: + switch (i) + { + case 0: return -9.0617984593866399279762687829939e-01_R; + case 1: return -5.3846931010568309103631442070021e-01_R; + case 2: return 0.0; + case 3: return 5.3846931010568309103631442070021e-01_R; + case 4: return 9.0617984593866399279762687829939e-01_R; + } + break; + case 6: + switch (i) + { + case 0: return -9.3246951420315202781230155449399e-01_R; + case 1: return -6.6120938646626451366139959501991e-01_R; + case 2: return -2.3861918608319690863050172168071e-01_R; + case 3: return 2.3861918608319690863050172168071e-01_R; + case 4: return 6.6120938646626451366139959501991e-01_R; + case 5: return 9.3246951420315202781230155449399e-01_R; + } + break; + case 7: + switch (i) + { + case 0: return -9.4910791234275852452618968404785e-01_R; + case 1: return -7.4153118559939443986386477328079e-01_R; + case 2: return -4.0584515137739716690660641207696e-01_R; + case 3: return 0.0; + case 4: return 4.0584515137739716690660641207696e-01_R; + case 5: return 7.4153118559939443986386477328079e-01_R; + case 6: return 9.4910791234275852452618968404785e-01_R; + } + break; + } + + libmesh_assert_msg(false, "Bad Gauss-Legendre rule request"); + return 0.0; +} + +LIBMESH_DEVICE_INLINE Real +gauss_legendre_weight(unsigned int n, unsigned int i) +{ + libmesh_assert_greater_equal(n, 1u); + libmesh_assert_less_equal(n, 7u); + libmesh_assert_less(i, n); + + switch (n) + { + case 1: return 2.0; + case 2: return 1.0; + case 3: + switch (i) + { + case 0: + case 2: + return 5.5555555555555555555555555555556e-01_R; + case 1: + return 8.8888888888888888888888888888889e-01_R; + } + break; + case 4: + switch (i) + { + case 0: + case 3: + return 3.4785484513745385737306394922200e-01_R; + case 1: + case 2: + return 6.5214515486254614262693605077800e-01_R; + } + break; + case 5: + switch (i) + { + case 0: + case 4: + return 2.3692688505618908751426404071992e-01_R; + case 1: + case 3: + return 4.7862867049936646804129151483564e-01_R; + case 2: + return 5.6888888888888888888888888888889e-01_R; + } + break; + case 6: + switch (i) + { + case 0: + case 5: + return 1.7132449237917034504029614217273e-01_R; + case 1: + case 4: + return 3.6076157304813860756983351383772e-01_R; + case 2: + case 3: + return 4.6791393457269104738987034398955e-01_R; + } + break; + case 7: + switch (i) + { + case 0: + case 6: + return 1.2948496616886969327061143267908e-01_R; + case 1: + case 5: + return 2.7970539148927666790146777142378e-01_R; + case 2: + case 4: + return 3.8183005050511894495036977548898e-01_R; + case 3: + return 4.1795918367346938775510204081633e-01_R; + } + break; + } + + libmesh_assert_msg(false, "Bad Gauss-Legendre rule request"); + return 0.0; +} + +LIBMESH_DEVICE_INLINE unsigned int +tri_n_points(unsigned int order) +{ + libmesh_assert_less_equal(order, 7u); + + switch (order) + { + case 0: + case 1: + return 1; + case 2: + return 3; + case 3: + return 4; + case 4: + return 6; + case 5: + return 7; + case 6: + case 7: + return 12; + } + + libmesh_assert_msg(false, "Bad triangle Gauss rule request"); + return 0; +} + +LIBMESH_DEVICE_INLINE point_2d +tri_point(unsigned int order, unsigned int qp) +{ + libmesh_assert_less_equal(order, 7u); + libmesh_assert_less(qp, tri_n_points(order)); + + switch (order) + { + case 0: + case 1: + return {Real(1) / 3, Real(1) / 3}; + + case 2: + switch (qp) + { + case 0: return {Real(2) / 3, Real(1) / 6}; + case 1: return {Real(1) / 6, Real(2) / 3}; + case 2: return {Real(1) / 6, Real(1) / 6}; + } + break; + + case 3: + switch (qp) + { + case 0: return {1.5505102572168219018027159252941e-01_R, 1.7855872826361642311703513337422e-01_R}; + case 1: return {6.4494897427831780981972840747059e-01_R, 7.5031110222608118177475598324603e-02_R}; + case 2: return {1.5505102572168219018027159252941e-01_R, 6.6639024601470138670269327409637e-01_R}; + case 3: return {6.4494897427831780981972840747059e-01_R, 2.8001991549907407200279599420481e-01_R}; + } + break; + + case 4: + { + const Real a1 = 4.4594849091596488631832925388305199e-01_R; + const Real a2 = 9.1576213509770743459571463402201508e-02_R; + const Real b1 = 1.0 - 2.0 * a1; + const Real b2 = 1.0 - 2.0 * a2; + + switch (qp) + { + case 0: return {a1, a1}; + case 1: return {a1, b1}; + case 2: return {b1, a1}; + case 3: return {a2, a2}; + case 4: return {a2, b2}; + case 5: return {b2, a2}; + } + break; + } + + case 5: + { + const Real a1 = 4.7014206410511508977044120951344760e-01_R; + const Real a2 = 1.0128650732345633880098736191512383e-01_R; + const Real b1 = 1.0 - 2.0 * a1; + const Real b2 = 1.0 - 2.0 * a2; + + switch (qp) + { + case 0: return {Real(1) / 3, Real(1) / 3}; + case 1: return {a1, a1}; + case 2: return {a1, b1}; + case 3: return {b1, a1}; + case 4: return {a2, a2}; + case 5: return {a2, b2}; + case 6: return {b2, a2}; + } + break; + } + + case 6: + { + const Real a1 = 2.4928674517091042129163855310701908e-01_R; + const Real a2 = 6.3089014491502228340331602870819157e-02_R; + const Real a3 = 3.1035245103378440541660773395655215e-01_R; + const Real b1 = 1.0 - 2.0 * a1; + const Real b2 = 1.0 - 2.0 * a2; + const Real b3 = 6.3650249912139864723014259441204970e-01_R; + const Real c3 = 1.0 - a3 - b3; + + switch (qp) + { + case 0: return {a1, a1}; + case 1: return {a1, b1}; + case 2: return {b1, a1}; + case 3: return {a2, a2}; + case 4: return {a2, b2}; + case 5: return {b2, a2}; + case 6: return {a3, b3}; + case 7: return {b3, a3}; + case 8: return {a3, c3}; + case 9: return {c3, a3}; + case 10: return {b3, c3}; + case 11: return {c3, b3}; + } + break; + } + + case 7: + switch (qp) + { + case 0: return {6.2382265094402118173683000996350e-02_R, 6.7517867073916085442557131050869e-02_R}; + case 1: return {8.7009986773168179638375986798548e-01_R, 6.2382265094402118173683000996350e-02_R}; + case 2: return {6.7517867073916085442557131050869e-02_R, 8.7009986773168179638375986798548e-01_R}; + case 3: return {5.5225456656926611737479190275645e-02_R, 3.2150249385198182266630784919920e-01_R}; + case 4: return {6.2327204949109156559621296052515e-01_R, 5.5225456656926611737479190275645e-02_R}; + case 5: return {3.2150249385198182266630784919920e-01_R, 6.2327204949109156559621296052515e-01_R}; + case 6: return {3.4324302945097146469630642483938e-02_R, 6.6094919618673565761198031019780e-01_R}; + case 7: return {3.0472650086816719591838904731826e-01_R, 3.4324302945097146469630642483938e-02_R}; + case 8: return {6.6094919618673565761198031019780e-01_R, 3.0472650086816719591838904731826e-01_R}; + case 9: return {5.1584233435359177925746338682643e-01_R, 2.7771616697639178256958187139372e-01_R}; + case 10: return {2.0644149867001643817295474177984e-01_R, 5.1584233435359177925746338682643e-01_R}; + case 11: return {2.7771616697639178256958187139372e-01_R, 2.0644149867001643817295474177984e-01_R}; + } + break; + } + + libmesh_assert_msg(false, "Bad triangle Gauss rule request"); + return {0.0, 0.0}; +} + +LIBMESH_DEVICE_INLINE Real +tri_weight(unsigned int order, unsigned int qp) +{ + libmesh_assert_less_equal(order, 7u); + libmesh_assert_less(qp, tri_n_points(order)); + + switch (order) + { + case 0: + case 1: + return 0.5; + + case 2: + return Real(1) / 6; + + case 3: + return (qp % 2 == 0) ? + 1.5902069087198858469718450103758e-01_R : + 9.0979309128011415302815498962418e-02_R; + + case 4: + return (qp < 3) ? + 1.1169079483900573284750350421656140e-01_R : + 5.4975871827660933819163162450105264e-02_R; + + case 5: + if (qp == 0) + return Real(9) / 80; + return (qp <= 3) ? + 6.6197076394253090368824693916576000e-02_R : + 6.2969590272413576297841972750090667e-02_R; + + case 6: + if (qp <= 2) + return 5.8393137863189683012644805692789721e-02_R; + if (qp <= 5) + return 2.5422453185103408460468404553434492e-02_R; + return 4.1425537809186787596776728210221227e-02_R; + + case 7: + switch (qp / 3) + { + case 0: return 2.6517028157436251428754180460739e-02_R; + case 1: return 4.3881408714446055036769903139288e-02_R; + case 2: return 2.8775042784981585738445496900219e-02_R; + case 3: return 6.7493187009802774462697086166421e-02_R; + } + break; + } + + libmesh_assert_msg(false, "Bad triangle Gauss rule request"); + return 0.0; +} + +LIBMESH_DEVICE_INLINE unsigned int +tet_n_points(unsigned int order) +{ + libmesh_assert_less_equal(order, 6u); + + switch (order) + { + case 0: + case 1: + return 1; + case 2: + return 4; + case 3: + return 5; + case 4: + return 11; + case 5: + return 14; + case 6: + return 24; + } + + libmesh_assert_msg(false, "Bad tetrahedron Gauss rule request"); + return 0; +} + +LIBMESH_DEVICE_INLINE point_3d +tet_point(unsigned int order, unsigned int qp) +{ + libmesh_assert_less_equal(order, 6u); + libmesh_assert_less(qp, tet_n_points(order)); + + switch (order) + { + case 0: + case 1: + return {0.25, 0.25, 0.25}; + + case 2: + { + const Real a = 5.8541019662496845446137605030969144e-01_R; + const Real b = 1.3819660112501051517954131656343619e-01_R; + + switch (qp) + { + case 0: return {a, b, b}; + case 1: return {b, a, b}; + case 2: return {b, b, a}; + case 3: return {b, b, b}; + } + break; + } + + case 3: + switch (qp) + { + case 0: return {0.25, 0.25, 0.25}; + case 1: return {0.5, Real(1) / 6, Real(1) / 6}; + case 2: return {Real(1) / 6, 0.5, Real(1) / 6}; + case 3: return {Real(1) / 6, Real(1) / 6, 0.5}; + case 4: return {Real(1) / 6, Real(1) / 6, Real(1) / 6}; + } + break; + + case 4: + switch (qp) + { + case 0: return {0.250000000000000000e+00_R, 0.250000000000000000e+00_R, 0.250000000000000000e+00_R}; + case 1: return {0.785714285714285714e+00_R, 0.0714285714285714285e+00_R, 0.0714285714285714285e+00_R}; + case 2: return {0.0714285714285714285e+00_R, 0.785714285714285714e+00_R, 0.0714285714285714285e+00_R}; + case 3: return {0.0714285714285714285e+00_R, 0.0714285714285714285e+00_R, 0.785714285714285714e+00_R}; + case 4: return {0.0714285714285714285e+00_R, 0.0714285714285714285e+00_R, 0.0714285714285714285e+00_R}; + case 5: return {0.399403576166799219e+00_R, 0.399403576166799219e+00_R, 0.100596423833200785e+00_R}; + case 6: return {0.399403576166799219e+00_R, 0.100596423833200785e+00_R, 0.100596423833200785e+00_R}; + case 7: return {0.100596423833200785e+00_R, 0.100596423833200785e+00_R, 0.399403576166799219e+00_R}; + case 8: return {0.100596423833200785e+00_R, 0.399403576166799219e+00_R, 0.100596423833200785e+00_R}; + case 9: return {0.100596423833200785e+00_R, 0.399403576166799219e+00_R, 0.399403576166799219e+00_R}; + case 10: return {0.399403576166799219e+00_R, 0.100596423833200785e+00_R, 0.399403576166799219e+00_R}; + } + break; + + case 5: + { + const Real a0 = 3.1088591926330060980e-01_R; + const Real a1 = 9.2735250310891226402e-02_R; + const Real a2 = 4.5503704125649649492e-02_R; + const Real b0 = 1.0 - 3.0 * a0; + const Real b1 = 1.0 - 3.0 * a1; + const Real b2 = 0.5 * (1.0 - 2.0 * a2); + + switch (qp) + { + case 0: return {a0, a0, a0}; + case 1: return {a0, b0, a0}; + case 2: return {b0, a0, a0}; + case 3: return {a0, a0, b0}; + case 4: return {a1, a1, a1}; + case 5: return {a1, b1, a1}; + case 6: return {b1, a1, a1}; + case 7: return {a1, a1, b1}; + case 8: return {b2, b2, a2}; + case 9: return {b2, a2, a2}; + case 10: return {a2, a2, b2}; + case 11: return {a2, b2, a2}; + case 12: return {b2, a2, b2}; + case 13: return {a2, b2, b2}; + } + break; + } + + case 6: + switch (qp) + { + case 0: return {0.356191386222544953e+00_R, 0.214602871259151684e+00_R, 0.214602871259151684e+00_R}; + case 1: return {0.214602871259151684e+00_R, 0.356191386222544953e+00_R, 0.214602871259151684e+00_R}; + case 2: return {0.214602871259151684e+00_R, 0.214602871259151684e+00_R, 0.356191386222544953e+00_R}; + case 3: return {0.214602871259151684e+00_R, 0.214602871259151684e+00_R, 0.214602871259151684e+00_R}; + case 4: return {0.877978124396165982e+00_R, 0.0406739585346113397e+00_R, 0.0406739585346113397e+00_R}; + case 5: return {0.0406739585346113397e+00_R, 0.877978124396165982e+00_R, 0.0406739585346113397e+00_R}; + case 6: return {0.0406739585346113397e+00_R, 0.0406739585346113397e+00_R, 0.877978124396165982e+00_R}; + case 7: return {0.0406739585346113397e+00_R, 0.0406739585346113397e+00_R, 0.0406739585346113397e+00_R}; + case 8: return {0.0329863295731730594e+00_R, 0.322337890142275646e+00_R, 0.322337890142275646e+00_R}; + case 9: return {0.322337890142275646e+00_R, 0.0329863295731730594e+00_R, 0.322337890142275646e+00_R}; + case 10: return {0.322337890142275646e+00_R, 0.322337890142275646e+00_R, 0.0329863295731730594e+00_R}; + case 11: return {0.322337890142275646e+00_R, 0.322337890142275646e+00_R, 0.322337890142275646e+00_R}; + case 12: return {0.0636610018750175299e+00_R, 0.0636610018750175299e+00_R, 0.269672331458315867e+00_R}; + case 13: return {0.0636610018750175299e+00_R, 0.0636610018750175299e+00_R, 0.603005664791649076e+00_R}; + case 14: return {0.269672331458315867e+00_R, 0.0636610018750175299e+00_R, 0.0636610018750175299e+00_R}; + case 15: return {0.603005664791649076e+00_R, 0.0636610018750175299e+00_R, 0.0636610018750175299e+00_R}; + case 16: return {0.0636610018750175299e+00_R, 0.269672331458315867e+00_R, 0.0636610018750175299e+00_R}; + case 17: return {0.0636610018750175299e+00_R, 0.603005664791649076e+00_R, 0.0636610018750175299e+00_R}; + case 18: return {0.0636610018750175299e+00_R, 0.269672331458315867e+00_R, 0.603005664791649076e+00_R}; + case 19: return {0.0636610018750175299e+00_R, 0.603005664791649076e+00_R, 0.269672331458315867e+00_R}; + case 20: return {0.269672331458315867e+00_R, 0.0636610018750175299e+00_R, 0.603005664791649076e+00_R}; + case 21: return {0.269672331458315867e+00_R, 0.603005664791649076e+00_R, 0.0636610018750175299e+00_R}; + case 22: return {0.603005664791649076e+00_R, 0.0636610018750175299e+00_R, 0.269672331458315867e+00_R}; + case 23: return {0.603005664791649076e+00_R, 0.269672331458315867e+00_R, 0.0636610018750175299e+00_R}; + } + break; + } + + libmesh_assert_msg(false, "Bad tetrahedron Gauss rule request"); + return {0.0, 0.0, 0.0}; +} + +LIBMESH_DEVICE_INLINE Real +tet_weight(unsigned int order, unsigned int qp) +{ + libmesh_assert_less_equal(order, 6u); + libmesh_assert_less(qp, tet_n_points(order)); + + switch (order) + { + case 0: + case 1: + return Real(1) / 6; + + case 2: + return Real(1) / 24; + + case 3: + return (qp == 0) ? Real(-2) / 15 : 7.5e-02_R; + + case 4: + if (qp == 0) + return -1.31555555555555556e-02_R; + if (qp <= 4) + return 7.62222222222222222e-03_R; + return 2.48888888888888889e-02_R; + + case 5: + if (qp < 4) + return 1.8781320953002641800e-02_R; + if (qp < 8) + return 1.2248840519393658257e-02_R; + return 7.0910034628469110730e-03_R; + + case 6: + if (qp < 4) + return 6.65379170969464506e-03_R; + if (qp < 8) + return 1.67953517588677620e-03_R; + if (qp < 12) + return 9.22619692394239843e-03_R; + return 8.03571428571428248e-03_R; + } + + libmesh_assert_msg(false, "Bad tetrahedron Gauss rule request"); + return 0.0; +} + +} // namespace gauss_rule_data + +} // namespace libMesh + +#endif // LIBMESH_QUADRATURE_GAUSS_DATA_H diff --git a/m4/libmesh_optional_packages.m4 b/m4/libmesh_optional_packages.m4 index 2c569d088c..6f3ca66ac7 100644 --- a/m4/libmesh_optional_packages.m4 +++ b/m4/libmesh_optional_packages.m4 @@ -861,6 +861,127 @@ AM_CONDITIONAL(LIBMESH_ENABLE_METAPHYSICL, test x$enablemetaphysicl = xyes) +# ------------------------------------------------------------- +# Kokkos -- optional, enables the native Kokkos FE math path +# ------------------------------------------------------------- +AC_ARG_WITH([kokkos], + AS_HELP_STRING([--with-kokkos=DIR], + [Enable Kokkos support using the installation at DIR]), + [KOKKOS_DIR="$withval"], + [KOKKOS_DIR="no"]) + +AC_ARG_WITH([kokkos-backend], + AS_HELP_STRING([--with-kokkos-backend=BACKEND], + [cuda|hip|sycl|openmp|serial (default: auto-detect from KokkosCore_config.h)]), + [KOKKOS_BACKEND="$withval"], [KOKKOS_BACKEND="auto"]) + +dnl Allow the caller (e.g. MOOSE's configure_libmesh.sh) to pre-set the +dnl Kokkos compiler and flags via environment variables. If KOKKOS_CXX is +dnl already set, we skip auto-detection entirely — the caller knows best. +dnl We use AC_SUBST (not AC_ARG_VAR) so these flags stay scoped to .K +dnl compilation rules and don't leak into the main CPPFLAGS/CXXFLAGS. + +AS_IF([test "x$KOKKOS_DIR" != "xno"], + [ + AC_CHECK_FILE([$KOKKOS_DIR/include/Kokkos_Core.hpp], + [ + enablekokkos=yes + libmesh_optional_INCLUDES="$libmesh_optional_INCLUDES -I$KOKKOS_DIR/include" + libmesh_optional_LIBS="$libmesh_optional_LIBS -L$KOKKOS_DIR/lib -lkokkoscore" + + dnl Only auto-detect if KOKKOS_CXX was not pre-set by the caller + AS_IF([test "x$KOKKOS_CXX" = "x"], + [ + KOKKOS_CFG="$KOKKOS_DIR/include/KokkosCore_config.h" + + dnl Auto-detect backend + AS_IF([test "x$KOKKOS_BACKEND" = "xauto"], + [ + AS_IF([test -r "$KOKKOS_CFG"], + [ + AS_IF([grep -q 'KOKKOS_ENABLE_CUDA' "$KOKKOS_CFG"], + [KOKKOS_BACKEND=cuda], + [AS_IF([grep -q 'KOKKOS_ENABLE_HIP' "$KOKKOS_CFG"], + [KOKKOS_BACKEND=hip], + [AS_IF([grep -q 'KOKKOS_ENABLE_SYCL' "$KOKKOS_CFG"], + [KOKKOS_BACKEND=sycl], + [AS_IF([grep -q 'KOKKOS_ENABLE_OPENMP' "$KOKKOS_CFG"], + [KOKKOS_BACKEND=openmp], + [KOKKOS_BACKEND=serial])])])]) + ], + [KOKKOS_BACKEND=serial]) + ]) + + AC_MSG_RESULT([Kokkos backend: $KOKKOS_BACKEND]) + + dnl Check if Kokkos was built with OpenMP + have_kokkos_openmp=no + AS_IF([test -r "$KOKKOS_CFG"], + [AS_IF([grep -q 'KOKKOS_ENABLE_OPENMP' "$KOKKOS_CFG"], + [have_kokkos_openmp=yes])]) + + case "$KOKKOS_BACKEND" in + cuda) + AC_PATH_PROG([NVCC],[nvcc],[no],[$PATH]) + AS_IF([test "x$NVCC" = "xno"], + [AC_MSG_ERROR([nvcc not found but Kokkos CUDA backend requested])]) + KOKKOS_CXX="$NVCC" + KOKKOS_CXXFLAGS="--forward-unknown-to-host-compiler --extended-lambda --disable-warnings -x cu -ccbin $CXX" + AS_IF([test "x$have_kokkos_openmp" = "xyes"], + [KOKKOS_CXXFLAGS="$KOKKOS_CXXFLAGS -fopenmp"]) + KOKKOS_LDFLAGS="--forward-unknown-to-host-compiler -L$KOKKOS_DIR/lib" + ;; + hip) + AC_PATH_PROG([HIPCC],[hipcc],[no],[$PATH]) + AS_IF([test "x$HIPCC" = "xno"], + [AC_MSG_ERROR([hipcc not found but Kokkos HIP backend requested])]) + KOKKOS_CXX="$HIPCC" + ;; + sycl) + AC_PATH_PROG([ICPX],[icpx],[no],[$PATH]) + AS_IF([test "x$ICPX" = "xno"], + [AC_MSG_ERROR([icpx not found but Kokkos SYCL backend requested])]) + KOKKOS_CXX="$ICPX" + KOKKOS_CXXFLAGS="-fsycl" + ;; + openmp) + KOKKOS_CXX="${CXX}" + KOKKOS_CXXFLAGS="-fopenmp -x c++" + ;; + serial|*) + KOKKOS_CXX="${CXX}" + KOKKOS_CXXFLAGS="-x c++" + ;; + esac + ], + [AC_MSG_RESULT([Using caller-provided KOKKOS_CXX=$KOKKOS_CXX])]) + + dnl Set defaults for any variables not provided by caller or auto-detect + KOKKOS_CPPFLAGS="${KOKKOS_CPPFLAGS:--DLIBMESH_KOKKOS_COMPILATION -I$KOKKOS_DIR/include}" + KOKKOS_LDFLAGS="${KOKKOS_LDFLAGS:--L$KOKKOS_DIR/lib}" + KOKKOS_LIBS="${KOKKOS_LIBS:--lkokkoscore}" + + AC_DEFINE([HAVE_KOKKOS], [1], + [Define if Kokkos support is enabled in libMesh]) + AC_MSG_RESULT(<<< Configuring library with Kokkos support >>>) + ], + [ + AC_MSG_WARN([Kokkos not found at $KOKKOS_DIR -- disabling Kokkos FE support]) + enablekokkos=no + ]) + ], + [enablekokkos=no]) + +AC_SUBST([KOKKOS_CXX]) +AC_SUBST([KOKKOS_CPPFLAGS]) +AC_SUBST([KOKKOS_CXXFLAGS]) +AC_SUBST([KOKKOS_LDFLAGS]) +AC_SUBST([KOKKOS_LIBS]) +AM_CONDITIONAL(LIBMESH_ENABLE_KOKKOS, test x$enablekokkos = xyes) +# ------------------------------------------------------------- + + + AS_IF([test "$enableoptional" != no], [ AC_MSG_RESULT(----------------------------------------------) diff --git a/src/quadrature/quadrature_gauss_1D.C b/src/quadrature/quadrature_gauss_1D.C index 0e72fc7c8a..a0371c99a0 100644 --- a/src/quadrature/quadrature_gauss_1D.C +++ b/src/quadrature/quadrature_gauss_1D.C @@ -21,144 +21,48 @@ // Local includes #include "libmesh/quadrature_gauss.h" +#include "libmesh/quadrature_gauss_data.h" namespace libMesh { - - -void QGauss::init_1D() +namespace { - //---------------------------------------------------------------------- - // 1D quadrature rules - switch(get_order()) - { - case CONSTANT: - case FIRST: - { - _points.resize (1); - _weights.resize(1); - - _points[0](0) = 0.; - - _weights[0] = 2.; - return; - } - case SECOND: - case THIRD: - { - _points.resize (2); - _weights.resize(2); - - _points[0](0) = -std::sqrt(Real(3))/3; - _points[1] = -_points[0]; - - _weights[0] = 1.; - _weights[1] = _weights[0]; - - return; - } - case FOURTH: - case FIFTH: - { - _points.resize (3); - _weights.resize(3); - - _points[ 0](0) = -7.7459666924148337703585307995648e-01_R; - _points[ 1](0) = 0.; - _points[ 2] = -_points[0]; - - _weights[ 0] = Real(5)/9; - _weights[ 1] = Real(8)/9; - _weights[ 2] = _weights[0]; - - return; - } - case SIXTH: - case SEVENTH: - { - _points.resize (4); - _weights.resize(4); - - _points[ 0](0) = -8.6113631159405257522394648889281e-01_R; - _points[ 1](0) = -3.3998104358485626480266575910324e-01_R; - _points[ 2] = -_points[1]; - _points[ 3] = -_points[0]; +void +load_shared_line_rule(unsigned int n_points, + std::vector & points, + std::vector & weights) +{ + points.resize(n_points); + weights.resize(n_points); - _weights[ 0] = 3.4785484513745385737306394922200e-01_R; - _weights[ 1] = 6.5214515486254614262693605077800e-01_R; - _weights[ 2] = _weights[1]; - _weights[ 3] = _weights[0]; + for (unsigned int i = 0; i != n_points; ++i) + { + points[i](0) = gauss_rule_data::gauss_legendre_point(n_points, i); + weights[i] = gauss_rule_data::gauss_legendre_weight(n_points, i); + } +} - return; - } - case EIGHTH: - case NINTH: - { - _points.resize (5); - _weights.resize(5); +} // anonymous namespace - _points[ 0](0) = -9.0617984593866399279762687829939e-01_R; - _points[ 1](0) = -5.3846931010568309103631442070021e-01_R; - _points[ 2](0) = 0.; - _points[ 3] = -_points[1]; - _points[ 4] = -_points[0]; - _weights[ 0] = 2.3692688505618908751426404071992e-01_R; - _weights[ 1] = 4.7862867049936646804129151483564e-01_R; - _weights[ 2] = 5.6888888888888888888888888888889e-01_R; - _weights[ 3] = _weights[1]; - _weights[ 4] = _weights[0]; - return; - } - case TENTH: - case ELEVENTH: - { - _points.resize (6); - _weights.resize(6); - - _points[ 0](0) = -9.3246951420315202781230155449399e-01_R; - _points[ 1](0) = -6.6120938646626451366139959501991e-01_R; - _points[ 2](0) = -2.3861918608319690863050172168071e-01_R; - _points[ 3] = -_points[2]; - _points[ 4] = -_points[1]; - _points[ 5] = -_points[0]; - - _weights[ 0] = 1.7132449237917034504029614217273e-01_R; - _weights[ 1] = 3.6076157304813860756983351383772e-01_R; - _weights[ 2] = 4.6791393457269104738987034398955e-01_R; - _weights[ 3] = _weights[2]; - _weights[ 4] = _weights[1]; - _weights[ 5] = _weights[0]; +void QGauss::init_1D() +{ + //---------------------------------------------------------------------- + // 1D quadrature rules + if (get_order() <= THIRTEENTH) + { + const unsigned int n_points = + gauss_rule_data::gauss_legendre_n_points(static_cast(get_order())); - return; - } - case TWELFTH: - case THIRTEENTH: - { - _points.resize (7); - _weights.resize(7); - - _points[ 0](0) = -9.4910791234275852452618968404785e-01_R; - _points[ 1](0) = -7.4153118559939443986386477328079e-01_R; - _points[ 2](0) = -4.0584515137739716690660641207696e-01_R; - _points[ 3](0) = 0.; - _points[ 4] = -_points[2]; - _points[ 5] = -_points[1]; - _points[ 6] = -_points[0]; - - _weights[ 0] = 1.2948496616886969327061143267908e-01_R; - _weights[ 1] = 2.7970539148927666790146777142378e-01_R; - _weights[ 2] = 3.8183005050511894495036977548898e-01_R; - _weights[ 3] = 4.1795918367346938775510204081633e-01_R; - _weights[ 4] = _weights[2]; - _weights[ 5] = _weights[1]; - _weights[ 6] = _weights[0]; + load_shared_line_rule(n_points, _points, _weights); + return; + } - return; - } + switch(get_order()) + { case FOURTEENTH: case FIFTEENTH: { diff --git a/src/quadrature/quadrature_gauss_2D.C b/src/quadrature/quadrature_gauss_2D.C index 06e30bff52..9ffd62d90d 100644 --- a/src/quadrature/quadrature_gauss_2D.C +++ b/src/quadrature/quadrature_gauss_2D.C @@ -20,6 +20,7 @@ // Local includes #include "libmesh/quadrature_gauss.h" #include "libmesh/quadrature_conical.h" +#include "libmesh/quadrature_gauss_data.h" #include "libmesh/enum_to_string.h" #include "libmesh/face_c0polygon.h" @@ -27,6 +28,29 @@ namespace libMesh { +namespace +{ + +void +load_shared_tri_rule(unsigned int order, + std::vector & points, + std::vector & weights) +{ + const unsigned int n_points = gauss_rule_data::tri_n_points(order); + + points.resize(n_points); + weights.resize(n_points); + + for (unsigned int qp = 0; qp != n_points; ++qp) + { + const auto pt = gauss_rule_data::tri_point(order, qp); + points[qp] = Point(pt.x, pt.y); + weights[qp] = gauss_rule_data::tri_weight(order, qp); + } +} + +} // anonymous namespace + void QGauss::init_2D() { @@ -76,330 +100,14 @@ void QGauss::init_2D() case TRI6: case TRI7: { - switch(get_order()) + if (get_order() <= SEVENTH) { - case CONSTANT: - case FIRST: - { - // Exact for linears - _points.resize(1); - _weights.resize(1); - - _points[0](0) = Real(1)/3; - _points[0](1) = Real(1)/3; - - _weights[0] = 0.5; - - return; - } - case SECOND: - { - // Exact for quadratics - _points.resize(3); - _weights.resize(3); - - // Alternate rule with points on ref. elt. boundaries. - // Not ideal for problems with material coefficient discontinuities - // aligned along element boundaries. - // _points[0](0) = .5; - // _points[0](1) = .5; - // _points[1](0) = 0.; - // _points[1](1) = .5; - // _points[2](0) = .5; - // _points[2](1) = .0; - - _points[0](0) = Real(2)/3; - _points[0](1) = Real(1)/6; - - _points[1](0) = Real(1)/6; - _points[1](1) = Real(2)/3; - - _points[2](0) = Real(1)/6; - _points[2](1) = Real(1)/6; - - - _weights[0] = Real(1)/6; - _weights[1] = Real(1)/6; - _weights[2] = Real(1)/6; - - return; - } - case THIRD: - { - // Exact for cubics - _points.resize(4); - _weights.resize(4); - - // This rule is formed from a tensor product of - // appropriately-scaled Gauss and Jacobi rules. (See - // also the QConical quadrature class, this is a - // hard-coded version of one of those rules.) For high - // orders these rules generally have too many points, - // but at extremely low order they are competitive and - // have the additional benefit of having all positive - // weights. - _points[0](0) = 1.5505102572168219018027159252941e-01_R; - _points[0](1) = 1.7855872826361642311703513337422e-01_R; - _points[1](0) = 6.4494897427831780981972840747059e-01_R; - _points[1](1) = 7.5031110222608118177475598324603e-02_R; - _points[2](0) = 1.5505102572168219018027159252941e-01_R; - _points[2](1) = 6.6639024601470138670269327409637e-01_R; - _points[3](0) = 6.4494897427831780981972840747059e-01_R; - _points[3](1) = 2.8001991549907407200279599420481e-01_R; - - _weights[0] = 1.5902069087198858469718450103758e-01_R; - _weights[1] = 9.0979309128011415302815498962418e-02_R; - _weights[2] = 1.5902069087198858469718450103758e-01_R; - _weights[3] = 9.0979309128011415302815498962418e-02_R; - - return; - - - // The following third-order rule is quite commonly cited - // in the literature and most likely works fine. However, - // we generally prefer a rule with all positive weights - // and an equal number of points, when available. - // - // (allow_rules_with_negative_weights) - // { - // // Exact for cubics - // _points.resize(4); - // _weights.resize(4); - // - // _points[0](0) = .33333333333333333333333333333333; - // _points[0](1) = .33333333333333333333333333333333; - // - // _points[1](0) = .2; - // _points[1](1) = .6; - // - // _points[2](0) = .2; - // _points[2](1) = .2; - // - // _points[3](0) = .6; - // _points[3](1) = .2; - // - // - // _weights[0] = -27./96.; - // _weights[1] = 25./96.; - // _weights[2] = 25./96.; - // _weights[3] = 25./96.; - // - // return; - // } // end if (allow_rules_with_negative_weights) - // Note: if !allow_rules_with_negative_weights, fall through to next case. - } - - - - // A degree 4 rule with six points. This rule can be found in many places - // including: - // - // J.N. Lyness and D. Jespersen, Moderate degree symmetric - // quadrature rules for the triangle, J. Inst. Math. Appl. 15 (1975), - // 19--32. - // - // We used the code in: - // L. Zhang, T. Cui, and H. Liu. "A set of symmetric quadrature rules - // on triangles and tetrahedra" Journal of Computational Mathematics, - // v. 27, no. 1, 2009, pp. 89-96. - // to generate additional precision. - case FOURTH: - { - const unsigned int n_wts = 2; - const Real wts[n_wts] = - { - 1.1169079483900573284750350421656140e-01_R, - 5.4975871827660933819163162450105264e-02_R - }; - - const Real a[n_wts] = - { - 4.4594849091596488631832925388305199e-01_R, - 9.1576213509770743459571463402201508e-02_R - }; - - const Real b[n_wts] = {0., 0.}; // not used - const unsigned int permutation_ids[n_wts] = {3, 3}; - - dunavant_rule2(wts, a, b, permutation_ids, n_wts); // 6 total points - - return; - } - - - - // Exact for quintics - // Can be found in "Quadrature on Simplices of Arbitrary - // Dimension" by Walkington. - case FIFTH: - { - const unsigned int n_wts = 3; - const Real wts[n_wts] = - { - Real(9)/80, // ~0.1125 - Real(31)/480 + std::sqrt(Real(15))/2400, // ~0.06619707639 - Real(31)/480 - std::sqrt(Real(15))/2400 // ~0.06296959027 - }; - - const Real a[n_wts] = - { - 0., // 'a' parameter not used for origin permutation - Real(2)/7 + std::sqrt(Real(15))/21, // ~0.4701420641 - Real(2)/7 - std::sqrt(Real(15))/21 // ~0.1012865073 - }; - - const Real b[n_wts] = {0., 0., 0.}; // not used - const unsigned int permutation_ids[n_wts] = {1, 3, 3}; - - dunavant_rule2(wts, a, b, permutation_ids, n_wts); // 7 total points - - return; - } - - - - // A degree 6 rule with 12 points. This rule can be found in many places - // including: - // - // J.N. Lyness and D. Jespersen, Moderate degree symmetric - // quadrature rules for the triangle, J. Inst. Math. Appl. 15 (1975), - // 19--32. - // - // We used the code in: - // L. Zhang, T. Cui, and H. Liu. "A set of symmetric quadrature rules - // on triangles and tetrahedra" Journal of Computational Mathematics, - // v. 27, no. 1, 2009, pp. 89-96. - // to generate additional precision. - // - // Note that the following 7th-order Ro3-invariant rule also has only 12 points, - // which technically makes it the superior rule. This one is here for completeness. - case SIXTH: - { - const unsigned int n_wts = 3; - const Real wts[n_wts] = - { - 5.8393137863189683012644805692789721e-02_R, - 2.5422453185103408460468404553434492e-02_R, - 4.1425537809186787596776728210221227e-02_R - }; - - const Real a[n_wts] = - { - 2.4928674517091042129163855310701908e-01_R, - 6.3089014491502228340331602870819157e-02_R, - 3.1035245103378440541660773395655215e-01_R - }; - - const Real b[n_wts] = - { - 0., - 0., - 6.3650249912139864723014259441204970e-01_R - }; - - const unsigned int permutation_ids[n_wts] = {3, 3, 6}; // 12 total points - - dunavant_rule2(wts, a, b, permutation_ids, n_wts); - - return; - } - - - // A degree 7 rule with 12 points. This rule can be found in: - // - // K. Gatermann, The construction of symmetric cubature - // formulas for the square and the triangle, Computing 40 - // (1988), 229--240. - // - // This rule, which is provably minimal in the number of - // integration points, is said to be 'Ro3 invariant' which - // means that a given set of barycentric coordinates - // (z1,z2,z3) implies the quadrature points (z1,z2), - // (z3,z1), (z2,z3) which are formed by taking the first - // two entries in cyclic permutations of the barycentric - // point. Barycentric coordinates are related in the - // sense that: z3 = 1 - z1 - z2. - // - // The 12-point sixth-order rule for triangles given in - // Flaherty's (http://www.cs.rpi.edu/~flaherje/FEM/fem6.ps) - // lecture notes has been removed in favor of this rule - // which is higher-order (for the same number of - // quadrature points) and has a few more digits of - // precision in the points and weights. Some 10-point - // degree 6 rules exist for the triangle but they have - // quadrature points outside the region of integration. - case SEVENTH: - { - _points.resize (12); - _weights.resize(12); - - const unsigned int nrows=4; - - // In each of the rows below, the first two entries are (z1, z2) which imply - // z3. The third entry is the weight for each of the points in the cyclic permutation. - // The original publication tabulated about 16 decimal digits for each point and weight - // parameter. The additional digits shown here were obtained using a code in the - // mp-quadrature library, https://github.com/jwpeterson/mp-quadrature - const Real rule_data[nrows][3] = { - {6.2382265094402118173683000996350e-02_R, 6.7517867073916085442557131050869e-02_R, 2.6517028157436251428754180460739e-02_R}, // group A - {5.5225456656926611737479190275645e-02_R, 3.2150249385198182266630784919920e-01_R, 4.3881408714446055036769903139288e-02_R}, // group B - {3.4324302945097146469630642483938e-02_R, 6.6094919618673565761198031019780e-01_R, 2.8775042784981585738445496900219e-02_R}, // group C - {5.1584233435359177925746338682643e-01_R, 2.7771616697639178256958187139372e-01_R, 6.7493187009802774462697086166421e-02_R} // group D - }; - - for (unsigned int i=0, offset=0; i(get_order()), _points, _weights); + return; + } + switch(get_order()) + { // Another Dunavant rule. This one has all positive weights. This rule has // 16 points while a comparable conical product rule would have 5*5=25. // diff --git a/src/quadrature/quadrature_gauss_3D.C b/src/quadrature/quadrature_gauss_3D.C index e9986c216c..dadb78adf7 100644 --- a/src/quadrature/quadrature_gauss_3D.C +++ b/src/quadrature/quadrature_gauss_3D.C @@ -20,6 +20,7 @@ // Local includes #include "libmesh/quadrature_gauss.h" #include "libmesh/quadrature_conical.h" +#include "libmesh/quadrature_gauss_data.h" #include "libmesh/quadrature_gm.h" #include "libmesh/enum_to_string.h" #include "libmesh/cell_c0polyhedron.h" @@ -27,6 +28,29 @@ namespace libMesh { +namespace +{ + +void +load_shared_tet_rule(unsigned int order, + std::vector & points, + std::vector & weights) +{ + const unsigned int n_points = gauss_rule_data::tet_n_points(order); + + points.resize(n_points); + weights.resize(n_points); + + for (unsigned int qp = 0; qp != n_points; ++qp) + { + const auto pt = gauss_rule_data::tet_point(order, qp); + points[qp] = Point(pt.x, pt.y, pt.z); + weights[qp] = gauss_rule_data::tet_weight(order, qp); + } +} + +} // anonymous namespace + void QGauss::init_3D() { #if LIBMESH_DIM == 3 @@ -56,66 +80,24 @@ void QGauss::init_3D() case TET10: case TET14: { - switch(get_order()) - { - // Taken from pg. 222 of "The finite element method," vol. 1 - // ed. 5 by Zienkiewicz & Taylor - case CONSTANT: - case FIRST: - { - // Exact for linears - _points.resize(1); - _weights.resize(1); - - - _points[0](0) = .25; - _points[0](1) = .25; - _points[0](2) = .25; - - _weights[0] = Real(1)/6; - - return; - } - case SECOND: - { - // Exact for quadratics - _points.resize(4); - _weights.resize(4); - - - // Can't be constexpr with my version of Boost quad - // precision - const Real b = 0.25*(1-std::sqrt(Real(5))/5); - const Real a = 1-3*b; - - _points[0](0) = a; - _points[0](1) = b; - _points[0](2) = b; - - _points[1](0) = b; - _points[1](1) = a; - _points[1](2) = b; - - _points[2](0) = b; - _points[2](1) = b; - _points[2](2) = a; - - _points[3](0) = b; - _points[3](1) = b; - _points[3](2) = b; - - - - _weights[0] = Real(1)/24; - _weights[1] = _weights[0]; - _weights[2] = _weights[0]; - _weights[3] = _weights[0]; - - return; - } + const auto order = get_order(); + if (order == FOURTH && !allow_rules_with_negative_weights) + { + load_shared_tet_rule(static_cast(FIFTH), _points, _weights); + return; + } + if (order == CONSTANT || order == FIRST || order == SECOND || + order == FIFTH || order == SIXTH || + ((order == THIRD || order == FOURTH) && allow_rules_with_negative_weights)) + { + load_shared_tet_rule(static_cast(order), _points, _weights); + return; + } + switch(order) + { // Can be found in the class notes // http://www.cs.rpi.edu/~flaherje/FEM/fem6.ps // by Flaherty. @@ -129,291 +111,15 @@ void QGauss::init_3D() // on the ref. elt. boundary, making it less suitable for FEM calculations. case THIRD: { - if (allow_rules_with_negative_weights) - { - _points.resize(5); - _weights.resize(5); - - - _points[0](0) = .25; - _points[0](1) = .25; - _points[0](2) = .25; - - _points[1](0) = .5; - _points[1](1) = Real(1)/6; - _points[1](2) = Real(1)/6; - - _points[2](0) = Real(1)/6; - _points[2](1) = .5; - _points[2](2) = Real(1)/6; - - _points[3](0) = Real(1)/6; - _points[3](1) = Real(1)/6; - _points[3](2) = .5; - - _points[4](0) = Real(1)/6; - _points[4](1) = Real(1)/6; - _points[4](2) = Real(1)/6; - - - _weights[0] = Real(-2)/15; - _weights[1] = .075; - _weights[2] = _weights[1]; - _weights[3] = _weights[1]; - _weights[4] = _weights[1]; - - return; - } // end if (allow_rules_with_negative_weights) - else - { - // If a rule with positive weights is required, the 2x2x2 conical - // product rule is third-order accurate and has less points than - // the next-available positive-weight rule at FIFTH order. - QConical conical_rule(3, _order); - conical_rule.init(*this); - - // Swap points and weights with the about-to-be destroyed rule. - _points.swap (conical_rule.get_points() ); - _weights.swap(conical_rule.get_weights()); - - return; - } - // Note: if !allow_rules_with_negative_weights, fall through to next case. - } - - - - // Originally a Keast rule, - // Patrick Keast, - // Moderate Degree Tetrahedral Quadrature Formulas, - // Computer Methods in Applied Mechanics and Engineering, - // Volume 55, Number 3, May 1986, pages 339-348. - // - // Can also be found the class notes - // http://www.cs.rpi.edu/~flaherje/FEM/fem6.ps - // by Flaherty. - // - // Caution: this rule has a negative weight and may be - // unsuitable for some problems. - case FOURTH: - { - if (allow_rules_with_negative_weights) - { - _points.resize(11); - _weights.resize(11); - - // The raw data for the quadrature rule. - const Real rule_data[3][4] = { - {0.250000000000000000e+00_R, 0._R, 0._R, -0.131555555555555556e-01_R}, // 1 - {0.785714285714285714e+00_R, 0.714285714285714285e-01_R, 0._R, 0.762222222222222222e-02_R}, // 4 - {0.399403576166799219e+00_R, 0._R, 0.100596423833200785e+00_R, 0.248888888888888889e-01_R} // 6 - }; - - - // Now call the keast routine to generate _points and _weights - keast_rule(rule_data, 3); - - return; - } // end if (allow_rules_with_negative_weights) - // Note: if !allow_rules_with_negative_weights, fall through to next case. - } - - libmesh_fallthrough(); - - - // Walkington's fifth-order 14-point rule from - // "Quadrature on Simplices of Arbitrary Dimension" - // - // We originally had a Keast rule here, but this rule had - // more points than an equivalent rule by Walkington and - // also contained points on the boundary of the ref. elt, - // making it less suitable for FEM calculations. - case FIFTH: - { - _points.resize(14); - _weights.resize(14); - - // permutations of these points and suitably-modified versions of - // these points are the quadrature point locations - const Real a[3] = {0.31088591926330060980_R, // a1 from the paper - 0.092735250310891226402_R, // a2 from the paper - 0.045503704125649649492_R}; // a3 from the paper - - // weights. a[] and wt[] are the only floating-point inputs required - // for this rule. - const Real wt[3] = {0.018781320953002641800_R, // w1 from the paper - 0.012248840519393658257_R, // w2 from the paper - 0.0070910034628469110730_R}; // w3 from the paper - - // The first two sets of 4 points are formed in a similar manner - for (unsigned int i=0; i<2; ++i) - { - // Where we will insert values into _points and _weights - const unsigned int offset=4*i; - - // Stuff points and weights values into their arrays - const Real b = 1. - 3.*a[i]; - - // Here are the permutations. Order of these is not important, - // all have the same weight - _points[offset + 0] = Point(a[i], a[i], a[i]); - _points[offset + 1] = Point(a[i], b, a[i]); - _points[offset + 2] = Point( b, a[i], a[i]); - _points[offset + 3] = Point(a[i], a[i], b); - - // These 4 points all have the same weights - for (unsigned int j=0; j<4; ++j) - _weights[offset + j] = wt[i]; - } // end for - - - { - // The third set contains 6 points and is formed a little differently - const unsigned int offset = 8; - const Real b = 0.5*(1. - 2.*a[2]); - - // Here are the permutations. Order of these is not important, - // all have the same weight - _points[offset + 0] = Point(b , b, a[2]); - _points[offset + 1] = Point(b , a[2], a[2]); - _points[offset + 2] = Point(a[2], a[2], b); - _points[offset + 3] = Point(a[2], b, a[2]); - _points[offset + 4] = Point( b, a[2], b); - _points[offset + 5] = Point(a[2], b, b); - - // These 6 points all have the same weights - for (unsigned int j=0; j<6; ++j) - _weights[offset + j] = wt[2]; - } - - - // Original rule by Keast, unsuitable because it has points on the - // reference element boundary! - // _points.resize(15); - // _weights.resize(15); - - // _points[0](0) = 0.25; - // _points[0](1) = 0.25; - // _points[0](2) = 0.25; - - // { - // const Real a = 0.; - // const Real b = Real(1)/3; - - // _points[1](0) = a; - // _points[1](1) = b; - // _points[1](2) = b; - - // _points[2](0) = b; - // _points[2](1) = a; - // _points[2](2) = b; - - // _points[3](0) = b; - // _points[3](1) = b; - // _points[3](2) = a; - - // _points[4](0) = b; - // _points[4](1) = b; - // _points[4](2) = b; - // } - // { - // const Real a = Real(8)/11; - // const Real b = Real(1)/11; - - // _points[5](0) = a; - // _points[5](1) = b; - // _points[5](2) = b; - - // _points[6](0) = b; - // _points[6](1) = a; - // _points[6](2) = b; - - // _points[7](0) = b; - // _points[7](1) = b; - // _points[7](2) = a; - - // _points[8](0) = b; - // _points[8](1) = b; - // _points[8](2) = b; - // } - // { - // const Real a = 0.066550153573664; - // const Real b = 0.433449846426336; - - // _points[9](0) = b; - // _points[9](1) = a; - // _points[9](2) = a; - - // _points[10](0) = a; - // _points[10](1) = a; - // _points[10](2) = b; - - // _points[11](0) = a; - // _points[11](1) = b; - // _points[11](2) = b; - - // _points[12](0) = b; - // _points[12](1) = a; - // _points[12](2) = b; - - // _points[13](0) = b; - // _points[13](1) = b; - // _points[13](2) = a; - - // _points[14](0) = a; - // _points[14](1) = b; - // _points[14](2) = a; - // } - - // _weights[0] = 0.030283678097089; - // _weights[1] = 0.006026785714286; - // _weights[2] = _weights[1]; - // _weights[3] = _weights[1]; - // _weights[4] = _weights[1]; - // _weights[5] = 0.011645249086029; - // _weights[6] = _weights[5]; - // _weights[7] = _weights[5]; - // _weights[8] = _weights[5]; - // _weights[9] = 0.010949141561386; - // _weights[10] = _weights[9]; - // _weights[11] = _weights[9]; - // _weights[12] = _weights[9]; - // _weights[13] = _weights[9]; - // _weights[14] = _weights[9]; - - return; - } - - - - - // This rule is originally from Keast: - // Patrick Keast, - // Moderate Degree Tetrahedral Quadrature Formulas, - // Computer Methods in Applied Mechanics and Engineering, - // Volume 55, Number 3, May 1986, pages 339-348. - // - // It is accurate on 6th-degree polynomials and has 24 points - // vs. 64 for the comparable conical product rule. - // - // Values copied 24th June 2008 from: - // http://people.scs.fsu.edu/~burkardt/f_src/keast/keast.f90 - case SIXTH: - { - _points.resize (24); - _weights.resize(24); - - // The raw data for the quadrature rule. - const Real rule_data[4][4] = { - {0.356191386222544953e+00_R , 0.214602871259151684e+00_R , 0._R, 0.00665379170969464506e+00_R}, // 4 - {0.877978124396165982e+00_R , 0.0406739585346113397e+00_R, 0._R, 0.00167953517588677620e+00_R}, // 4 - {0.0329863295731730594e+00_R, 0.322337890142275646e+00_R , 0._R, 0.00922619692394239843e+00_R}, // 4 - {0.0636610018750175299e+00_R, 0.269672331458315867e+00_R , 0.603005664791649076e+00_R, 0.00803571428571428248e+00_R} // 12 - }; - - - // Now call the keast routine to generate _points and _weights - keast_rule(rule_data, 4); + // If a rule with positive weights is required, the 2x2x2 conical + // product rule is third-order accurate and has less points than + // the next-available positive-weight rule at FIFTH order. + QConical conical_rule(3, _order); + conical_rule.init(*this); + + // Swap points and weights with the about-to-be destroyed rule. + _points.swap (conical_rule.get_points() ); + _weights.swap(conical_rule.get_weights()); return; } diff --git a/tests/Makefile.am b/tests/Makefile.am index bb12f42483..26890185ac 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -247,7 +247,38 @@ if LIBMESH_ENABLE_FPARSER fparser/autodiff.C endif +if LIBMESH_ENABLE_KOKKOS + AM_CPPFLAGS += $(KOKKOS_CPPFLAGS) -I$(top_srcdir)/include +endif + check_PROGRAMS = # empty, append below +TESTS = + +if LIBMESH_ENABLE_KOKKOS + check_PROGRAMS += kokkos_fe_types_unit kokkos_fe_shape_unit + TESTS += kokkos_fe_types_unit kokkos_fe_shape_unit + + kokkos_fe_types_unit_SOURCES = fe/kokkos_fe_types_test.K + kokkos_fe_types_unit_CPPFLAGS = $(AM_CPPFLAGS) $(KOKKOS_CPPFLAGS) + kokkos_fe_types_unit_CXXFLAGS = $(AM_CXXFLAGS) $(KOKKOS_CXXFLAGS) + kokkos_fe_types_unit_LDFLAGS = $(AM_LDFLAGS) $(KOKKOS_LDFLAGS) + kokkos_fe_types_unit_LDADD = $(top_builddir)/libmesh_opt.la $(KOKKOS_LIBS) $(libmesh_optional_LIBS) + + kokkos_fe_shape_unit_SOURCES = fe/kokkos_fe_shape_test.K + kokkos_fe_shape_unit_CPPFLAGS = $(AM_CPPFLAGS) $(KOKKOS_CPPFLAGS) + kokkos_fe_shape_unit_CXXFLAGS = $(AM_CXXFLAGS) $(KOKKOS_CXXFLAGS) + kokkos_fe_shape_unit_LDFLAGS = $(AM_LDFLAGS) $(KOKKOS_LDFLAGS) + kokkos_fe_shape_unit_LDADD = $(top_builddir)/libmesh_opt.la $(KOKKOS_LIBS) $(libmesh_optional_LIBS) + + check_PROGRAMS += kokkos_quadrature_unit + TESTS += kokkos_quadrature_unit + + kokkos_quadrature_unit_SOURCES = fe/kokkos_quadrature_test.K + kokkos_quadrature_unit_CPPFLAGS = $(AM_CPPFLAGS) $(KOKKOS_CPPFLAGS) + kokkos_quadrature_unit_CXXFLAGS = $(AM_CXXFLAGS) $(KOKKOS_CXXFLAGS) + kokkos_quadrature_unit_LDFLAGS = $(AM_LDFLAGS) $(KOKKOS_LDFLAGS) + kokkos_quadrature_unit_LDADD = $(top_builddir)/libmesh_opt.la $(KOKKOS_LIBS) $(libmesh_optional_LIBS) +endif # our GLIBC debugging preprocessor flags seem to potentially conflict # with libcppunit binaries. Some cppunit versions work fine for us, @@ -358,9 +389,31 @@ $(top_builddir)/libmesh_oprof.la: FORCE if LIBMESH_ENABLE_CPPUNIT -TESTS = run_unit_tests.sh +TESTS += run_unit_tests.sh endif +# Compile .K translation units with the Kokkos device compiler. +# $(MPI_INCLUDES) is needed because KOKKOS_CXX may be nvcc/hipcc +# instead of the MPI compiler wrapper, so mpi.h won't be found implicitly. +.K.o: + $(KOKKOS_CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(MPI_INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(KOKKOS_CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(KOKKOS_CXXFLAGS) \ + -c $< -o $@ + +# Custom link rules so the Kokkos compiler drives the final link step. +kokkos_fe_types_unit_LINK = \ + $(LIBTOOL) --tag=CXX --mode=link $(KOKKOS_CXX) \ + $(LDFLAGS) $(kokkos_fe_types_unit_LDFLAGS) -o $@ + +kokkos_fe_shape_unit_LINK = \ + $(LIBTOOL) --tag=CXX --mode=link $(KOKKOS_CXX) \ + $(LDFLAGS) $(kokkos_fe_shape_unit_LDFLAGS) -o $@ + +kokkos_quadrature_unit_LINK = \ + $(LIBTOOL) --tag=CXX --mode=link $(KOKKOS_CXX) \ + $(LDFLAGS) $(kokkos_quadrature_unit_LDFLAGS) -o $@ + CLEANFILES = cube_mesh.xda \ slit_mesh.xda \ slit_solution.xda \ diff --git a/tests/Makefile.in b/tests/Makefile.in index 59ed2e7641..db7d73bb27 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -94,26 +94,32 @@ target_triplet = @target@ @LIBMESH_ENABLE_FPARSER_TRUE@am__append_1 = \ @LIBMESH_ENABLE_FPARSER_TRUE@ fparser/autodiff.C +@LIBMESH_ENABLE_KOKKOS_TRUE@am__append_2 = $(KOKKOS_CPPFLAGS) -I$(top_srcdir)/include check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ - $(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6) + $(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6) \ + $(am__EXEEXT_7) +TESTS = $(am__EXEEXT_1) $(am__append_11) +@LIBMESH_ENABLE_KOKKOS_TRUE@am__append_3 = kokkos_fe_types_unit kokkos_fe_shape_unit +@LIBMESH_ENABLE_KOKKOS_TRUE@am__append_4 = kokkos_fe_types_unit kokkos_fe_shape_unit # our GLIBC debugging preprocessor flags seem to potentially conflict # with libcppunit binaries. Some cppunit versions work fine for us, # others segfault and/or hang. By default we will not run # GLIBCXX-debugging builds with cppunit unless specifically # configured to. -@ACSM_ENABLE_GLIBCXX_DEBUGGING_CPPUNIT_TRUE@@ACSM_ENABLE_GLIBCXX_DEBUGGING_TRUE@@LIBMESH_DBG_MODE_TRUE@@LIBMESH_ENABLE_CPPUNIT_TRUE@am__append_2 = unit_tests-dbg -@ACSM_ENABLE_GLIBCXX_DEBUGGING_FALSE@@LIBMESH_DBG_MODE_TRUE@@LIBMESH_ENABLE_CPPUNIT_TRUE@am__append_3 = unit_tests-dbg -@LIBMESH_DEVEL_MODE_TRUE@@LIBMESH_ENABLE_CPPUNIT_TRUE@am__append_4 = unit_tests-devel -@LIBMESH_ENABLE_CPPUNIT_TRUE@@LIBMESH_PROF_MODE_TRUE@am__append_5 = unit_tests-prof -@LIBMESH_ENABLE_CPPUNIT_TRUE@@LIBMESH_OPROF_MODE_TRUE@am__append_6 = unit_tests-oprof -@LIBMESH_ENABLE_CPPUNIT_TRUE@@LIBMESH_OPT_MODE_TRUE@am__append_7 = unit_tests-opt -@LIBMESH_VPATH_BUILD_TRUE@am__append_8 = .linkstamp +@ACSM_ENABLE_GLIBCXX_DEBUGGING_CPPUNIT_TRUE@@ACSM_ENABLE_GLIBCXX_DEBUGGING_TRUE@@LIBMESH_DBG_MODE_TRUE@@LIBMESH_ENABLE_CPPUNIT_TRUE@am__append_5 = unit_tests-dbg +@ACSM_ENABLE_GLIBCXX_DEBUGGING_FALSE@@LIBMESH_DBG_MODE_TRUE@@LIBMESH_ENABLE_CPPUNIT_TRUE@am__append_6 = unit_tests-dbg +@LIBMESH_DEVEL_MODE_TRUE@@LIBMESH_ENABLE_CPPUNIT_TRUE@am__append_7 = unit_tests-devel +@LIBMESH_ENABLE_CPPUNIT_TRUE@@LIBMESH_PROF_MODE_TRUE@am__append_8 = unit_tests-prof +@LIBMESH_ENABLE_CPPUNIT_TRUE@@LIBMESH_OPROF_MODE_TRUE@am__append_9 = unit_tests-oprof +@LIBMESH_ENABLE_CPPUNIT_TRUE@@LIBMESH_OPT_MODE_TRUE@am__append_10 = unit_tests-opt +@LIBMESH_ENABLE_CPPUNIT_TRUE@am__append_11 = run_unit_tests.sh +@LIBMESH_VPATH_BUILD_TRUE@am__append_12 = .linkstamp ###################################################################### # # Don't leave code coverage outputs lying around -@CODE_COVERAGE_ENABLED_TRUE@am__append_9 = */*.gcda */*.gcno +@CODE_COVERAGE_ENABLED_TRUE@am__append_13 = */*.gcda */*.gcno subdir = tests ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = \ @@ -182,12 +188,32 @@ mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/libmesh_config.h.tmp CONFIG_CLEAN_FILES = run_unit_tests.sh CONFIG_CLEAN_VPATH_FILES = -@ACSM_ENABLE_GLIBCXX_DEBUGGING_CPPUNIT_TRUE@@ACSM_ENABLE_GLIBCXX_DEBUGGING_TRUE@@LIBMESH_DBG_MODE_TRUE@@LIBMESH_ENABLE_CPPUNIT_TRUE@am__EXEEXT_1 = unit_tests-dbg$(EXEEXT) -@ACSM_ENABLE_GLIBCXX_DEBUGGING_FALSE@@LIBMESH_DBG_MODE_TRUE@@LIBMESH_ENABLE_CPPUNIT_TRUE@am__EXEEXT_2 = unit_tests-dbg$(EXEEXT) -@LIBMESH_DEVEL_MODE_TRUE@@LIBMESH_ENABLE_CPPUNIT_TRUE@am__EXEEXT_3 = unit_tests-devel$(EXEEXT) -@LIBMESH_ENABLE_CPPUNIT_TRUE@@LIBMESH_PROF_MODE_TRUE@am__EXEEXT_4 = unit_tests-prof$(EXEEXT) -@LIBMESH_ENABLE_CPPUNIT_TRUE@@LIBMESH_OPROF_MODE_TRUE@am__EXEEXT_5 = unit_tests-oprof$(EXEEXT) -@LIBMESH_ENABLE_CPPUNIT_TRUE@@LIBMESH_OPT_MODE_TRUE@am__EXEEXT_6 = unit_tests-opt$(EXEEXT) +@LIBMESH_ENABLE_KOKKOS_TRUE@am__EXEEXT_1 = \ +@LIBMESH_ENABLE_KOKKOS_TRUE@ kokkos_fe_types_unit$(EXEEXT) \ +@LIBMESH_ENABLE_KOKKOS_TRUE@ kokkos_fe_shape_unit$(EXEEXT) +@ACSM_ENABLE_GLIBCXX_DEBUGGING_CPPUNIT_TRUE@@ACSM_ENABLE_GLIBCXX_DEBUGGING_TRUE@@LIBMESH_DBG_MODE_TRUE@@LIBMESH_ENABLE_CPPUNIT_TRUE@am__EXEEXT_2 = unit_tests-dbg$(EXEEXT) +@ACSM_ENABLE_GLIBCXX_DEBUGGING_FALSE@@LIBMESH_DBG_MODE_TRUE@@LIBMESH_ENABLE_CPPUNIT_TRUE@am__EXEEXT_3 = unit_tests-dbg$(EXEEXT) +@LIBMESH_DEVEL_MODE_TRUE@@LIBMESH_ENABLE_CPPUNIT_TRUE@am__EXEEXT_4 = unit_tests-devel$(EXEEXT) +@LIBMESH_ENABLE_CPPUNIT_TRUE@@LIBMESH_PROF_MODE_TRUE@am__EXEEXT_5 = unit_tests-prof$(EXEEXT) +@LIBMESH_ENABLE_CPPUNIT_TRUE@@LIBMESH_OPROF_MODE_TRUE@am__EXEEXT_6 = unit_tests-oprof$(EXEEXT) +@LIBMESH_ENABLE_CPPUNIT_TRUE@@LIBMESH_OPT_MODE_TRUE@am__EXEEXT_7 = unit_tests-opt$(EXEEXT) +am__kokkos_fe_shape_unit_SOURCES_DIST = fe/kokkos_fe_shape_test.K +am__dirstamp = $(am__leading_dot)dirstamp +@LIBMESH_ENABLE_KOKKOS_TRUE@am_kokkos_fe_shape_unit_OBJECTS = \ +@LIBMESH_ENABLE_KOKKOS_TRUE@ fe/kokkos_fe_shape_test.$(OBJEXT) +kokkos_fe_shape_unit_OBJECTS = $(am_kokkos_fe_shape_unit_OBJECTS) +am__DEPENDENCIES_1 = +am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +@LIBMESH_ENABLE_KOKKOS_TRUE@kokkos_fe_shape_unit_DEPENDENCIES = \ +@LIBMESH_ENABLE_KOKKOS_TRUE@ $(top_builddir)/libmesh_opt.la \ +@LIBMESH_ENABLE_KOKKOS_TRUE@ $(am__DEPENDENCIES_2) +am__kokkos_fe_types_unit_SOURCES_DIST = fe/kokkos_fe_types_test.K +@LIBMESH_ENABLE_KOKKOS_TRUE@am_kokkos_fe_types_unit_OBJECTS = \ +@LIBMESH_ENABLE_KOKKOS_TRUE@ fe/kokkos_fe_types_test.$(OBJEXT) +kokkos_fe_types_unit_OBJECTS = $(am_kokkos_fe_types_unit_OBJECTS) +@LIBMESH_ENABLE_KOKKOS_TRUE@kokkos_fe_types_unit_DEPENDENCIES = \ +@LIBMESH_ENABLE_KOKKOS_TRUE@ $(top_builddir)/libmesh_opt.la \ +@LIBMESH_ENABLE_KOKKOS_TRUE@ $(am__DEPENDENCIES_2) am__unit_tests_dbg_SOURCES_DIST = driver.C libmesh_cppunit.h \ stream_redirector.h test_comm.h base/dof_object_test.h \ base/dof_map_test.C base/default_coupling_test.C \ @@ -262,7 +288,6 @@ am__unit_tests_dbg_SOURCES_DIST = driver.C libmesh_cppunit.h \ utils/parameters_test.C utils/point_locator_test.C \ utils/rb_parameters_test.C utils/transparent_comparator.C \ utils/vectormap_test.C utils/xdr_test.C fparser/autodiff.C -am__dirstamp = $(am__leading_dot)dirstamp @LIBMESH_ENABLE_FPARSER_TRUE@am__objects_1 = fparser/unit_tests_dbg-autodiff.$(OBJEXT) am__objects_2 = unit_tests_dbg-driver.$(OBJEXT) \ base/unit_tests_dbg-dof_map_test.$(OBJEXT) \ @@ -1860,10 +1885,13 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = -SOURCES = $(unit_tests_dbg_SOURCES) $(unit_tests_devel_SOURCES) \ - $(unit_tests_oprof_SOURCES) $(unit_tests_opt_SOURCES) \ - $(unit_tests_prof_SOURCES) -DIST_SOURCES = $(am__unit_tests_dbg_SOURCES_DIST) \ +SOURCES = $(kokkos_fe_shape_unit_SOURCES) \ + $(kokkos_fe_types_unit_SOURCES) $(unit_tests_dbg_SOURCES) \ + $(unit_tests_devel_SOURCES) $(unit_tests_oprof_SOURCES) \ + $(unit_tests_opt_SOURCES) $(unit_tests_prof_SOURCES) +DIST_SOURCES = $(am__kokkos_fe_shape_unit_SOURCES_DIST) \ + $(am__kokkos_fe_types_unit_SOURCES_DIST) \ + $(am__unit_tests_dbg_SOURCES_DIST) \ $(am__unit_tests_devel_SOURCES_DIST) \ $(am__unit_tests_oprof_SOURCES_DIST) \ $(am__unit_tests_opt_SOURCES_DIST) \ @@ -2284,9 +2312,8 @@ AUTOMAKE_OPTIONS = subdir-objects AM_CXXFLAGS = $(libmesh_CXXFLAGS) AM_CFLAGS = $(libmesh_CFLAGS) AM_CPPFLAGS = $(libmesh_optional_INCLUDES) -I$(top_builddir)/include \ - $(libmesh_contrib_INCLUDES) $(CPPUNIT_CFLAGS) \ - -DLIBMESH_IS_UNIT_TESTING - + $(libmesh_contrib_INCLUDES) $(CPPUNIT_CFLAGS) \ + -DLIBMESH_IS_UNIT_TESTING $(am__append_2) AM_LDFLAGS = $(libmesh_LDFLAGS) $(libmesh_contrib_LDFLAGS) unit_tests_sources = driver.C libmesh_cppunit.h stream_redirector.h \ test_comm.h base/dof_object_test.h base/dof_map_test.C \ @@ -2450,6 +2477,16 @@ unit_tests_data = $(data) # Why isn't this working automatically? EXTRA_DIST = $(data) +@LIBMESH_ENABLE_KOKKOS_TRUE@kokkos_fe_types_unit_SOURCES = fe/kokkos_fe_types_test.K +@LIBMESH_ENABLE_KOKKOS_TRUE@kokkos_fe_types_unit_CPPFLAGS = $(AM_CPPFLAGS) $(KOKKOS_CPPFLAGS) +@LIBMESH_ENABLE_KOKKOS_TRUE@kokkos_fe_types_unit_CXXFLAGS = $(AM_CXXFLAGS) $(KOKKOS_CXXFLAGS) +@LIBMESH_ENABLE_KOKKOS_TRUE@kokkos_fe_types_unit_LDFLAGS = $(AM_LDFLAGS) $(KOKKOS_LDFLAGS) +@LIBMESH_ENABLE_KOKKOS_TRUE@kokkos_fe_types_unit_LDADD = $(top_builddir)/libmesh_opt.la $(KOKKOS_LIBS) $(LIBS) +@LIBMESH_ENABLE_KOKKOS_TRUE@kokkos_fe_shape_unit_SOURCES = fe/kokkos_fe_shape_test.K +@LIBMESH_ENABLE_KOKKOS_TRUE@kokkos_fe_shape_unit_CPPFLAGS = $(AM_CPPFLAGS) $(KOKKOS_CPPFLAGS) +@LIBMESH_ENABLE_KOKKOS_TRUE@kokkos_fe_shape_unit_CXXFLAGS = $(AM_CXXFLAGS) $(KOKKOS_CXXFLAGS) +@LIBMESH_ENABLE_KOKKOS_TRUE@kokkos_fe_shape_unit_LDFLAGS = $(AM_LDFLAGS) $(KOKKOS_LDFLAGS) +@LIBMESH_ENABLE_KOKKOS_TRUE@kokkos_fe_shape_unit_LDADD = $(top_builddir)/libmesh_opt.la $(KOKKOS_LIBS) $(LIBS) @LIBMESH_DBG_MODE_TRUE@@LIBMESH_ENABLE_CPPUNIT_TRUE@unit_tests_dbg_SOURCES = $(unit_tests_sources) @LIBMESH_DBG_MODE_TRUE@@LIBMESH_ENABLE_CPPUNIT_TRUE@unit_tests_dbg_CPPFLAGS = $(CPPFLAGS_DBG) $(AM_CPPFLAGS) @LIBMESH_DBG_MODE_TRUE@@LIBMESH_ENABLE_CPPUNIT_TRUE@unit_tests_dbg_CXXFLAGS = $(CXXFLAGS_DBG) @@ -2480,7 +2517,16 @@ EXTRA_DIST = $(data) @LIBMESH_ENABLE_CPPUNIT_TRUE@@LIBMESH_OPT_MODE_TRUE@unit_tests_opt_LDADD = $(top_builddir)/libmesh_opt.la @LIBMESH_ENABLE_CPPUNIT_TRUE@@LIBMESH_OPT_MODE_TRUE@unit_tests_optdir = $(datadir) @LIBMESH_ENABLE_CPPUNIT_TRUE@@LIBMESH_OPT_MODE_TRUE@unit_tests_opt_DATA = $(data) -@LIBMESH_ENABLE_CPPUNIT_TRUE@TESTS = run_unit_tests.sh + +# Custom link rules so the Kokkos compiler drives the final link step. +kokkos_fe_types_unit_LINK = \ + $(LIBTOOL) --tag=CXX --mode=link $(KOKKOS_CXX) \ + $(LDFLAGS) $(kokkos_fe_types_unit_LDFLAGS) -o $@ + +kokkos_fe_shape_unit_LINK = \ + $(LIBTOOL) --tag=CXX --mode=link $(KOKKOS_CXX) \ + $(LDFLAGS) $(kokkos_fe_shape_unit_LDFLAGS) -o $@ + CLEANFILES = cube_mesh.xda slit_mesh.xda slit_solution.xda out.e \ mesh_with_soln.e elemental_from_nodal.e write_elemset_data.e \ write_sideset_data.e write_nodeset_data.e write_edgeset_data.e \ @@ -2514,8 +2560,8 @@ CLEANFILES = cube_mesh.xda slit_mesh.xda slit_solution.xda out.e \ write_exodus_QUADSHELL9.e write_exodus_TET10.e \ write_exodus_TET14.e write_exodus_TET4.e write_exodus_TRI3.e \ write_exodus_TRI6.e write_exodus_TRI7.e \ - write_exodus_TRISHELL3.e smoother.out $(am__append_8) \ - $(am__append_9) + write_exodus_TRISHELL3.e smoother.out $(am__append_12) \ + $(am__append_13) # need to link any data files for VPATH builds @LIBMESH_VPATH_BUILD_TRUE@BUILT_SOURCES = .linkstamp @@ -2523,7 +2569,7 @@ all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: -.SUFFIXES: .C .lo .o .obj +.SUFFIXES: .C .K .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ @@ -2559,6 +2605,24 @@ run_unit_tests.sh: $(top_builddir)/config.status $(srcdir)/run_unit_tests.sh.in clean-checkPROGRAMS: $(am__rm_f) $(check_PROGRAMS) test -z "$(EXEEXT)" || $(am__rm_f) $(check_PROGRAMS:$(EXEEXT)=) +fe/$(am__dirstamp): + @$(MKDIR_P) fe + @: >>fe/$(am__dirstamp) +fe/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) fe/$(DEPDIR) + @: >>fe/$(DEPDIR)/$(am__dirstamp) +fe/kokkos_fe_shape_test.$(OBJEXT): fe/$(am__dirstamp) \ + fe/$(DEPDIR)/$(am__dirstamp) + +kokkos_fe_shape_unit$(EXEEXT): $(kokkos_fe_shape_unit_OBJECTS) $(kokkos_fe_shape_unit_DEPENDENCIES) $(EXTRA_kokkos_fe_shape_unit_DEPENDENCIES) + @rm -f kokkos_fe_shape_unit$(EXEEXT) + $(AM_V_GEN)$(kokkos_fe_shape_unit_LINK) $(kokkos_fe_shape_unit_OBJECTS) $(kokkos_fe_shape_unit_LDADD) $(LIBS) +fe/kokkos_fe_types_test.$(OBJEXT): fe/$(am__dirstamp) \ + fe/$(DEPDIR)/$(am__dirstamp) + +kokkos_fe_types_unit$(EXEEXT): $(kokkos_fe_types_unit_OBJECTS) $(kokkos_fe_types_unit_DEPENDENCIES) $(EXTRA_kokkos_fe_types_unit_DEPENDENCIES) + @rm -f kokkos_fe_types_unit$(EXEEXT) + $(AM_V_GEN)$(kokkos_fe_types_unit_LINK) $(kokkos_fe_types_unit_OBJECTS) $(kokkos_fe_types_unit_LDADD) $(LIBS) base/$(am__dirstamp): @$(MKDIR_P) base @: >>base/$(am__dirstamp) @@ -2579,12 +2643,6 @@ base/unit_tests_dbg-nonmanifold_coupling_test.$(OBJEXT): \ base/$(am__dirstamp) base/$(DEPDIR)/$(am__dirstamp) base/unit_tests_dbg-multi_evaluable_pred_test.$(OBJEXT): \ base/$(am__dirstamp) base/$(DEPDIR)/$(am__dirstamp) -fe/$(am__dirstamp): - @$(MKDIR_P) fe - @: >>fe/$(am__dirstamp) -fe/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) fe/$(DEPDIR) - @: >>fe/$(DEPDIR)/$(am__dirstamp) fe/unit_tests_dbg-fe_bernstein_test.$(OBJEXT): fe/$(am__dirstamp) \ fe/$(DEPDIR)/$(am__dirstamp) fe/unit_tests_dbg-fe_clough_test.$(OBJEXT): fe/$(am__dirstamp) \ @@ -14717,6 +14775,13 @@ $(top_builddir)/libmesh_prof.la: FORCE $(top_builddir)/libmesh_oprof.la: FORCE (cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) libmesh_oprof.la) +# Compile .K translation units with the Kokkos device compiler. +.K.o: + $(KOKKOS_CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(KOKKOS_CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(KOKKOS_CXXFLAGS) \ + -c $< -o $@ + @LIBMESH_VPATH_BUILD_TRUE@.linkstamp: @LIBMESH_VPATH_BUILD_TRUE@ -rm -f solutions && $(LN_S) -f $(srcdir)/solutions . @LIBMESH_VPATH_BUILD_TRUE@ -rm -f meshes && $(LN_S) -f $(srcdir)/meshes . diff --git a/tests/fe/kokkos_fe_shape_test.K b/tests/fe/kokkos_fe_shape_test.K new file mode 100644 index 0000000000..414e033f86 --- /dev/null +++ b/tests/fe/kokkos_fe_shape_test.K @@ -0,0 +1,509 @@ +// GPU kernel tests for libMesh::Kokkos FE shape functions. +// +// Standalone executable (no CppUnit). Uses libMesh::LibMeshInit so that +// QGauss and the host FE / FEMap dispatch are available for reference values. +// +// The test suite covers: +// A. Geometry-map shape parity against the libMesh FE map oracle for the +// 12 implemented LAGRANGE map topologies. +// B. Geometry-map gradient parity against the libMesh FE map oracle for the +// same topologies. +// C. Physics FE parity for exact libMesh LAGRANGE keys that the Kokkos +// evaluator currently supports. +// D. Physics FE gradient parity for the same exact keys. +// +// Unsupported exact LAGRANGE keys are expected to hard-abort in the Kokkos +// path and are therefore intentionally not invoked here. + +#include "libmesh/elem.h" +#include "gpu/kokkos_fe_evaluator.h" +#include "gpu/kokkos_fe_types.h" +#include "gpu/kokkos_scalar_types.h" + +#include "libmesh/fe.h" +#include "libmesh/fe_interface.h" +#include "libmesh/fe_map.h" +#include "libmesh/libmesh.h" +#include "libmesh/quadrature_gauss.h" +#include "libmesh/enum_elem_type.h" +#include "libmesh/enum_order.h" + +// Avoid conflicting complex operators between CUDA and PETSc +#define PETSC_SKIP_CXX_COMPLEX_FIX 1 +#include +#undef __CUDACC_VER__ +#include +#include +#include +#include + +using libMesh::Kokkos::Real; +using libMesh::Kokkos::Real3; + +static constexpr double tol = 1.0e-13; +static constexpr unsigned int quad_order = 4; + +namespace +{ + +struct map_elem_info +{ + libMesh::ElemType topo; + unsigned int dim; + unsigned int n_dofs; + const char * name; +}; + +struct physics_shape_info +{ + libMesh::Kokkos::FEShapeKey key; + unsigned int dim; + unsigned int n_dofs; + const char * name; +}; + +static const map_elem_info map_elems[] = { + { libMesh::EDGE2, 1, 2, "EDGE2" }, + { libMesh::EDGE3, 1, 3, "EDGE3" }, + { libMesh::TRI3, 2, 3, "TRI3" }, + { libMesh::TRI6, 2, 6, "TRI6" }, + { libMesh::QUAD4, 2, 4, "QUAD4" }, + { libMesh::QUAD8, 2, 8, "QUAD8" }, + { libMesh::QUAD9, 2, 9, "QUAD9" }, + { libMesh::TET4, 3, 4, "TET4" }, + { libMesh::TET10, 3, 10, "TET10" }, + { libMesh::HEX8, 3, 8, "HEX8" }, + { libMesh::HEX20, 3, 20, "HEX20" }, + { libMesh::HEX27, 3, 27, "HEX27" }, +}; +static constexpr unsigned int n_map_elems = sizeof(map_elems) / sizeof(map_elems[0]); + +// Only exact libMesh LAGRANGE keys whose evaluator topology is implemented in +// the current Kokkos path are included here. +static const physics_shape_info physics_cases[] = { + { { libMesh::LAGRANGE, libMesh::EDGE2, libMesh::FIRST }, 1, 2, "EDGE2/FIRST" }, + { { libMesh::LAGRANGE, libMesh::EDGE3, libMesh::FIRST }, 1, 2, "EDGE3/FIRST" }, + { { libMesh::LAGRANGE, libMesh::EDGE3, libMesh::SECOND }, 1, 3, "EDGE3/SECOND" }, + { { libMesh::LAGRANGE, libMesh::EDGE4, libMesh::FIRST }, 1, 2, "EDGE4/FIRST" }, + + { { libMesh::LAGRANGE, libMesh::TRI3, libMesh::FIRST }, 2, 3, "TRI3/FIRST" }, + { { libMesh::LAGRANGE, libMesh::TRI6, libMesh::FIRST }, 2, 3, "TRI6/FIRST" }, + { { libMesh::LAGRANGE, libMesh::TRI6, libMesh::SECOND }, 2, 6, "TRI6/SECOND" }, + { { libMesh::LAGRANGE, libMesh::TRI7, libMesh::FIRST }, 2, 3, "TRI7/FIRST" }, + { { libMesh::LAGRANGE, libMesh::TRI7, libMesh::SECOND }, 2, 6, "TRI7/SECOND" }, + + { { libMesh::LAGRANGE, libMesh::QUAD4, libMesh::FIRST }, 2, 4, "QUAD4/FIRST" }, + { { libMesh::LAGRANGE, libMesh::QUAD8, libMesh::FIRST }, 2, 4, "QUAD8/FIRST" }, + { { libMesh::LAGRANGE, libMesh::QUAD8, libMesh::SECOND }, 2, 8, "QUAD8/SECOND" }, + { { libMesh::LAGRANGE, libMesh::QUAD9, libMesh::FIRST }, 2, 4, "QUAD9/FIRST" }, + { { libMesh::LAGRANGE, libMesh::QUAD9, libMesh::SECOND }, 2, 9, "QUAD9/SECOND" }, + + { { libMesh::LAGRANGE, libMesh::TET4, libMesh::FIRST }, 3, 4, "TET4/FIRST" }, + { { libMesh::LAGRANGE, libMesh::TET10, libMesh::FIRST }, 3, 4, "TET10/FIRST" }, + { { libMesh::LAGRANGE, libMesh::TET10, libMesh::SECOND }, 3, 10, "TET10/SECOND" }, + { { libMesh::LAGRANGE, libMesh::TET14, libMesh::FIRST }, 3, 4, "TET14/FIRST" }, + { { libMesh::LAGRANGE, libMesh::TET14, libMesh::SECOND }, 3, 10, "TET14/SECOND" }, + + { { libMesh::LAGRANGE, libMesh::HEX8, libMesh::FIRST }, 3, 8, "HEX8/FIRST" }, + { { libMesh::LAGRANGE, libMesh::HEX20, libMesh::FIRST }, 3, 8, "HEX20/FIRST" }, + { { libMesh::LAGRANGE, libMesh::HEX20, libMesh::SECOND }, 3, 20, "HEX20/SECOND" }, + { { libMesh::LAGRANGE, libMesh::HEX27, libMesh::FIRST }, 3, 8, "HEX27/FIRST" }, + { { libMesh::LAGRANGE, libMesh::HEX27, libMesh::SECOND }, 3, 27, "HEX27/SECOND" }, +}; +static constexpr unsigned int n_physics_cases = + sizeof(physics_cases) / sizeof(physics_cases[0]); + +} // anonymous namespace + +// --------------------------------------------------------------------------- +// Helper: build QPs on the host using QGauss and fill flat arrays. +// Returns the number of quadrature points. +// --------------------------------------------------------------------------- +static unsigned int +build_qps(libMesh::ElemType elem_type, + unsigned int dim, + unsigned int quadrature_order, + std::vector & xi_h, + std::vector & eta_h, + std::vector & zeta_h) +{ + libMesh::QGauss qr(dim, static_cast(quadrature_order)); + qr.allow_rules_with_negative_weights = true; + qr.init(elem_type); + + const unsigned int nqp = qr.n_points(); + xi_h.resize(nqp); + eta_h.resize(nqp); + zeta_h.resize(nqp); + + for (unsigned int q = 0; q < nqp; ++q) + { + xi_h[q] = qr.qp(q)(0); + eta_h[q] = (dim >= 2) ? qr.qp(q)(1) : Real(0); + zeta_h[q] = (dim >= 3) ? qr.qp(q)(2) : Real(0); + } + + return nqp; +} + +// --------------------------------------------------------------------------- +// Upload a std::vector to a 1-D Kokkos View on device. +// --------------------------------------------------------------------------- +static Kokkos::View +upload_real(const std::vector & v, const char * label) +{ + Kokkos::View d(std::string(label), v.size()); + auto h = Kokkos::create_mirror_view(d); + for (std::size_t i = 0; i < v.size(); ++i) + h(i) = v[i]; + Kokkos::deep_copy(d, h); + return d; +} + +static int +compare_device_values(const Kokkos::View & d_values, + const std::vector & ref_values) +{ + auto h_values = Kokkos::create_mirror_view(d_values); + Kokkos::deep_copy(h_values, d_values); + + int fail = 0; + for (std::size_t i = 0; i < ref_values.size(); ++i) + if (std::fabs(h_values(i) - ref_values[i]) > tol) + ++fail; + + return fail; +} + +static std::unique_ptr +build_reference_elem(libMesh::ElemType elem_type) +{ + auto elem = libMesh::Elem::build(elem_type); + elem->set_mapping_type(libMesh::LAGRANGE_MAP); + return elem; +} + +static Real +host_map_shape(const libMesh::Elem & elem, + const libMesh::FEType & fe_type, + unsigned int i, + Real xi, + Real eta, + Real zeta) +{ + return libMesh::FEInterface::shape(fe_type, 0, &elem, i, libMesh::Point(xi, eta, zeta)); +} + +static Real3 +host_map_grad(const libMesh::Elem & elem, + const libMesh::FEType & fe_type, + unsigned int dim, + unsigned int i, + Real xi, + Real eta, + Real zeta) +{ + const libMesh::Point p(xi, eta, zeta); + const Real gx = libMesh::FEInterface::shape_deriv(fe_type, 0, &elem, i, 0, p); + const Real gy = (dim >= 2) ? libMesh::FEInterface::shape_deriv(fe_type, 0, &elem, i, 1, p) + : Real(0); + const Real gz = (dim >= 3) ? libMesh::FEInterface::shape_deriv(fe_type, 0, &elem, i, 2, p) + : Real(0); + return Real3(gx, gy, gz); +} + +static Real +host_lagrange_shape(const physics_shape_info & info, + unsigned int i, + Real xi, + Real eta, + Real zeta) +{ + const libMesh::Point p(xi, eta, zeta); + + switch (info.dim) + { + case 1: + return libMesh::FE<1, libMesh::LAGRANGE>::shape(info.key.elem_type, info.key.order, i, p); + case 2: + return libMesh::FE<2, libMesh::LAGRANGE>::shape(info.key.elem_type, info.key.order, i, p); + case 3: + return libMesh::FE<3, libMesh::LAGRANGE>::shape(info.key.elem_type, info.key.order, i, p); + default: + return Real(0); + } +} + +static Real3 +host_lagrange_grad(const physics_shape_info & info, + unsigned int i, + Real xi, + Real eta, + Real zeta) +{ + const libMesh::Point p(xi, eta, zeta); + + switch (info.dim) + { + case 1: + return Real3( + libMesh::FE<1, libMesh::LAGRANGE>::shape_deriv(info.key.elem_type, info.key.order, i, 0, p), + 0.0, + 0.0); + case 2: + return Real3( + libMesh::FE<2, libMesh::LAGRANGE>::shape_deriv(info.key.elem_type, info.key.order, i, 0, p), + libMesh::FE<2, libMesh::LAGRANGE>::shape_deriv(info.key.elem_type, info.key.order, i, 1, p), + 0.0); + case 3: + return Real3( + libMesh::FE<3, libMesh::LAGRANGE>::shape_deriv(info.key.elem_type, info.key.order, i, 0, p), + libMesh::FE<3, libMesh::LAGRANGE>::shape_deriv(info.key.elem_type, info.key.order, i, 1, p), + libMesh::FE<3, libMesh::LAGRANGE>::shape_deriv(info.key.elem_type, info.key.order, i, 2, p)); + default: + return Real3(0.0, 0.0, 0.0); + } +} + +// --------------------------------------------------------------------------- +// Test A: Geometry-map shape parity against libMesh FE map dispatch. +// --------------------------------------------------------------------------- +static int +test_map_shape_parity(const map_elem_info & e) +{ + auto elem = build_reference_elem(e.topo); + const libMesh::FEType fe_type(elem->default_order(), libMesh::FEMap::map_fe_type(*elem)); + + std::vector xi_h, eta_h, zeta_h; + const unsigned int nqp = build_qps(e.topo, e.dim, quad_order, xi_h, eta_h, zeta_h); + const unsigned int nd = e.n_dofs; + + std::vector ref_phi(nd * nqp); + for (unsigned int i = 0; i < nd; ++i) + for (unsigned int q = 0; q < nqp; ++q) + ref_phi[i * nqp + q] = + host_map_shape(*elem, fe_type, i, xi_h[q], eta_h[q], zeta_h[q]); + + auto d_xi = upload_real(xi_h, "xi"); + auto d_eta = upload_real(eta_h, "eta"); + auto d_zeta = upload_real(zeta_h, "zeta"); + + Kokkos::View d_phi(std::string("dev_phi"), nd * nqp); + + const libMesh::ElemType topo = e.topo; + const unsigned int nd_ = nd; + const unsigned int nqp_ = nqp; + + Kokkos::parallel_for( + nd_ * nqp_, + KOKKOS_LAMBDA(int idx) { + const int i = idx / static_cast(nqp_); + const int q = idx % static_cast(nqp_); + d_phi(idx) = libMesh::Kokkos::native_map_shape( + libMesh::LAGRANGE_MAP, topo, static_cast(i), d_xi(q), d_eta(q), d_zeta(q)); + }); + Kokkos::fence(); + + return compare_device_values(d_phi, ref_phi); +} + +// --------------------------------------------------------------------------- +// Test B: Geometry-map gradient parity against libMesh FE map dispatch. +// --------------------------------------------------------------------------- +static int +test_map_grad_parity(const map_elem_info & e) +{ + auto elem = build_reference_elem(e.topo); + const libMesh::FEType fe_type(elem->default_order(), libMesh::FEMap::map_fe_type(*elem)); + + std::vector xi_h, eta_h, zeta_h; + const unsigned int nqp = build_qps(e.topo, e.dim, quad_order, xi_h, eta_h, zeta_h); + const unsigned int nd = e.n_dofs; + const unsigned int dim = e.dim; + + std::vector ref_gx(nd * nqp); + std::vector ref_gy(nd * nqp); + std::vector ref_gz(nd * nqp); + for (unsigned int i = 0; i < nd; ++i) + for (unsigned int q = 0; q < nqp; ++q) + { + const Real3 g = host_map_grad(*elem, fe_type, dim, i, xi_h[q], eta_h[q], zeta_h[q]); + ref_gx[i * nqp + q] = g(0); + ref_gy[i * nqp + q] = g(1); + ref_gz[i * nqp + q] = g(2); + } + + auto d_xi = upload_real(xi_h, "xi"); + auto d_eta = upload_real(eta_h, "eta"); + auto d_zeta = upload_real(zeta_h, "zeta"); + + Kokkos::View d_gx(std::string("map_gx"), nd * nqp); + Kokkos::View d_gy(std::string("map_gy"), nd * nqp); + Kokkos::View d_gz(std::string("map_gz"), nd * nqp); + + const libMesh::ElemType topo = e.topo; + const unsigned int nd_ = nd; + const unsigned int nqp_ = nqp; + + Kokkos::parallel_for( + nd_ * nqp_, + KOKKOS_LAMBDA(int idx) { + const int i = idx / static_cast(nqp_); + const int q = idx % static_cast(nqp_); + const Real3 g = libMesh::Kokkos::native_grad_map_shape( + libMesh::LAGRANGE_MAP, topo, static_cast(i), d_xi(q), d_eta(q), d_zeta(q)); + d_gx(idx) = g(0); + d_gy(idx) = g(1); + d_gz(idx) = g(2); + }); + Kokkos::fence(); + + return compare_device_values(d_gx, ref_gx) + + compare_device_values(d_gy, ref_gy) + + compare_device_values(d_gz, ref_gz); +} + +// --------------------------------------------------------------------------- +// Test C: Exact-key physics shape parity against libMesh CPU FE dispatch. +// --------------------------------------------------------------------------- +static int +test_native_shape_parity(const physics_shape_info & info) +{ + std::vector xi_h, eta_h, zeta_h; + const unsigned int nqp = build_qps(info.key.elem_type, info.dim, quad_order, xi_h, eta_h, zeta_h); + const unsigned int nd = info.n_dofs; + + std::vector ref_phi(nd * nqp); + for (unsigned int i = 0; i < nd; ++i) + for (unsigned int q = 0; q < nqp; ++q) + ref_phi[i * nqp + q] = host_lagrange_shape(info, i, xi_h[q], eta_h[q], zeta_h[q]); + + auto d_xi = upload_real(xi_h, "phys_xi"); + auto d_eta = upload_real(eta_h, "phys_eta"); + auto d_zeta = upload_real(zeta_h, "phys_zeta"); + + Kokkos::View d_phi(std::string("phys_phi"), nd * nqp); + + const libMesh::Kokkos::FEShapeKey key = info.key; + const unsigned int nqp_ = nqp; + const unsigned int nd_ = nd; + + Kokkos::parallel_for( + nd_ * nqp_, + KOKKOS_LAMBDA(int idx) { + const int i = idx / static_cast(nqp_); + const int q = idx % static_cast(nqp_); + d_phi(idx) = libMesh::Kokkos::native_shape( + key, static_cast(i), d_xi(q), d_eta(q), d_zeta(q)); + }); + Kokkos::fence(); + + return compare_device_values(d_phi, ref_phi); +} + +// --------------------------------------------------------------------------- +// Test D: Exact-key physics gradient parity against libMesh CPU FE dispatch. +// --------------------------------------------------------------------------- +static int +test_native_grad_shape_parity(const physics_shape_info & info) +{ + std::vector xi_h, eta_h, zeta_h; + const unsigned int nqp = build_qps(info.key.elem_type, info.dim, quad_order, xi_h, eta_h, zeta_h); + const unsigned int nd = info.n_dofs; + + std::vector ref_gx(nd * nqp); + std::vector ref_gy(nd * nqp); + std::vector ref_gz(nd * nqp); + for (unsigned int i = 0; i < nd; ++i) + for (unsigned int q = 0; q < nqp; ++q) + { + const Real3 g = host_lagrange_grad(info, i, xi_h[q], eta_h[q], zeta_h[q]); + ref_gx[i * nqp + q] = g(0); + ref_gy[i * nqp + q] = g(1); + ref_gz[i * nqp + q] = g(2); + } + + auto d_xi = upload_real(xi_h, "grad_xi"); + auto d_eta = upload_real(eta_h, "grad_eta"); + auto d_zeta = upload_real(zeta_h, "grad_zeta"); + + Kokkos::View d_gx(std::string("phys_gx"), nd * nqp); + Kokkos::View d_gy(std::string("phys_gy"), nd * nqp); + Kokkos::View d_gz(std::string("phys_gz"), nd * nqp); + + const libMesh::Kokkos::FEShapeKey key = info.key; + const unsigned int nqp_ = nqp; + const unsigned int nd_ = nd; + + Kokkos::parallel_for( + nd_ * nqp_, + KOKKOS_LAMBDA(int idx) { + const int i = idx / static_cast(nqp_); + const int q = idx % static_cast(nqp_); + const Real3 g = libMesh::Kokkos::native_grad_shape( + key, static_cast(i), d_xi(q), d_eta(q), d_zeta(q)); + d_gx(idx) = g(0); + d_gy(idx) = g(1); + d_gz(idx) = g(2); + }); + Kokkos::fence(); + + return compare_device_values(d_gx, ref_gx) + + compare_device_values(d_gy, ref_gy) + + compare_device_values(d_gz, ref_gz); +} + +// --------------------------------------------------------------------------- +// main +// --------------------------------------------------------------------------- +int main(int argc, char ** argv) +{ + Kokkos::initialize(argc, argv); + libMesh::LibMeshInit init(argc, argv); + + int total_fail = 0; + + for (unsigned int e = 0; e < n_map_elems; ++e) + { + const map_elem_info & info = map_elems[e]; + + { + const int f = test_map_shape_parity(info); + std::printf("[map_shape_parity ][%s] %s (%d)\n", + info.name, f ? "FAIL" : "PASS", f); + total_fail += f; + } + { + const int f = test_map_grad_parity(info); + std::printf("[map_grad_parity ][%s] %s (%d)\n", + info.name, f ? "FAIL" : "PASS", f); + total_fail += f; + } + } + + for (unsigned int c = 0; c < n_physics_cases; ++c) + { + const physics_shape_info & info = physics_cases[c]; + + { + const int f = test_native_shape_parity(info); + std::printf("[native_shape_parity ][%s] %s (%d)\n", + info.name, f ? "FAIL" : "PASS", f); + total_fail += f; + } + { + const int f = test_native_grad_shape_parity(info); + std::printf("[native_grad_shape_parity][%s] %s (%d)\n", + info.name, f ? "FAIL" : "PASS", f); + total_fail += f; + } + } + + if (total_fail == 0) + std::printf("ALL TESTS PASSED\n"); + else + std::printf("%d TEST(S) FAILED\n", total_fail); + + Kokkos::finalize(); + return total_fail ? 1 : 0; +} diff --git a/tests/fe/kokkos_fe_types_test.K b/tests/fe/kokkos_fe_types_test.K new file mode 100644 index 0000000000..dc92a30bc6 --- /dev/null +++ b/tests/fe/kokkos_fe_types_test.K @@ -0,0 +1,453 @@ +// GPU kernel tests for libMesh::Kokkos FE type helpers. +// +// Standalone executable (no CppUnit). Uses libMesh::LibMeshInit so that +// libMesh element topology and FEInterface dispatch are available for +// oracle values. +// +// The test suite covers: +// A. get_side_topology() against libMesh side topology, with the 1D +// NODEELEM -> EDGE2 surrogate used by the Kokkos path. +// B. class_from_topology() against a class inferred from libMesh +// first-order LAGRANGE FE spaces. +// C. n_dofs(FEShapeKey) for exact LAGRANGE keys against +// libMesh::FEInterface::n_dofs(). +// D. n_dofs(FEShapeKey) for MONOMIAL keys against +// libMesh::FEInterface::n_dofs(). +// +// Returns 0 on success, non-zero on failure. + +#include "gpu/kokkos_fe_types.h" + +#include "libmesh/elem.h" +#include "libmesh/fe_interface.h" +#include "libmesh/fe_type.h" +#include "libmesh/libmesh.h" + +#include "libmesh/enum_elem_type.h" +#include "libmesh/enum_fe_family.h" +#include "libmesh/enum_order.h" + +// Avoid conflicting complex operators between CUDA and PETSc +#define PETSC_SKIP_CXX_COMPLEX_FIX 1 +#include +#undef __CUDACC_VER__ + +#include +#include +#include + +namespace +{ + +struct side_topology_case +{ + libMesh::ElemType parent; + libMesh::ElemType expected; +}; + +struct class_from_topology_case +{ + libMesh::ElemType topo; + libMesh::FEElemClass expected; +}; + +struct n_dof_case +{ + libMesh::Kokkos::FEShapeKey key; + unsigned int expected; +}; + +static std::unique_ptr +build_reference_elem(libMesh::ElemType elem_type) +{ + auto elem = libMesh::Elem::build(elem_type); + elem->set_mapping_type(libMesh::LAGRANGE_MAP); + return elem; +} + +static libMesh::ElemType +host_side_topology_oracle(libMesh::ElemType parent_type) +{ + auto elem = build_reference_elem(parent_type); + + if (elem->dim() == 1) + return libMesh::EDGE2; + + auto first_side = elem->build_side_ptr(0); + const libMesh::ElemType side_topo = first_side->type(); + + for (unsigned int s = 1; s < elem->n_sides(); ++s) + { + auto side = elem->build_side_ptr(s); + if (side->type() != side_topo) + return libMesh::INVALID_ELEM; + } + + return side_topo; +} + +static libMesh::FEElemClass +host_class_from_topology_oracle(libMesh::ElemType topo) +{ + auto elem = build_reference_elem(topo); + + if (elem->dim() == 1) + return libMesh::FEElemClass::EDGE; + + const libMesh::FEType fe_type(libMesh::FIRST, libMesh::LAGRANGE); + const unsigned int ndofs = libMesh::FEInterface::n_dofs(fe_type, 0, elem.get()); + + switch (elem->dim()) + { + case 2: + switch (ndofs) + { + case 3: return libMesh::FEElemClass::TRI; + case 4: return libMesh::FEElemClass::QUAD; + default: return libMesh::FEElemClass::N_CLASSES; + } + + case 3: + switch (ndofs) + { + case 4: return libMesh::FEElemClass::TET; + case 8: return libMesh::FEElemClass::HEX; + case 6: return libMesh::FEElemClass::PRISM; + case 5: return libMesh::FEElemClass::PYRAMID; + default: return libMesh::FEElemClass::N_CLASSES; + } + + default: + return libMesh::FEElemClass::N_CLASSES; + } +} + +static unsigned int +host_n_dofs_oracle(libMesh::Kokkos::FEShapeKey key) +{ + auto elem = build_reference_elem(key.elem_type); + return libMesh::FEInterface::n_dofs(libMesh::FEType(key.order, key.family), 0, elem.get()); +} + +} // anonymous namespace + +// --------------------------------------------------------------------------- +// Test 1: get_side_topology() against libMesh side topology. +// --------------------------------------------------------------------------- +static int +test_side_topology() +{ + static const libMesh::ElemType parents[] = { + libMesh::EDGE2, + libMesh::EDGE3, + libMesh::EDGE4, + libMesh::TRI3, + libMesh::TRI7, + libMesh::QUAD4, + libMesh::TRI6, + libMesh::QUAD8, + libMesh::QUAD9, + libMesh::TET4, + libMesh::HEX8, + libMesh::TET10, + libMesh::TET14, + libMesh::HEX20, + libMesh::HEX27 + }; + constexpr int n_cases = sizeof(parents) / sizeof(parents[0]); + + Kokkos::View d_cases(std::string("side_cases"), n_cases); + { + auto h = Kokkos::create_mirror_view(d_cases); + for (int i = 0; i < n_cases; ++i) + { + h(i).parent = parents[i]; + h(i).expected = host_side_topology_oracle(parents[i]); + } + Kokkos::deep_copy(d_cases, h); + } + + Kokkos::View d_fail(std::string("side_fail")); + Kokkos::deep_copy(d_fail, 0); + + Kokkos::parallel_for( + n_cases, + KOKKOS_LAMBDA(int i) { + using namespace libMesh::Kokkos; + if (get_side_topology(d_cases(i).parent) != d_cases(i).expected) + Kokkos::atomic_add(&d_fail(), 1); + }); + Kokkos::fence(); + + int fail = 0; + Kokkos::deep_copy(fail, d_fail); + return fail; +} + +// --------------------------------------------------------------------------- +// Test 2: class_from_topology() against libMesh FE oracle. +// --------------------------------------------------------------------------- +static int +test_class_from_topology() +{ + static const libMesh::ElemType topos[] = { + libMesh::EDGE2, + libMesh::EDGE3, + libMesh::EDGE4, + libMesh::TRI3, + libMesh::TRI6, + libMesh::TRI7, + libMesh::QUAD4, + libMesh::QUAD8, + libMesh::QUAD9, + libMesh::TET4, + libMesh::TET10, + libMesh::TET14, + libMesh::HEX8, + libMesh::HEX20, + libMesh::HEX27, + libMesh::PRISM6, + libMesh::PRISM15, + libMesh::PRISM18, + libMesh::PRISM20, + libMesh::PRISM21, + libMesh::PYRAMID5, + libMesh::PYRAMID13, + libMesh::PYRAMID14, + libMesh::PYRAMID18 + }; + constexpr int n_cases = sizeof(topos) / sizeof(topos[0]); + + Kokkos::View d_cases(std::string("class_cases"), n_cases); + { + auto h = Kokkos::create_mirror_view(d_cases); + for (int i = 0; i < n_cases; ++i) + { + h(i).topo = topos[i]; + h(i).expected = host_class_from_topology_oracle(topos[i]); + } + Kokkos::deep_copy(d_cases, h); + } + + Kokkos::View d_fail(std::string("class_fail")); + Kokkos::deep_copy(d_fail, 0); + + Kokkos::parallel_for( + n_cases, + KOKKOS_LAMBDA(int i) { + using namespace libMesh::Kokkos; + if (class_from_topology(d_cases(i).topo) != d_cases(i).expected) + Kokkos::atomic_add(&d_fail(), 1); + }); + Kokkos::fence(); + + int fail = 0; + Kokkos::deep_copy(fail, d_fail); + return fail; +} + +// --------------------------------------------------------------------------- +// Test 3: n_dofs() for exact LAGRANGE keys against libMesh FEInterface. +// --------------------------------------------------------------------------- +static int +test_n_dofs_lagrange() +{ + using libMesh::Kokkos::FEShapeKey; + + static const FEShapeKey keys[] = { + { libMesh::LAGRANGE, libMesh::NODEELEM, libMesh::CONSTANT }, + { libMesh::LAGRANGE, libMesh::NODEELEM, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::EDGE2, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::EDGE3, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::EDGE3, libMesh::SECOND }, + { libMesh::LAGRANGE, libMesh::EDGE4, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::EDGE4, libMesh::THIRD }, + + { libMesh::LAGRANGE, libMesh::TRI3, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::TRI6, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::TRI6, libMesh::SECOND }, + { libMesh::LAGRANGE, libMesh::TRI7, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::TRI7, libMesh::SECOND }, + { libMesh::LAGRANGE, libMesh::TRI7, libMesh::THIRD }, + { libMesh::LAGRANGE, libMesh::QUAD4, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::QUAD8, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::QUAD8, libMesh::SECOND }, + { libMesh::LAGRANGE, libMesh::QUAD9, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::QUAD9, libMesh::SECOND }, + + { libMesh::LAGRANGE, libMesh::TET4, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::TET10, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::TET10, libMesh::SECOND }, + { libMesh::LAGRANGE, libMesh::TET14, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::TET14, libMesh::SECOND }, + { libMesh::LAGRANGE, libMesh::TET14, libMesh::THIRD }, + { libMesh::LAGRANGE, libMesh::HEX8, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::HEX20, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::HEX20, libMesh::SECOND }, + { libMesh::LAGRANGE, libMesh::HEX27, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::HEX27, libMesh::SECOND }, + + { libMesh::LAGRANGE, libMesh::PRISM6, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::PRISM15, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::PRISM15, libMesh::SECOND }, + { libMesh::LAGRANGE, libMesh::PRISM18, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::PRISM18, libMesh::SECOND }, + { libMesh::LAGRANGE, libMesh::PRISM20, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::PRISM20, libMesh::SECOND }, + { libMesh::LAGRANGE, libMesh::PRISM20, libMesh::THIRD }, + { libMesh::LAGRANGE, libMesh::PRISM21, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::PRISM21, libMesh::SECOND }, + { libMesh::LAGRANGE, libMesh::PRISM21, libMesh::THIRD }, + { libMesh::LAGRANGE, libMesh::PYRAMID5, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::PYRAMID13, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::PYRAMID13, libMesh::SECOND }, + { libMesh::LAGRANGE, libMesh::PYRAMID14, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::PYRAMID14, libMesh::SECOND }, + { libMesh::LAGRANGE, libMesh::PYRAMID18, libMesh::FIRST }, + { libMesh::LAGRANGE, libMesh::PYRAMID18, libMesh::SECOND }, + { libMesh::LAGRANGE, libMesh::PYRAMID18, libMesh::THIRD } + }; + constexpr int n_cases = sizeof(keys) / sizeof(keys[0]); + + Kokkos::View d_cases(std::string("lagrange_cases"), n_cases); + { + auto h = Kokkos::create_mirror_view(d_cases); + for (int i = 0; i < n_cases; ++i) + { + h(i).key = keys[i]; + h(i).expected = host_n_dofs_oracle(keys[i]); + } + Kokkos::deep_copy(d_cases, h); + } + + Kokkos::View d_fail(std::string("lagrange_fail")); + Kokkos::deep_copy(d_fail, 0); + + Kokkos::parallel_for( + n_cases, + KOKKOS_LAMBDA(int i) { + using namespace libMesh::Kokkos; + if (n_dofs(d_cases(i).key) != d_cases(i).expected) + Kokkos::atomic_add(&d_fail(), 1); + }); + Kokkos::fence(); + + int fail = 0; + Kokkos::deep_copy(fail, d_fail); + return fail; +} + +// --------------------------------------------------------------------------- +// Test 4: n_dofs() for MONOMIAL keys against libMesh FEInterface. +// --------------------------------------------------------------------------- +static int +test_n_dofs_monomial() +{ + using libMesh::Kokkos::FEShapeKey; + + static const libMesh::Order orders[] = { + libMesh::CONSTANT, + libMesh::FIRST, + libMesh::SECOND, + libMesh::THIRD, + libMesh::FOURTH, + libMesh::FIFTH + }; + static const libMesh::ElemType higher_dim_topos[] = { + libMesh::TRI7, + libMesh::QUAD9, + libMesh::TET14, + libMesh::HEX27, + libMesh::PRISM21 + }; + + constexpr int n_cases = sizeof(orders) / sizeof(orders[0]) * + (2 + sizeof(higher_dim_topos) / sizeof(higher_dim_topos[0])); + + Kokkos::View d_cases(std::string("monomial_cases"), n_cases); + { + auto h = Kokkos::create_mirror_view(d_cases); + int i = 0; + for (const auto order : orders) + { + const libMesh::ElemType edge_topo = + (order <= libMesh::THIRD) ? libMesh::EDGE4 : libMesh::EDGE3; + const libMesh::ElemType pyramid_topo = + (order <= libMesh::THIRD) ? libMesh::PYRAMID18 : libMesh::PYRAMID14; + + h(i).key = { libMesh::MONOMIAL, edge_topo, order }; + h(i).expected = host_n_dofs_oracle(h(i).key); + ++i; + + h(i).key = { libMesh::MONOMIAL, pyramid_topo, order }; + h(i).expected = host_n_dofs_oracle(h(i).key); + ++i; + + for (const auto topo : higher_dim_topos) + { + h(i).key = { libMesh::MONOMIAL, topo, order }; + h(i).expected = host_n_dofs_oracle(h(i).key); + ++i; + } + } + Kokkos::deep_copy(d_cases, h); + } + + Kokkos::View d_fail(std::string("monomial_fail")); + Kokkos::deep_copy(d_fail, 0); + + Kokkos::parallel_for( + n_cases, + KOKKOS_LAMBDA(int i) { + using namespace libMesh::Kokkos; + if (n_dofs(d_cases(i).key) != d_cases(i).expected) + Kokkos::atomic_add(&d_fail(), 1); + }); + Kokkos::fence(); + + int fail = 0; + Kokkos::deep_copy(fail, d_fail); + return fail; +} + +// --------------------------------------------------------------------------- +// main +// --------------------------------------------------------------------------- +int +main(int argc, char ** argv) +{ + Kokkos::initialize(argc, argv); + libMesh::LibMeshInit init(argc, argv); + + int total_fail = 0; + + { + const int f = test_side_topology(); + std::printf("[side_topology_oracle] %s (%d failures)\n", f ? "FAIL" : "PASS", f); + total_fail += f; + } + { + const int f = test_class_from_topology(); + std::printf("[class_topology_oracle] %s (%d failures)\n", f ? "FAIL" : "PASS", f); + total_fail += f; + } + { + const int f = test_n_dofs_lagrange(); + std::printf("[lagrange_ndofs_oracle] %s (%d failures)\n", f ? "FAIL" : "PASS", f); + total_fail += f; + } + { + const int f = test_n_dofs_monomial(); + std::printf("[monomial_ndofs_oracle] %s (%d failures)\n", f ? "FAIL" : "PASS", f); + total_fail += f; + } + + Kokkos::finalize(); + + if (total_fail == 0) + std::printf("ALL TESTS PASSED\n"); + else + std::printf("%d TEST(S) FAILED\n", total_fail); + + return total_fail ? 1 : 0; +} diff --git a/tests/fe/kokkos_quadrature_test.K b/tests/fe/kokkos_quadrature_test.K new file mode 100644 index 0000000000..cedccd2010 --- /dev/null +++ b/tests/fe/kokkos_quadrature_test.K @@ -0,0 +1,516 @@ +// GPU kernel tests for libMesh::Kokkos quadrature and map helpers. +// +// Standalone executable (no CppUnit). Uses libMesh::LibMeshInit so that +// QGauss, FEMap, and FEBase::side_map are available for oracle values. +// +// The test suite covers: +// A. GaussQuadrature point and weight tables against libMesh QGauss. +// B. physical_point() and jacobian() against libMesh FEMap::map() and +// FEMap::map_deriv(). +// C. map_face_qp_to_parent() against libMesh FEBase::side_map(). +// +// Returns 0 on success, non-zero on failure. + +#include "libmesh/libmesh_config.h" + +#include "gpu/kokkos_fe_face_map.h" +#include "gpu/kokkos_fe_map.h" +#include "gpu/kokkos_quadrature.h" + +#include "libmesh/elem.h" +#include "libmesh/fe_base.h" +#include "libmesh/fe_map.h" +#include "libmesh/libmesh.h" +#include "libmesh/node.h" +#include "libmesh/quadrature_gauss.h" + +// Avoid conflicting complex operators between CUDA and PETSc +#define PETSC_SKIP_CXX_COMPLEX_FIX 1 +#include +#undef __CUDACC_VER__ + +#include +#include +#include +#include +#include + +using libMesh::Kokkos::GaussQuadrature; +using libMesh::Kokkos::Real; +using libMesh::Kokkos::Real3; +using libMesh::Kokkos::Real33; + +static constexpr double tol = 1.0e-13; + +namespace +{ + +struct quadrature_case +{ + libMesh::ElemType topo; + unsigned int dim; + unsigned int order; +}; + +struct element_fixture +{ + std::unique_ptr elem; + std::vector> nodes; +}; + +} // anonymous namespace + +static int +compare_device_values(const Kokkos::View & d_values, + const std::vector & ref_values) +{ + auto h_values = Kokkos::create_mirror_view(d_values); + Kokkos::deep_copy(h_values, d_values); + + int fail = 0; + for (std::size_t i = 0; i < ref_values.size(); ++i) + if (std::fabs(h_values(i) - ref_values[i]) > tol) + ++fail; + + return fail; +} + +static unsigned int +build_host_qgauss(libMesh::ElemType topo, + unsigned int dim, + unsigned int order, + std::vector & x_ref, + std::vector & y_ref, + std::vector & z_ref, + std::vector & w_ref) +{ + libMesh::QGauss qr(dim, static_cast(order)); + qr.allow_rules_with_negative_weights = true; + qr.init(topo); + + const unsigned int nqp = qr.n_points(); + x_ref.resize(nqp); + y_ref.resize(nqp); + z_ref.resize(nqp); + w_ref.resize(nqp); + + for (unsigned int q = 0; q < nqp; ++q) + { + x_ref[q] = qr.qp(q)(0); + y_ref[q] = (dim >= 2) ? qr.qp(q)(1) : Real(0); + z_ref[q] = (dim >= 3) ? qr.qp(q)(2) : Real(0); + w_ref[q] = qr.w(q); + } + + return nqp; +} + +static int +test_quadrature_case(const quadrature_case & info) +{ + std::vector x_ref, y_ref, z_ref, w_ref; + const unsigned int host_nqp = + build_host_qgauss(info.topo, info.dim, info.order, x_ref, y_ref, z_ref, w_ref); + + Kokkos::View d_nqp(std::string("nqp")); + Kokkos::parallel_for( + 1, + KOKKOS_LAMBDA(int) { + d_nqp() = GaussQuadrature::n_points(info.topo, info.order); + }); + Kokkos::fence(); + + unsigned int device_nqp = 0; + Kokkos::deep_copy(device_nqp, d_nqp); + + int fail = 0; + if (device_nqp != host_nqp) + ++fail; + + Kokkos::View d_x(std::string("qx"), host_nqp); + Kokkos::View d_y(std::string("qy"), host_nqp); + Kokkos::View d_z(std::string("qz"), host_nqp); + Kokkos::View d_w(std::string("qw"), host_nqp); + + Kokkos::parallel_for( + host_nqp, + KOKKOS_LAMBDA(int qp) { + const Real3 pt = GaussQuadrature::point(info.topo, info.order, qp); + d_x(qp) = pt(0); + d_y(qp) = pt(1); + d_z(qp) = pt(2); + d_w(qp) = GaussQuadrature::weight(info.topo, info.order, qp); + }); + Kokkos::fence(); + + fail += compare_device_values(d_x, x_ref); + fail += compare_device_values(d_y, y_ref); + fail += compare_device_values(d_z, z_ref); + fail += compare_device_values(d_w, w_ref); + + if (fail) + std::printf(" quadrature mismatch: topo=%d dim=%u order=%u (%d failures)\n", + static_cast(info.topo), info.dim, info.order, fail); + + return fail; +} + +static int +test_quadrature_against_qgauss() +{ + int fail = 0; + + const libMesh::ElemType edge_topos[] = { libMesh::EDGE2, libMesh::EDGE3 }; + const libMesh::ElemType quad_topos[] = { libMesh::QUAD4, libMesh::QUAD8, libMesh::QUAD9 }; + const libMesh::ElemType hex_topos[] = { libMesh::HEX8, libMesh::HEX20, libMesh::HEX27 }; + const libMesh::ElemType tri_topos[] = { libMesh::TRI3, libMesh::TRI6 }; + const libMesh::ElemType tet_topos[] = { libMesh::TET4, libMesh::TET10 }; + + for (const auto topo : edge_topos) + for (unsigned int order = 0; order <= 12; ++order) + fail += test_quadrature_case({ topo, 1, order }); + + for (const auto topo : quad_topos) + for (unsigned int order = 0; order <= 12; ++order) + fail += test_quadrature_case({ topo, 2, order }); + + for (const auto topo : hex_topos) + for (unsigned int order = 0; order <= 12; ++order) + fail += test_quadrature_case({ topo, 3, order }); + + for (const auto topo : tri_topos) + for (unsigned int order = 0; order <= 6; ++order) + fail += test_quadrature_case({ topo, 2, order }); + + for (const auto topo : tet_topos) + for (unsigned int order = 0; order <= 6; ++order) + fail += test_quadrature_case({ topo, 3, order }); + + return fail; +} + +static element_fixture +build_hex8_fixture() +{ + element_fixture fixture; + fixture.elem = libMesh::Elem::build(libMesh::HEX8); + fixture.elem->set_mapping_type(libMesh::LAGRANGE_MAP); + fixture.nodes.reserve(8); + + static const double coords[8][3] = { + {0.0, 0.0, 0.0}, + {1.0, 0.0, 0.0}, + {1.0, 1.0, 0.0}, + {0.0, 1.0, 0.0}, + {0.0, 0.0, 1.0}, + {1.0, 0.0, 1.0}, + {1.0, 1.0, 1.0}, + {0.0, 1.0, 1.0} + }; + + for (unsigned int i = 0; i < 8; ++i) + { + fixture.nodes.push_back(libMesh::Node::build(coords[i][0], coords[i][1], coords[i][2], i)); + fixture.elem->set_node(i, fixture.nodes.back().get()); + } + + return fixture; +} + +static element_fixture +build_tri3_fixture() +{ + element_fixture fixture; + fixture.elem = libMesh::Elem::build(libMesh::TRI3); + fixture.elem->set_mapping_type(libMesh::LAGRANGE_MAP); + fixture.nodes.reserve(3); + + static const double coords[3][3] = { + {0.0, 0.0, 0.0}, + {1.0, 0.0, 0.0}, + {0.0, 1.0, 0.0} + }; + + for (unsigned int i = 0; i < 3; ++i) + { + fixture.nodes.push_back(libMesh::Node::build(coords[i][0], coords[i][1], coords[i][2], i)); + fixture.elem->set_node(i, fixture.nodes.back().get()); + } + + return fixture; +} + +static int +test_physical_map_hex8() +{ + auto fixture = build_hex8_fixture(); + + const libMesh::Point ref_center(0.0, 0.0, 0.0); + const libMesh::Point ref_corner(-1.0, -1.0, -1.0); + + const libMesh::Point host_center = libMesh::FEMap::map(3, fixture.elem.get(), ref_center); + const libMesh::Point host_corner = libMesh::FEMap::map(3, fixture.elem.get(), ref_corner); + const libMesh::Point host_dxi = libMesh::FEMap::map_deriv(3, fixture.elem.get(), 0, ref_center); + const libMesh::Point host_deta = libMesh::FEMap::map_deriv(3, fixture.elem.get(), 1, ref_center); + const libMesh::Point host_dzeta = libMesh::FEMap::map_deriv(3, fixture.elem.get(), 2, ref_center); + + std::vector ref_values = { + host_center(0), host_center(1), host_center(2), + host_dxi(0), host_dxi(1), host_dxi(2), + host_deta(0), host_deta(1), host_deta(2), + host_dzeta(0), host_dzeta(1), host_dzeta(2), + host_corner(0), host_corner(1), host_corner(2) + }; + + Kokkos::View d_coords(std::string("hex_coords"), 24); + { + auto h = Kokkos::create_mirror_view(d_coords); + for (unsigned int i = 0; i < fixture.elem->n_nodes(); ++i) + { + h(3 * i + 0) = fixture.elem->point(i)(0); + h(3 * i + 1) = fixture.elem->point(i)(1); + h(3 * i + 2) = fixture.elem->point(i)(2); + } + Kokkos::deep_copy(d_coords, h); + } + + Kokkos::View d_results(std::string("hex_results"), ref_values.size()); + Kokkos::parallel_for( + 1, + KOKKOS_LAMBDA(int) { + Real3 nodes[8]; + for (unsigned int i = 0; i < 8; ++i) + nodes[i] = Real3(d_coords(3 * i + 0), d_coords(3 * i + 1), d_coords(3 * i + 2)); + + const Real3 xyz_center = libMesh::Kokkos::physical_point( + libMesh::LAGRANGE_MAP, libMesh::HEX8, nodes, 8, 0.0, 0.0, 0.0); + const Real33 J_center = libMesh::Kokkos::jacobian( + libMesh::LAGRANGE_MAP, libMesh::HEX8, nodes, 8, 0.0, 0.0, 0.0); + const Real3 xyz_corner = libMesh::Kokkos::physical_point( + libMesh::LAGRANGE_MAP, libMesh::HEX8, nodes, 8, -1.0, -1.0, -1.0); + + d_results(0) = xyz_center(0); + d_results(1) = xyz_center(1); + d_results(2) = xyz_center(2); + d_results(3) = J_center(0, 0); + d_results(4) = J_center(0, 1); + d_results(5) = J_center(0, 2); + d_results(6) = J_center(1, 0); + d_results(7) = J_center(1, 1); + d_results(8) = J_center(1, 2); + d_results(9) = J_center(2, 0); + d_results(10) = J_center(2, 1); + d_results(11) = J_center(2, 2); + d_results(12) = xyz_corner(0); + d_results(13) = xyz_corner(1); + d_results(14) = xyz_corner(2); + }); + Kokkos::fence(); + + return compare_device_values(d_results, ref_values); +} + +static int +test_physical_map_tri3() +{ + auto fixture = build_tri3_fixture(); + + const libMesh::Point ref_pt(1.0 / 3.0, 1.0 / 3.0, 0.0); + + const libMesh::Point host_xyz = libMesh::FEMap::map(2, fixture.elem.get(), ref_pt); + const libMesh::Point host_dxi = libMesh::FEMap::map_deriv(2, fixture.elem.get(), 0, ref_pt); + const libMesh::Point host_deta = libMesh::FEMap::map_deriv(2, fixture.elem.get(), 1, ref_pt); + + std::vector ref_values = { + host_xyz(0), host_xyz(1), host_xyz(2), + host_dxi(0), host_dxi(1), host_dxi(2), + host_deta(0), host_deta(1), host_deta(2) + }; + + Kokkos::View d_coords(std::string("tri_coords"), 9); + { + auto h = Kokkos::create_mirror_view(d_coords); + for (unsigned int i = 0; i < fixture.elem->n_nodes(); ++i) + { + h(3 * i + 0) = fixture.elem->point(i)(0); + h(3 * i + 1) = fixture.elem->point(i)(1); + h(3 * i + 2) = fixture.elem->point(i)(2); + } + Kokkos::deep_copy(d_coords, h); + } + + Kokkos::View d_results(std::string("tri_results"), ref_values.size()); + Kokkos::parallel_for( + 1, + KOKKOS_LAMBDA(int) { + Real3 nodes[3]; + for (unsigned int i = 0; i < 3; ++i) + nodes[i] = Real3(d_coords(3 * i + 0), d_coords(3 * i + 1), d_coords(3 * i + 2)); + + const Real3 xyz = libMesh::Kokkos::physical_point( + libMesh::LAGRANGE_MAP, libMesh::TRI3, nodes, 3, 1.0 / 3.0, 1.0 / 3.0, 0.0); + const Real33 J = libMesh::Kokkos::jacobian( + libMesh::LAGRANGE_MAP, libMesh::TRI3, nodes, 3, 1.0 / 3.0, 1.0 / 3.0, 0.0); + + d_results(0) = xyz(0); + d_results(1) = xyz(1); + d_results(2) = xyz(2); + d_results(3) = J(0, 0); + d_results(4) = J(0, 1); + d_results(5) = J(0, 2); + d_results(6) = J(1, 0); + d_results(7) = J(1, 1); + d_results(8) = J(1, 2); + }); + Kokkos::fence(); + + return compare_device_values(d_results, ref_values); +} + +static Real3 +host_face_qp_to_parent_oracle(const libMesh::Elem & parent, + const libMesh::Elem & side, + unsigned int side_id, + Real3 face_qpt) +{ + const libMesh::FEType fe_type(parent.default_order(), libMesh::FEMap::map_fe_type(parent)); + auto fe = libMesh::FEBase::build(parent.dim(), fe_type); + + std::vector ref_side_points(1); + ref_side_points[0] = libMesh::Point(face_qpt(0), face_qpt(1), face_qpt(2)); + + std::vector ref_points; + fe->side_map(&parent, &side, side_id, ref_side_points, ref_points); + + return Real3(ref_points[0](0), ref_points[0](1), ref_points[0](2)); +} + +static int +test_face_qp_to_parent_ref_coords() +{ + using libMesh::Elem; + using libMesh::Node; + using libMesh::Kokkos::map_face_qp_to_parent; + + int fail = 0; + + { + auto edge = Elem::build(libMesh::EDGE2); + edge->set_mapping_type(libMesh::LAGRANGE_MAP); + auto n0 = Node::build(3.25, -2.0, 5.0, 0); + auto n1 = Node::build(9.50, 4.0, -1.0, 1); + edge->set_node(0, n0.get()); + edge->set_node(1, n1.get()); + + auto side0 = edge->build_side_ptr(0); + auto side1 = edge->build_side_ptr(1); + + const Real3 host0 = host_face_qp_to_parent_oracle(*edge, *side0, 0, Real3(0.0, 0.0, 0.0)); + const Real3 host1 = host_face_qp_to_parent_oracle(*edge, *side1, 1, Real3(0.0, 0.0, 0.0)); + + const Real3 kokkos0 = map_face_qp_to_parent( + *side0, libMesh::LAGRANGE_MAP, side0->type(), Real3(0.0, 0.0, 0.0)); + const Real3 kokkos1 = map_face_qp_to_parent( + *side1, libMesh::LAGRANGE_MAP, side1->type(), Real3(0.0, 0.0, 0.0)); + + for (unsigned int d = 0; d < 3; ++d) + { + if (std::fabs(kokkos0(d) - host0(d)) > tol) + ++fail; + if (std::fabs(kokkos1(d) - host1(d)) > tol) + ++fail; + } + } + + { + auto tri3 = Elem::build(libMesh::TRI3); + tri3->set_mapping_type(libMesh::LAGRANGE_MAP); + auto n0 = Node::build(10.0, 20.0, 0.0, 0); + auto n1 = Node::build(14.0, 20.0, 0.0, 1); + auto n2 = Node::build(10.0, 23.0, 0.0, 2); + tri3->set_node(0, n0.get()); + tri3->set_node(1, n1.get()); + tri3->set_node(2, n2.get()); + + auto side0 = tri3->build_side_ptr(0); + + const Real3 host = host_face_qp_to_parent_oracle(*tri3, *side0, 0, Real3(0.0, 0.0, 0.0)); + const Real3 kokkos = map_face_qp_to_parent( + *side0, libMesh::LAGRANGE_MAP, side0->type(), Real3(0.0, 0.0, 0.0)); + + for (unsigned int d = 0; d < 3; ++d) + if (std::fabs(kokkos(d) - host(d)) > tol) + ++fail; + } + + { + auto tri6 = Elem::build(libMesh::TRI6); + tri6->set_mapping_type(libMesh::LAGRANGE_MAP); + auto n0 = Node::build(4.0, 1.0, 0.0, 0); + auto n1 = Node::build(9.0, 2.0, 0.0, 1); + auto n2 = Node::build(3.0, 8.0, 0.0, 2); + auto n3 = Node::build(42.0, -17.0, 5.0, 3); + auto n4 = Node::build(11.0, 11.0, 1.0, 4); + auto n5 = Node::build(-7.0, 4.0, 2.0, 5); + tri6->set_node(0, n0.get()); + tri6->set_node(1, n1.get()); + tri6->set_node(2, n2.get()); + tri6->set_node(3, n3.get()); + tri6->set_node(4, n4.get()); + tri6->set_node(5, n5.get()); + + auto side0 = tri6->build_side_ptr(0); + + const Real3 host = host_face_qp_to_parent_oracle(*tri6, *side0, 0, Real3(0.0, 0.0, 0.0)); + const Real3 kokkos = map_face_qp_to_parent( + *side0, libMesh::LAGRANGE_MAP, side0->type(), Real3(0.0, 0.0, 0.0)); + + for (unsigned int d = 0; d < 3; ++d) + if (std::fabs(kokkos(d) - host(d)) > tol) + ++fail; + } + + return fail; +} + +// --------------------------------------------------------------------------- +// main +// --------------------------------------------------------------------------- +int +main(int argc, char ** argv) +{ + Kokkos::initialize(argc, argv); + libMesh::LibMeshInit init(argc, argv); + + int total_fail = 0; + + { + const int f = test_quadrature_against_qgauss(); + std::printf("[quadrature_qgauss_oracle] %s (%d failures)\n", f ? "FAIL" : "PASS", f); + total_fail += f; + } + { + const int f = test_physical_map_hex8(); + std::printf("[physical_map_hex8] %s (%d failures)\n", f ? "FAIL" : "PASS", f); + total_fail += f; + } + { + const int f = test_physical_map_tri3(); + std::printf("[physical_map_tri3] %s (%d failures)\n", f ? "FAIL" : "PASS", f); + total_fail += f; + } + { + const int f = test_face_qp_to_parent_ref_coords(); + std::printf("[face_qp_parent_oracle] %s (%d failures)\n", f ? "FAIL" : "PASS", f); + total_fail += f; + } + + Kokkos::finalize(); + + if (total_fail == 0) + std::printf("ALL TESTS PASSED\n"); + else + std::printf("%d TEST(S) FAILED\n", total_fail); + + return total_fail ? 1 : 0; +}