src/dolfinx_access/minmax_p2.cc

changeset 12
a0d61ac3719e
parent 3
c3a4f4bb87f7
equal deleted inserted replaced
11:c4f923017349 12:a0d61ac3719e
81 // // assert(adj->num_links(i) == 3); // Should not need this 81 // // assert(adj->num_links(i) == 3); // Should not need this
82 // auto d = fp->dofmap()->cell_dofs(i); 82 // auto d = fp->dofmap()->cell_dofs(i);
83 // printf("%zd\n", d.size()); 83 // printf("%zd\n", d.size());
84 // } 84 // }
85 85
86 // DOF coordinates (may be more than nodes, e.g., intermediate points) 86 // DOF coordinates and dofmap for the function space itself (not the mesh geometry).
87 auto gx = geom.x(); 87 // For a scalar P2 space this gives us, per cell, the 6 nodal points (3 corners + 3 edge
88 // auto num_points = gx.size() / 3; 88 // midpoints) directly in basix's local ordering, so we no longer need to reconstruct
89 // Map from cells to DOF indices 89 // edge midpoints via f->eval.
90 auto geom_dofmap = geom.dofmap();
91 assert(geom_dofmap.extent(0) == (size_t)n_cells);
92 assert(geom_dofmap.extent(1) == 3);
93 auto fp_dofmap = fp->dofmap(); 90 auto fp_dofmap = fp->dofmap();
94 91 // transpose=false gives a flat vector laid out as (num_dofs, 3) row-major, i.e.
95 // auto dof_coords = fp->tabulate_dof_coordinates(); 92 // dof_coords[3*d + component].
93 auto dof_coords = fp->tabulate_dof_coordinates(false);
94 auto v_array = v->array(); // local coefficient vector
96 95
97 CoordValuePair res{{{0.0, 0.0}}, INFINITY}; 96 CoordValuePair res{{{0.0, 0.0}}, INFINITY};
98 97
99 // printf("%zd %zd\n", v->array().size(), gx.size()); 98 for (auto i = 0; i < n_cells; i++) {
99 auto dofs = fp_dofmap->cell_dofs(i);
100 assert(dofs.size() == 6);
100 101
101 for (auto i = 0; i < n_cells; i++) { 102 // Coordinates of all 6 P2 nodes for this cell, in Fenics' hard-coded 3D layout.
102 // Cell corners 103 std::array<double, 18> x{};
103 auto j0 = geom_dofmap(i, 0); 104 // Nodal values of f at those same 6 points.
104 auto j1 = geom_dofmap(i, 1); 105 std::array<double, 6> vals{};
105 auto j2 = geom_dofmap(i, 2);
106 106
107 // Construct list of coordinates. Due to f->eval, we construct this is a single list 107 for (std::size_t k = 0; k < 6; k++) {
108 // with all the Fenics weirdness of hard-coded 3D. 108 auto d = dofs[k];
109 std::array<double, 9> x = {gx[3 * j0], gx[3 * j0 + 1], 0, 109 vals[k] = v_array[d];
110 gx[3 * j1], gx[3 * j1 + 1], 0, 110 x[3 * k] = dof_coords[3 * d];
111 gx[3 * j2], gx[3 * j2 + 1], 0}; 111 x[3 * k + 1] = dof_coords[3 * d + 1];
112 x[3 * k + 2] = 0.0;
113 }
112 114
113 // Find the solution on the simplex. 115 // Find the solution on the simplex.
114 auto newres = minmax_dolfinx_p2_cell(f, x, i, max); 116 auto newres = minmax_dolfinx_p2(x, vals, max);
115 117
116 // printf("%f [%f, %f] [%f %f %f %f %f %f] <%f, %f> <%f, %f> <‸%f, %f>\n", newres.v,
117 // newres.x[0], newres.x[1], values[0], values[1], values[2], values[3],
118 // values[4], values[5], x[0], x[1], x[3], x[4], x[6], x[7]);
119 if (newres.v < res.v) { 118 if (newres.v < res.v) {
120 res = newres; 119 res = newres;
121 } 120 }
122
123 // // Full DOF data
124 // auto d = fp_dofmap->cell_dofs(i);
125 // // TODO: array() gives just local part of vector
126 // assert(d.size() == 6);
127 // for (auto k = 0; k < d.size(); k++) {
128 // auto j = d[k];
129 // // printf("%d %d\n", 3 * j + 1, nodes.size());
130 // assert(2 * j + 1 <= nodes.size());
131 // auto x = {nodes[3 * j], nodes[3 * j + 1]};
132 // }
133 } 121 }
134 122
135 // Negate result if maximising. 123 // Negate result if maximising.
136 if (max) { 124 if (max) {
137 res.v = -res.v; 125 res.v = -res.v;
138 } 126 }
139 return res; 127 return res;
128 }
129
130 void cell_dofs_Function_f64_p2(Function<double> const* f, int32_t cell,
131 std::array<double, 18>& x, std::array<double, 6>& vals) {
132 auto fp = f->function_space();
133 auto fp_dofmap = fp->dofmap();
134 auto dofs = fp_dofmap->cell_dofs(cell);
135 assert(dofs.size() == 6);
136 auto dof_coords = fp->tabulate_dof_coordinates(false);
137 auto v = f->x();
138 auto v_array = v->array(); // local coefficient vector
139
140 for (std::size_t k = 0; k < 6; k++) {
141 auto d = dofs[k];
142 vals[k] = v_array[d];
143 x[3 * k] = dof_coords[3 * d];
144 x[3 * k + 1] = dof_coords[3 * d + 1];
145 x[3 * k + 2] = 0.0;
146 }
140 } 147 }
141 148
142 CoordValuePair min_Function_f64_p2(Function<double> const* f) { 149 CoordValuePair min_Function_f64_p2(Function<double> const* f) {
143 return minmax_Function_f64_p2(f, false); 150 return minmax_Function_f64_p2(f, false);
144 } 151 }
152 m.def("min_Function_f64_p2", &min_Function_f64_p2); 159 m.def("min_Function_f64_p2", &min_Function_f64_p2);
153 m.def("max_Function_f64_p2", &max_Function_f64_p2); 160 m.def("max_Function_f64_p2", &max_Function_f64_p2);
154 m.def("minmax_Function_f64_p2", &minmax_Function_f64_p2); 161 m.def("minmax_Function_f64_p2", &minmax_Function_f64_p2);
155 m.def("eval_Function_f64", &eval_Function_f64); 162 m.def("eval_Function_f64", &eval_Function_f64);
156 m.def("cell_Function_f64", &cell_Function_f64); 163 m.def("cell_Function_f64", &cell_Function_f64);
164 m.def("cell_dofs_Function_f64_p2", &cell_dofs_Function_f64_p2);
157 // m.def("cell_Mesh_f64", &cell_Mesh_f64); 165 // m.def("cell_Mesh_f64", &cell_Mesh_f64);
158 m.def("cell_FunctionSpace_f64", &cell_FunctionSpace_f64); 166 m.def("cell_FunctionSpace_f64", &cell_FunctionSpace_f64);
159 nanobind::class_<CoordValuePair>(m, "CoordValuePair") 167 nanobind::class_<CoordValuePair>(m, "CoordValuePair")
160 .def_rw("x", &CoordValuePair::x) 168 .def_rw("x", &CoordValuePair::x)
161 .def_rw("v", &CoordValuePair::v); 169 .def_rw("v", &CoordValuePair::v);

mercurial