198{
199
201
202
204
205
207
208
210
211
212
213for (const auto & elem : range)
214{
216
217 for (
unsigned int var=0; var<
n_vars; var++)
218 {
220 const Order element_order = fe_type.
order + elem->p_level();
221
224 fe->attach_quadrature_rule(qrule.get());
225
226 const std::vector<Real> & JxW = fe->get_JxW();
227 const std::vector<Point> & q_point = fe->get_xyz();
228 const std::vector<std::vector<Real>> * phi = &(fe->get_phi());
229
230 std::vector<dof_id_type> dof_indices;
231
232 unsigned int matsize = element_order + 1;
234 {
235 matsize *= (element_order + 2);
236 matsize /= 2;
237 }
239 {
240 matsize *= (element_order + 3);
241 matsize /= 3;
242 }
243
244 DenseMatrix<Number> Kp(matsize, matsize);
245 DenseVector<Number> F;
246 DenseVector<Number> Pu_h;
247
248 F.resize(matsize);
249 Pu_h.resize(matsize);
250
251
252 fe->reinit(elem);
253
254 dof_map.dof_indices(elem, dof_indices, var);
255 libmesh_assert_equal_to(dof_indices.size(), phi->size());
256
257 const unsigned int n_dofs = cast_int<unsigned int>(dof_indices.size());
258 const unsigned int n_qp = qrule->n_points();
259
260 for (unsigned int qp = 0; qp < n_qp; qp++)
261 {
262 std::vector<Real> psi =
legepoly(
dim, element_order, q_point[qp], matsize);
263 const unsigned int psi_size = cast_int<unsigned int>(psi.size());
264
265 for (unsigned int i = 0; i < matsize; i++)
266 for (unsigned int j = 0; j < matsize; j++)
267 Kp(i, j) += JxW[qp] * psi[i] * psi[j];
268
270 for (unsigned int i = 0; i < n_dofs; i++)
272
273 for (unsigned int i = 0; i < psi_size; i++)
274 F(i) += JxW[qp] * u_h * psi[i];
275 }
276
277 Kp.lu_solve(F, Pu_h);
278
279
280 std::vector<unsigned int> total_degree_per_index;
281
282 for (unsigned int poly_deg = 0; poly_deg <= static_cast<unsigned int>(element_order); ++poly_deg)
283 {
285 {
286 case 3:
287 for (int i = poly_deg; i >= 0; --i)
288 for (int j = poly_deg - i; j >= 0; --j)
289 {
290 int k = poly_deg - i - j;
291 total_degree_per_index.push_back(i + j + k);
292 }
293 break;
294
295 case 2:
296 for (int i = poly_deg; i >= 0; --i)
297 {
298 int j = poly_deg - i;
299 total_degree_per_index.push_back(i + j);
300 }
301 break;
302
303 case 1:
304 total_degree_per_index.push_back(poly_deg);
305 break;
306
307 default:
308 libmesh_error_msg(
"Invalid dimension dim " <<
dim);
309 }
310 }
311
312
313 std::map<unsigned int, std::vector<Number>> coeff_by_degree;
314
315 for (unsigned int i = 0; i < Pu_h.size(); ++i)
316 {
317 unsigned int degree = total_degree_per_index[i];
318
319
320 if (degree > 0)
321 coeff_by_degree[degree].push_back(Pu_h(i));
322 }
323
324
325 std::vector<unsigned int> degrees;
326 std::vector<double> norms;
327
328 for (const auto & pair : coeff_by_degree)
329 {
330 unsigned int deg = pair.first;
331 const std::vector<Number> & coeffs = pair.second;
332
334 for (const auto & c : coeffs)
336
337 norm = std::sqrt(norm);
338
339 degrees.push_back(deg);
340 norms.push_back(norm);
341 }
342
343
344
345 std::vector<double> log_norms, log_degrees;
346
347 for (unsigned int i = 0; i < degrees.size(); ++i)
348 {
349
350 if (norms[i] > 1e-12)
351 {
352 log_degrees.push_back(std::log(static_cast<double>(degrees[i])));
353 log_norms.push_back(std::log(norms[i]));
354 }
355 }
356
357
358
359 double Sx = 0., Sy = 0., Sxx = 0., Sxy = 0.;
360 const size_t N = log_degrees.size();
361
362 for (size_t i = 0; i < N; ++i)
363 {
364 Sx += log_degrees[i];
365 Sy += log_norms[i];
366 Sxx += log_degrees[i] * log_degrees[i];
367 Sxy += log_degrees[i] * log_norms[i];
368 }
369
370 const double regularity = -
compute_slope(N, Sx, Sy, Sxx, Sxy);
371
372
375 }
376
377}
378
379}
const FEType & variable_type(const unsigned int i) const
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Builds a specific finite element type.
OrderWrapper order
The approximation order of the element (at 0 p-refinement level).
unsigned int mesh_dimension() const
static std::vector< Real > legepoly(const unsigned int dim, const Order order, const Point p, const unsigned int matsize)
static Real compute_slope(int N, Real Sx, Real Sy, Real Sxx, Real Sxy)
Computes slop in a linear regression.
int _extra_order
Extra order to use for quadrature rule.
Number current_solution(const dof_id_type global_dof_number) const
unsigned int n_vars() const
const DofMap & get_dof_map() const
const MeshBase & get_mesh() const
spin_mutex spin_mtx
A convenient spin mutex object which can be used for obtaining locks.