212{
213
215
216
218
219
221
222
224
225
226
227 for (const auto & elem : range)
228 {
229
231
232
233
234 Patch patch(
mesh.processor_id());
235
236
237
238
240 continue;
241
242
243
244
247
248
249
250
251
252 std::vector<Real> new_error_per_cell(1, 0.);
254 new_error_per_cell.resize(patch.size(), 0.);
255
256
257
258 for (
unsigned int var=0; var<
n_vars; var++)
259 {
261#ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
262#ifdef DEBUG
263 bool is_valid_norm_type =
270 norm_type ==
L_INF ||
274#endif
275#else
277 norm_type ==
L_INF ||
283#endif
284
285
286#ifdef DEBUG
287 if (var > 0)
288 {
289
290 bool is_valid_norm_combo =
303 ((norm_type ==
L_INF ||
310 }
311#endif
312
313
315
316
317 const FEType & fe_type = dof_map.variable_type (var);
318
319 const Order element_order = fe_type.order + elem->p_level();
320
321
323
324
326
327
328 fe->attach_quadrature_rule (qrule.get());
329
330
331 const std::vector<Real> & JxW = fe->get_JxW();
332 const std::vector<Point> & q_point = fe->get_xyz();
333
334
335
336
337
338 const std::vector<std::vector<Real>> * phi = nullptr;
339
340
341
342#ifdef NDEBUG
343 if (norm_type ==
L2 ||
345#endif
346 phi = &(fe->get_phi());
347
348 const std::vector<std::vector<RealGradient>> * dphi = nullptr;
354 dphi = &(fe->get_dphi());
355
356#ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
357 const std::vector<std::vector<RealTensor>> * d2phi = nullptr;
360 d2phi = &(fe->get_d2phi());
361#endif
362
363
364 std::vector<dof_id_type> dof_indices;
365
366
367
368 unsigned int matsize = element_order + 1;
370 {
371 matsize *= (element_order + 2);
372 matsize /= 2;
373 }
375 {
376 matsize *= (element_order + 3);
377 matsize /= 3;
378 }
379
380 DenseMatrix<Number> Kp(matsize,matsize);
381 DenseVector<Number> F, Fx, Fy, Fz, Fxy, Fxz, Fyz;
382 DenseVector<Number> Pu_h, Pu_x_h, Pu_y_h, Pu_z_h, Pu_xy_h, Pu_xz_h, Pu_yz_h;
383 if (norm_type ==
L2 ||
385 {
386 F.resize(matsize); Pu_h.resize(matsize);
387 }
392 {
393 Fx.resize(matsize); Pu_x_h.resize(matsize);
394#if LIBMESH_DIM > 1
395 Fy.resize(matsize); Pu_y_h.resize(matsize);
396#endif
397#if LIBMESH_DIM > 2
398 Fz.resize(matsize); Pu_z_h.resize(matsize);
399#endif
400 }
402 {
403 Fx.resize(matsize); Pu_x_h.resize(matsize);
404 }
406 {
407 libmesh_assert_greater (LIBMESH_DIM, 1);
408 Fy.resize(matsize); Pu_y_h.resize(matsize);
409 }
411 {
412 libmesh_assert_greater (LIBMESH_DIM, 2);
413 Fz.resize(matsize); Pu_z_h.resize(matsize);
414 }
415
416#if LIBMESH_DIM > 1
419 {
420 Fxy.resize(matsize); Pu_xy_h.resize(matsize);
421#if LIBMESH_DIM > 2
422 Fxz.resize(matsize); Pu_xz_h.resize(matsize);
423 Fyz.resize(matsize); Pu_yz_h.resize(matsize);
424#endif
425 }
426#endif
427
428
429
430
431 for (const auto & e_p : patch)
432 {
433
434 fe->reinit (e_p);
435
436
437
438 dof_map.dof_indices (e_p, dof_indices, var);
439 libmesh_assert_equal_to (dof_indices.size(), phi->size());
440
441 const unsigned int n_dofs =
442 cast_int<unsigned int>(dof_indices.size());
443 const unsigned int n_qp = qrule->n_points();
444
445
446
447 for (unsigned int qp=0; qp<n_qp; qp++)
448 {
449
450 std::vector<Real> psi(
specpoly(
dim, element_order, q_point[qp], matsize));
451
452 const unsigned int psi_size = cast_int<unsigned int>(psi.size());
453
454
455 const unsigned int m = Kp.m(), n = Kp.n();
456 for (unsigned int i=0; i<m; i++)
457 for (unsigned int j=0; j<n; j++)
458 Kp(i,j) += JxW[qp]*psi[i]*psi[j];
459
460 if (norm_type ==
L2 ||
462 {
463
464
466
467 for (unsigned int i=0; i<n_dofs; i++)
469
470
471 for (unsigned int i=0; i != psi_size; i++)
472 F(i) += JxW[qp]*u_h*psi[i];
473
474 }
477 {
478
479
481
482 for (unsigned int i=0; i<n_dofs; i++)
485
486
487 for (unsigned int i=0; i != psi_size; i++)
488 {
489 Fx(i) += JxW[qp]*grad_u_h(0)*psi[i];
490#if LIBMESH_DIM > 1
491 Fy(i) += JxW[qp]*grad_u_h(1)*psi[i];
492#endif
493#if LIBMESH_DIM > 2
494 Fz(i) += JxW[qp]*grad_u_h(2)*psi[i];
495#endif
496 }
497 }
499 {
500
501
503
504 for (unsigned int i=0; i<n_dofs; i++)
507
508
509 for (unsigned int i=0; i != psi_size; i++)
510 {
511 Fx(i) += JxW[qp]*grad_u_h(0)*psi[i];
512 }
513 }
514#if LIBMESH_DIM > 1
516 {
517
518
520
521 for (unsigned int i=0; i<n_dofs; i++)
524
525
526 for (unsigned int i=0; i != psi_size; i++)
527 {
528 Fy(i) += JxW[qp]*grad_u_h(1)*psi[i];
529 }
530 }
531#endif
532#if LIBMESH_DIM > 2
534 {
535
536
538
539 for (unsigned int i=0; i<n_dofs; i++)
542
543
544 for (unsigned int i=0; i != psi_size; i++)
545 {
546 Fz(i) += JxW[qp]*grad_u_h(2)*psi[i];
547 }
548 }
549#endif
552 {
553#ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
554
555
557
558 for (unsigned int i=0; i<n_dofs; i++)
561
562
563 for (unsigned int i=0; i != psi_size; i++)
564 {
565 Fx(i) += JxW[qp]*hess_u_h(0,0)*psi[i];
566#if LIBMESH_DIM > 1
567 Fy(i) += JxW[qp]*hess_u_h(1,1)*psi[i];
568 Fxy(i) += JxW[qp]*hess_u_h(0,1)*psi[i];
569#endif
570#if LIBMESH_DIM > 2
571 Fz(i) += JxW[qp]*hess_u_h(2,2)*psi[i];
572 Fxz(i) += JxW[qp]*hess_u_h(0,2)*psi[i];
573 Fyz(i) += JxW[qp]*hess_u_h(1,2)*psi[i];
574#endif
575 }
576#else
577 libmesh_error_msg("ERROR: --enable-second-derivatives is required \nfor _sobolev_order == 2!");
578#endif
579 }
580 else
582 }
583 }
584
585
586
587
588
589
590
591 if (norm_type ==
L2 ||
593 {
594 Kp.lu_solve(F, Pu_h);
595 }
600 {
601 Kp.lu_solve (Fx, Pu_x_h);
602#if LIBMESH_DIM > 1
603 Kp.lu_solve (Fy, Pu_y_h);
604#endif
605#if LIBMESH_DIM > 2
606 Kp.lu_solve (Fz, Pu_z_h);
607#endif
608 }
610 {
611 Kp.lu_solve (Fx, Pu_x_h);
612 }
614 {
615 Kp.lu_solve (Fy, Pu_y_h);
616 }
618 {
619 Kp.lu_solve (Fz, Pu_z_h);
620 }
621
622#if LIBMESH_DIM > 1
625 {
626 Kp.lu_solve(Fxy, Pu_xy_h);
627#if LIBMESH_DIM > 2
628 Kp.lu_solve(Fxz, Pu_xz_h);
629 Kp.lu_solve(Fyz, Pu_yz_h);
630#endif
631 }
632#endif
633
634
635
636
637
638 Patch::const_iterator patch_re_it;
639 Patch::const_iterator patch_re_end;
640
641
642 Patch patch_re(
mesh.processor_id());
643
645 {
646
647 patch_re_it = patch.begin();
648 patch_re_end = patch.end();
649 }
650 else
651 {
652
653
654 patch_re.build_around_element (elem, 0,
656
657
658 patch_re_it = patch_re.begin();
659 patch_re_end = patch_re.end();
660 }
661
662
663
664
665
666
667
668
669 for (unsigned int e = 0 ; patch_re_it != patch_re_end; ++patch_re_it, ++e)
670 {
671
672
673
674 const Elem * e_p = *patch_re_it;
675
676
678
679
680
681
682
683
685 continue;
686
687
688 fe->reinit (e_p);
689
690
691
692 dof_map.dof_indices (e_p, dof_indices, var);
693 libmesh_assert_equal_to (dof_indices.size(), phi->size());
694
695
696 const unsigned int n_dofs =
697 cast_int<unsigned int>(dof_indices.size());
698
699
700 Real element_error = 0;
701
702 const Order qorder = fe_type.order + e_p->p_level();
703
704
705 QGrid samprule (
dim, qorder);
706
709 fe->attach_quadrature_rule (&samprule);
710
711
712 const unsigned int n_sp =
713 cast_int<unsigned int>(JxW.size());
714
715
716 for (unsigned int sp=0; sp<n_sp; sp++)
717 {
718
719
720 std::vector<Number> temperr(6,0.0);
721
722 if (norm_type ==
L2 ||
724 {
725
727
728 for (unsigned int i=0; i<n_dofs; i++)
730
731
732 std::vector<Real> psi(
specpoly(
dim, element_order, q_point[sp], matsize));
733 for (unsigned int i=0; i<matsize; i++)
734 {
735 temperr[0] += psi[i]*Pu_h(i);
736 }
737
738 temperr[0] -= u_h;
739 }
742 {
743
745
746 for (unsigned int i=0; i<n_dofs; i++)
749
750
751 std::vector<Real> psi(
specpoly(
dim, element_order, q_point[sp], matsize));
752
753 for (unsigned int i=0; i<matsize; i++)
754 {
755 temperr[0] += psi[i]*Pu_x_h(i);
756#if LIBMESH_DIM > 1
757 temperr[1] += psi[i]*Pu_y_h(i);
758#endif
759#if LIBMESH_DIM > 2
760 temperr[2] += psi[i]*Pu_z_h(i);
761#endif
762 }
763 temperr[0] -= grad_u_h(0);
764#if LIBMESH_DIM > 1
765 temperr[1] -= grad_u_h(1);
766#endif
767#if LIBMESH_DIM > 2
768 temperr[2] -= grad_u_h(2);
769#endif
770 }
772 {
773
775
776 for (unsigned int i=0; i<n_dofs; i++)
779
780
781 std::vector<Real> psi(
specpoly(
dim, element_order, q_point[sp], matsize));
782 for (unsigned int i=0; i<matsize; i++)
783 {
784 temperr[0] += psi[i]*Pu_x_h(i);
785 }
786
787 temperr[0] -= grad_u_h(0);
788 }
789#if LIBMESH_DIM > 1
791 {
792
794
795 for (unsigned int i=0; i<n_dofs; i++)
798
799
800 std::vector<Real> psi(
specpoly(
dim, element_order, q_point[sp], matsize));
801 for (unsigned int i=0; i<matsize; i++)
802 {
803 temperr[1] += psi[i]*Pu_y_h(i);
804 }
805
806 temperr[1] -= grad_u_h(1);
807 }
808#endif
809#if LIBMESH_DIM > 2
811 {
812
814
815 for (unsigned int i=0; i<n_dofs; i++)
818
819
820 std::vector<Real> psi(
specpoly(
dim, element_order, q_point[sp], matsize));
821 for (unsigned int i=0; i<matsize; i++)
822 {
823 temperr[2] += psi[i]*Pu_z_h(i);
824 }
825
826 temperr[2] -= grad_u_h(2);
827 }
828#endif
831 {
832#ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
833
835
836 for (unsigned int i=0; i<n_dofs; i++)
839
840
841 std::vector<Real> psi(
specpoly(
dim, element_order, q_point[sp], matsize));
842 for (unsigned int i=0; i<matsize; i++)
843 {
844 temperr[0] += psi[i]*Pu_x_h(i);
845#if LIBMESH_DIM > 1
846 temperr[1] += psi[i]*Pu_y_h(i);
847 temperr[3] += psi[i]*Pu_xy_h(i);
848#endif
849#if LIBMESH_DIM > 2
850 temperr[2] += psi[i]*Pu_z_h(i);
851 temperr[4] += psi[i]*Pu_xz_h(i);
852 temperr[5] += psi[i]*Pu_yz_h(i);
853#endif
854 }
855
856 temperr[0] -= hess_u_h(0,0);
857#if LIBMESH_DIM > 1
858 temperr[1] -= hess_u_h(1,1);
859 temperr[3] -= hess_u_h(0,1);
860#endif
861#if LIBMESH_DIM > 2
862 temperr[2] -= hess_u_h(2,2);
863 temperr[4] -= hess_u_h(0,2);
864 temperr[5] -= hess_u_h(1,2);
865#endif
866#else
867 libmesh_error_msg("ERROR: --enable-second-derivatives is required \nfor _sobolev_order == 2!");
868#endif
869 }
870
871
872
873
874 if (norm_type ==
L_INF)
875 element_error = std::max(element_error, std::abs(temperr[0]));
877 for (unsigned int i=0; i != LIBMESH_DIM; ++i)
878 element_error = std::max(element_error, std::abs(temperr[i]));
880 for (unsigned int i=0; i != 6; ++i)
881 element_error = std::max(element_error, std::abs(temperr[i]));
882 else if (norm_type ==
L2)
885 for (unsigned int i=0; i != LIBMESH_DIM; ++i)
894 {
895 for (unsigned int i=0; i != LIBMESH_DIM; ++i)
897
898 for (unsigned int i=3; i != 6; ++i)
900 }
901
902 }
903
904 if (norm_type ==
L_INF ||
908 else if (norm_type ==
L2 ||
915 else
917 }
918
919 }
920
921
922
923
924
925
926
927 Patch::const_iterator patch_re_it;
928 Patch::const_iterator patch_re_end;
929
930
931 Patch current_elem_patch(
mesh.processor_id());
932
934 {
935
936 patch_re_it = patch.begin();
937 patch_re_end = patch.end();
938 }
939 else
940 {
941
942
943 current_elem_patch.build_around_element (elem, 0,
945
946
947 patch_re_it = current_elem_patch.begin();
948 patch_re_end = current_elem_patch.end();
949 }
950
951
952 for (unsigned int i = 0 ; patch_re_it != patch_re_end; ++patch_re_it, ++i)
953 {
954
955 const Elem * e_p = *patch_re_it;
956
957
959
960
967 {
972 }
973 else
974 {
982 }
983
984 }
985
986 }
987
988}
SystemNorm error_norm
When estimating the error in a single system, the error_norm is used to control the scaling and norm ...
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Builds a specific finite element type.
unsigned int mesh_dimension() const
unsigned int target_patch_size
The PatchErrorEstimator will build patches of at least this many elements to perform estimates.
static std::vector< Real > specpoly(const unsigned int dim, const Order order, const Point p, const unsigned int matsize)
Patch::PMF patch_growth_strategy
The PatchErrorEstimator will use this pointer to a Patch member function when growing patches.
int _extra_order
Extra order to use for quadrature rule.
FEMNormType type(unsigned int var) const
Real weight(unsigned int var) const
Real weight_sq(unsigned int var) const
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
void add_scaled(const TypeTensor< T2 > &, const T &)
Add a scaled tensor to this tensor without creating a temporary.
void add_scaled(const TypeVector< T2 > &, const T &)
Add a scaled value to this vector without creating a temporary.
spin_mutex spin_mtx
A convenient spin mutex object which can be used for obtaining locks.
std::string enum_to_string(const T e)
DIE A HORRIBLE DEATH HERE typedef float ErrorVectorReal
NumberVectorValue Gradient
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real