src/dolfinx_access/minmax_p2.cc

changeset 12
a0d61ac3719e
parent 3
c3a4f4bb87f7
--- a/src/dolfinx_access/minmax_p2.cc	Mon Jun 29 00:20:42 2026 +0300
+++ b/src/dolfinx_access/minmax_p2.cc	Sun Oct 04 13:02:26 2026 -0500
@@ -83,53 +83,41 @@
         //     printf("%zd\n", d.size());
         // }
 
-        // DOF coordinates (may be more than nodes, e.g., intermediate points)
-        auto gx = geom.x();
-        // auto num_points = gx.size() / 3;
-        //  Map from cells to DOF indices
-        auto geom_dofmap = geom.dofmap();
-        assert(geom_dofmap.extent(0) == (size_t)n_cells);
-        assert(geom_dofmap.extent(1) == 3);
+        // DOF coordinates and dofmap for the function space itself (not the mesh geometry).
+        // For a scalar P2 space this gives us, per cell, the 6 nodal points (3 corners + 3 edge
+        // midpoints) directly in basix's local ordering, so we no longer need to reconstruct
+        // edge midpoints via f->eval.
         auto fp_dofmap = fp->dofmap();
-
-        // auto dof_coords = fp->tabulate_dof_coordinates();
+        // transpose=false gives a flat vector laid out as (num_dofs, 3) row-major, i.e.
+        // dof_coords[3*d + component].
+        auto dof_coords = fp->tabulate_dof_coordinates(false);
+        auto v_array = v->array(); // local coefficient vector
 
         CoordValuePair res{{{0.0, 0.0}}, INFINITY};
 
-        // printf("%zd %zd\n", v->array().size(), gx.size());
+        for (auto i = 0; i < n_cells; i++) {
+            auto dofs = fp_dofmap->cell_dofs(i);
+            assert(dofs.size() == 6);
 
-        for (auto i = 0; i < n_cells; i++) {
-            // Cell corners
-            auto j0 = geom_dofmap(i, 0);
-            auto j1 = geom_dofmap(i, 1);
-            auto j2 = geom_dofmap(i, 2);
+            // Coordinates of all 6 P2 nodes for this cell, in Fenics' hard-coded 3D layout.
+            std::array<double, 18> x{};
+            // Nodal values of f at those same 6 points.
+            std::array<double, 6> vals{};
 
-            // Construct list of coordinates. Due to f->eval, we construct this is a single list
-            // with all the Fenics weirdness of hard-coded 3D.
-            std::array<double, 9> x = {gx[3 * j0], gx[3 * j0 + 1], 0,
-                                       gx[3 * j1], gx[3 * j1 + 1], 0,
-                                       gx[3 * j2], gx[3 * j2 + 1], 0};
+            for (std::size_t k = 0; k < 6; k++) {
+                auto d = dofs[k];
+                vals[k] = v_array[d];
+                x[3 * k] = dof_coords[3 * d];
+                x[3 * k + 1] = dof_coords[3 * d + 1];
+                x[3 * k + 2] = 0.0;
+            }
 
             // Find the solution on the simplex.
-            auto newres = minmax_dolfinx_p2_cell(f, x, i, max);
+            auto newres = minmax_dolfinx_p2(x, vals, max);
 
-            // printf("%f [%f, %f] [%f %f %f %f %f %f] <%f, %f> <%f, %f> <‸%f, %f>\n", newres.v,
-            //        newres.x[0], newres.x[1], values[0], values[1], values[2], values[3],
-            //        values[4], values[5], x[0], x[1], x[3], x[4], x[6], x[7]);
             if (newres.v < res.v) {
                 res = newres;
             }
-
-            // // Full DOF data
-            // auto d = fp_dofmap->cell_dofs(i);
-            // // TODO: array() gives just local part of vector
-            // assert(d.size() == 6);
-            // for (auto k = 0; k < d.size(); k++) {
-            //     auto j = d[k];
-            //     // printf("%d %d\n", 3 * j + 1, nodes.size());
-            //     assert(2 * j + 1 <= nodes.size());
-            //     auto x = {nodes[3 * j], nodes[3 * j + 1]};
-            // }
         }
 
         // Negate result if maximising.
@@ -139,6 +127,25 @@
         return res;
     }
 
+    void cell_dofs_Function_f64_p2(Function<double> const* f, int32_t cell,
+                                   std::array<double, 18>& x, std::array<double, 6>& vals) {
+        auto fp = f->function_space();
+        auto fp_dofmap = fp->dofmap();
+        auto dofs = fp_dofmap->cell_dofs(cell);
+        assert(dofs.size() == 6);
+        auto dof_coords = fp->tabulate_dof_coordinates(false);
+        auto v = f->x();
+        auto v_array = v->array(); // local coefficient vector
+
+        for (std::size_t k = 0; k < 6; k++) {
+            auto d = dofs[k];
+            vals[k] = v_array[d];
+            x[3 * k] = dof_coords[3 * d];
+            x[3 * k + 1] = dof_coords[3 * d + 1];
+            x[3 * k + 2] = 0.0;
+        }
+    }
+
     CoordValuePair min_Function_f64_p2(Function<double> const* f) {
         return minmax_Function_f64_p2(f, false);
     }
@@ -154,6 +161,7 @@
         m.def("minmax_Function_f64_p2", &minmax_Function_f64_p2);
         m.def("eval_Function_f64", &eval_Function_f64);
         m.def("cell_Function_f64", &cell_Function_f64);
+        m.def("cell_dofs_Function_f64_p2", &cell_dofs_Function_f64_p2);
         // m.def("cell_Mesh_f64", &cell_Mesh_f64);
         m.def("cell_FunctionSpace_f64", &cell_FunctionSpace_f64);
         nanobind::class_<CoordValuePair>(m, "CoordValuePair")

mercurial