PRISMS-PF Manual
Loading...
Searching...
No Matches
field_container.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: © 2025 PRISMS Center at the University of Michigan
2// SPDX-License-Identifier: GNU Lesser General Public Version 2.1
3
4#pragma once
5
6#include <deal.II/base/config.h>
7#include <deal.II/base/exceptions.h>
8#include <deal.II/base/point.h>
9#include <deal.II/base/symmetric_tensor.h>
10#include <deal.II/base/tensor.h>
11#include <deal.II/lac/vector.h>
12#include <deal.II/matrix_free/evaluation_flags.h>
13#include <deal.II/matrix_free/fe_evaluation.h>
14#include <deal.II/matrix_free/matrix_free.h>
15
22#include <prismspf/core/types.h>
23
24#include <prismspf/config.h>
25
26#include <utility>
27
29
45template <unsigned int dim, unsigned int degree, typename number>
47{
48public:
52 using ScalarValue = dealii::VectorizedArray<number>;
53
57 using VectorValue = dealii::Tensor<1, dim, ScalarValue>;
58
59 template <TensorRank Rank>
60 using Value = std::conditional_t<Rank == TensorRank::Scalar || dim == 1,
62 dealii::Tensor<int(Rank), dim, ScalarValue>>;
63
64 template <TensorRank Rank>
65 using Gradient = dealii::Tensor<int(Rank) + 1, dim, ScalarValue>;
66
67 template <TensorRank Rank>
68 using Hessian = dealii::Tensor<int(Rank) + 2, dim, ScalarValue>;
69
70 template <TensorRank Rank>
71 using FEEval =
72 dealii::FEEvaluation<dim,
73 degree,
74 degree + 1,
75 dealii::Tensor<int(Rank), dim>::n_independent_components,
76 number,
78
82 template <typename ValType>
83 static constexpr TensorRank RankFromVal = []() constexpr
84 {
85 if constexpr (std::is_same_v<ValType, ScalarValue> ||
86 std::is_same_v<ValType, typename ScalarValue::value_type>)
87 {
88 return TensorRank::Scalar;
89 }
90 else
91 {
92 return TensorRank(ValType::rank);
93 }
94 }();
95
99 template <typename GradType>
100 static constexpr TensorRank RankFromGrad = []() constexpr
101 {
102 if constexpr (std::is_same_v<GradType, ScalarValue>)
103 {
104 return TensorRank::Scalar;
105 }
106 else
107 {
108 return TensorRank(GradType::rank - 1);
109 }
110 }();
111
116 template <TensorRank Rank>
118 {
122 using FEEDepPair = std::pair<FEEval<Rank>, EvalFlags>;
123
128 using FEEDepPairPtr = std::shared_ptr<FEEDepPair>;
129
134
139
143 std::vector<FEEDepPairPtr> fe_eval_old;
144
149 EvalFlags integration_flags = EvalFlags::nothing;
150
158
166 unsigned int field_index = -1;
167
174 unsigned int block_index = -1;
175
179 FEEValuationDeps() = default;
180
181 FEEValuationDeps(const MatrixFree<dim, number> &matrix_free,
182 const Dependency &dependency,
183 const SolutionLevel<dim, number> &_solution_level,
184 unsigned int _field_index,
185 unsigned int _block_index,
186 bool is_dst);
187
188 template <DependencyType type>
189 const FEEval<Rank> &
190 get() const;
191
192 template <DependencyType type>
195
196 const FEEval<Rank> &
197 get(DependencyType type) const;
198
200 get(DependencyType type);
201
202 void
203 reinit(unsigned int cell);
204
205 void
206 eval(const BlockVector<number> *_src_solutions, bool plain);
207
208 void
209 reinit_and_eval(unsigned int cell,
210 const BlockVector<number> *_src_solutions,
211 bool plain);
212
213 void
215
216 void
217 integrate();
218
219 void
220 distribute(BlockVector<number> *dst_solutions);
221
222 void
224 };
225
238 FieldContainer(const std::vector<FieldAttributes> &_field_attributes,
239 const SolutionIndexer<dim, number> &_solution_indexer,
240 unsigned int _relative_level,
241 const DependencyMap &dependency_map,
242 const SolveBlock &_solve_block,
243 const MatrixFree<dim, number> &matrix_free);
244
248 void
249 reinit(unsigned int cell);
250
255 void
256 eval(const BlockVector<number> *src_solutions, bool plain);
257
264 void
265 reinit_and_eval(unsigned int cell,
266 const BlockVector<number> *src_solutions,
267 bool plain);
268
273 void
275
279 void
280 integrate();
281
285 void
286 distribute(BlockVector<number> *dst_solutions);
287
291 void
292 distribute(unsigned int field_index, BlockVector<number> *dst_solutions);
293
299 void
301
305 void
306 set_q_point(unsigned int q);
307
311 template <TensorRank Rank, DependencyType type>
312 [[nodiscard]] Value<Rank>
313 get_value(Types::Index field_index) const;
314
318 template <TensorRank Rank>
319 [[nodiscard]] Value<Rank>
320 get_value(Types::Index field_index, DependencyType type) const;
321
325 template <TensorRank Rank, DependencyType type>
326 [[nodiscard]] Gradient<Rank>
327 get_gradient(Types::Index field_index) const;
328
332 template <TensorRank Rank>
333 [[nodiscard]] Gradient<Rank>
334 get_gradient(Types::Index field_index, DependencyType type) const;
335
339 template <TensorRank Rank, DependencyType type>
340 [[nodiscard]] Hessian<Rank>
341 get_hessian(Types::Index field_index) const;
342
346 template <TensorRank Rank>
347 [[nodiscard]] Hessian<Rank>
348 get_hessian(Types::Index field_index, DependencyType type) const;
349
353 template <TensorRank Rank, DependencyType type>
354 [[nodiscard]] Gradient<Rank>
356
360 template <TensorRank Rank>
361 [[nodiscard]] Gradient<Rank>
363
367 template <TensorRank Rank, DependencyType type>
368 [[nodiscard]] Value<Rank>
369 get_laplacian(Types::Index field_index) const;
370
374 template <TensorRank Rank>
375 [[nodiscard]] Value<Rank>
376 get_laplacian(Types::Index field_index, DependencyType type) const;
377
381 template <TensorRank Rank, DependencyType type>
382 [[nodiscard]] ScalarValue
383 get_divergence(Types::Index field_index) const;
384
388 template <TensorRank Rank>
389 [[nodiscard]] ScalarValue
391
395 template <TensorRank Rank, DependencyType type>
396 [[nodiscard]] dealii::SymmetricTensor<2, dim, ScalarValue>
398
402 template <TensorRank Rank>
403 [[nodiscard]] dealii::SymmetricTensor<2, dim, ScalarValue>
405
409 template <TensorRank Rank, DependencyType type>
410 [[nodiscard]] dealii::Tensor<1, (dim == 2 ? 1 : dim), ScalarValue>
411 get_curl(Types::Index field_index) const;
412
416 template <TensorRank Rank>
417 [[nodiscard]] dealii::Tensor<1, (dim == 2 ? 1 : dim), ScalarValue>
418 get_curl(Types::Index field_index, DependencyType type) const;
419
423 [[nodiscard]] dealii::Point<dim, ScalarValue>
424 get_q_point_location() const;
425
429 [[nodiscard]] ScalarValue
430 get_element_volume() const;
431
435 [[nodiscard]] unsigned int
436 get_n_q_points() const;
437
441 template <typename ValType>
442 void
443 set_value_term(Types::Index field_index, const ValType &val);
444
448 template <typename GradType>
449 void
450 set_gradient_term(Types::Index field_index, const GradType &val);
451
455 template <typename ValType>
456 void
457 get_dof_value_to(ValType &destination,
458 Types::Index field_index,
459 unsigned int dof_index);
460
464 template <typename ValType>
465 void
466 submit_dof_value(Types::Index field_index, const ValType &val, unsigned int dof_index);
467
468 constexpr static unsigned int dofs_per_component =
470
471private:
472 template <TensorRank Rank>
473 std::vector<FEEValuationDeps<Rank>> &
475
476 template <TensorRank Rank>
477 const std::vector<FEEValuationDeps<Rank>> &
479
484 void
485 feevaluation_size_valid(Types::Index field_index) const;
486
491 void
492 feevaluation_exists(Types::Index field_index, Types::Index dependency_index) const;
493
498 void
499 access_valid(Types::Index field_index,
500 DependencyType dependency_type,
501 dealii::EvaluationFlags::EvaluationFlags flag) const;
502
506 void
507 submission_valid(Types::Index field_index, DependencyType dependency_type) const;
508
512 const std::vector<FieldAttributes> *field_attributes_ptr;
513
518
522 std::vector<FEEValuationDeps<TensorRank::Scalar>> feeval_deps_scalar;
523
527 std::vector<FEEValuationDeps<TensorRank::Vector>> feeval_deps_vector;
528
533
544
548 unsigned int relative_level;
549
553 unsigned int q_point = 0;
554};
555
556inline static const std::map<DependencyType, std::string> dependency_type_to_string = {
557 {DependencyType::Current, "current"},
558 {DependencyType::OldOne, "old_1" },
559 {DependencyType::OldTwo, "old_2" },
560 {DependencyType::OldThree, "old_3" },
561 {DependencyType::OldFour, "old_4" },
562 {DependencyType::SRC, "src" },
563 {DependencyType::DST, "dst" }
564};
565
566template <unsigned int dim, unsigned int degree, typename number>
567template <TensorRank Rank>
569 const MatrixFree<dim, number> &matrix_free,
570 const Dependency &dependency,
571 const SolutionLevel<dim, number> &_solution_level,
572 unsigned int _field_index,
573 unsigned int _block_index,
574 bool is_dst)
575 : solution_level(&_solution_level)
576 , field_index(_field_index)
577 , block_index(_block_index)
578{
579 // Make an FEEvaluation if the current solution needs to be evaluated
580 if (dependency.flag)
581 {
582 fe_eval = std::make_shared<FEEDepPair>(FEEval<Rank>(matrix_free, field_index),
583 dependency.flag);
584 }
585 // Make FEEvaluations for the the old solutions
586 fe_eval_old.resize(dependency.old_flags.size(), nullptr);
587 for (unsigned int age = 0; age < dependency.old_flags.size(); ++age)
588 {
589 if (dependency.old_flags.at(age)) // kinda redundant... maybe remove?
590 {
591 fe_eval_old[age] =
592 std::make_shared<FEEDepPair>(FEEval<Rank>(matrix_free, field_index),
593 dependency.old_flags.at(age));
594 }
595 }
596 if (dependency.src_flag || is_dst)
597 {
598 fe_eval_src_dst =
599 std::make_shared<FEEDepPair>(FEEval<Rank>(matrix_free, field_index),
600 dependency.src_flag);
601 }
602}
603
604class ExcDepNotInitialized : public dealii::ExceptionBase
605{
606public:
607 explicit ExcDepNotInitialized(DependencyType _dependency_type)
608 : dependency_type(_dependency_type)
609 {}
610
611 const char *
612 what() const noexcept override
613 {
614 return "Access was attempted for a field that was not declared as a "
615 "dependency for the current solve block.\n";
616 }
617
618 void
619 print_info(std::ostream &out) const override
620 {
621 out << what() << std::flush;
622 }
623
624private:
626};
627#ifdef DEBUG
628# define AssertAccessible(fe_eval_pair_ptr, dependency_type) \
629 AssertThrowDebug(block_index != -1, ExcDepNotInitialized(dependency_type)); \
630 AssertThrowDebug(fe_eval_pair_ptr, ExcDepNotInitialized(dependency_type));
631#else
632# define AssertAccessible(fe_eval_pair_ptr, dependency_type)
633#endif
634
635template <unsigned int dim, unsigned int degree, typename number>
636template <TensorRank Rank>
637template <DependencyType Type>
638inline DEAL_II_ALWAYS_INLINE const typename FieldContainer<dim, degree, number>::
639 template FEEval<Rank> &
641{
642 if constexpr (Type == DependencyType::SRC || Type == DependencyType::DST)
643 {
645 return fe_eval_src_dst->first;
646 }
647 else if constexpr (Type == DependencyType::Current)
648 {
650 return fe_eval->first;
651 }
652 else
653 {
656 return fe_eval_old[int(Type) - 1]->first;
657 }
658}
659
660template <unsigned int dim, unsigned int degree, typename number>
661template <TensorRank Rank>
662template <DependencyType Type>
663inline DEAL_II_ALWAYS_INLINE
666{
667 if constexpr (Type == DependencyType::SRC || Type == DependencyType::DST)
668 {
670 return fe_eval_src_dst->first;
671 }
672 else if constexpr (Type == DependencyType::Current)
673 {
675 return fe_eval->first;
676 }
677 else
678 {
681 return fe_eval_old[int(Type) - 1]->first;
682 }
683}
684
685template <unsigned int dim, unsigned int degree, typename number>
686template <TensorRank Rank>
687inline DEAL_II_ALWAYS_INLINE const typename FieldContainer<dim, degree, number>::
688 template FEEval<Rank> &
690 DependencyType type) const
691{
692 if (type == DependencyType::SRC || type == DependencyType::DST)
693 {
695 return fe_eval_src_dst->first;
696 }
697 if (type == DependencyType::Current)
698 {
700 return fe_eval->first;
701 }
702 {
703 AssertThrowDebug(int(type) - 1 < fe_eval_old.size(), ExcDepNotInitialized(type));
704 AssertAccessible(fe_eval_old[int(type) - 1], type);
705 return fe_eval_old[type - 1]->first;
706 }
707}
708
709template <unsigned int dim, unsigned int degree, typename number>
710template <TensorRank Rank>
711inline DEAL_II_ALWAYS_INLINE
714{
715 if (type == DependencyType::SRC || type == DependencyType::DST)
716 {
718 return fe_eval_src_dst->first;
719 }
720 if (type == DependencyType::Current)
721 {
723 return fe_eval->first;
724 }
725 {
726 AssertThrowDebug(int(type) - 1 < fe_eval_old.size(), ExcDepNotInitialized(type));
727 AssertAccessible(fe_eval_old[int(type) - 1], type);
728 return fe_eval_old[int(type) - 1]->first;
729 }
730}
731
732template <unsigned int dim, unsigned int degree, typename number>
733template <TensorRank Rank>
734inline void
736{
737 if (fe_eval)
738 {
739 fe_eval->first.reinit(cell);
740 }
741 for (auto &old_fe_eval : fe_eval_old)
742 {
743 if (old_fe_eval)
744 {
745 old_fe_eval->first.reinit(cell);
746 }
747 }
748 if (fe_eval_src_dst)
749 {
750 fe_eval_src_dst->first.reinit(cell);
751 }
752}
753
754template <unsigned int dim, unsigned int degree, typename number>
755template <TensorRank Rank>
756inline void
758 const BlockVector<number> *_src_solutions,
759 bool plain)
760{
761 // NOTE: `read_dof_values_plain` must be called here so that constraints aren't
762 // implicitly applied. This allows us to have inhomogeneous constraints.
763 if (fe_eval)
764 {
765 fe_eval->first.read_dof_values_plain(solution_level->solutions.block(block_index));
766 fe_eval->first.evaluate(fe_eval->second);
767 }
768 for (unsigned int age = 0; age < fe_eval_old.size(); ++age)
769 {
770 if (FEEDepPairPtr &old_fe_eval = fe_eval_old[age])
771 {
772 old_fe_eval->first.read_dof_values_plain(
773 solution_level->old_solutions[age].block(block_index));
774 old_fe_eval->first.evaluate(old_fe_eval->second);
775 }
776 }
777 if (fe_eval_src_dst && fe_eval_src_dst->second != EvalFlags::nothing)
778 {
779 if (plain)
780 {
781 fe_eval_src_dst->first.read_dof_values_plain(
782 _src_solutions->block(block_index));
783 }
784 else
785 {
786 fe_eval_src_dst->first.read_dof_values(_src_solutions->block(block_index));
787 }
788 fe_eval_src_dst->first.evaluate(fe_eval_src_dst->second);
789 }
790}
791
792template <unsigned int dim, unsigned int degree, typename number>
793template <TensorRank Rank>
794inline void
796 unsigned int cell,
797 const BlockVector<number> *_src_solutions,
798 bool plain)
799{
800 // NOTE: `read_dof_values_plain` must be called here so that constraints aren't
801 // implicitly applied. This allows us to have inhomogeneous constraints.
802 if (fe_eval)
803 {
804 fe_eval->first.reinit(cell);
805 fe_eval->first.read_dof_values_plain(solution_level->solutions.block(block_index));
806 fe_eval->first.evaluate(fe_eval->second);
807 }
808 for (unsigned int age = 0; age < fe_eval_old.size(); ++age)
809 {
810 if (FEEDepPairPtr &old_fe_eval = fe_eval_old[age])
811 {
812 old_fe_eval->first.reinit(cell);
813 old_fe_eval->first.read_dof_values_plain(
814 solution_level->old_solutions[age].block(block_index));
815 old_fe_eval->first.evaluate(old_fe_eval->second);
816 }
817 }
818 if (fe_eval_src_dst)
819 {
820 fe_eval_src_dst->first.reinit(cell);
821 if (fe_eval_src_dst->second != EvalFlags::nothing)
822 {
823 if (plain)
824 {
825 fe_eval_src_dst->first.read_dof_values_plain(
826 _src_solutions->block(block_index));
827 }
828 else
829 {
830 fe_eval_src_dst->first.read_dof_values(_src_solutions->block(block_index));
831 }
832 fe_eval_src_dst->first.evaluate(fe_eval_src_dst->second);
833 }
834 }
835}
836
837template <unsigned int dim, unsigned int degree, typename number>
838template <TensorRank Rank>
839inline void
841{
842 if (fe_eval_src_dst && fe_eval_src_dst->second != EvalFlags::nothing)
843 {
844 fe_eval_src_dst->first.evaluate(fe_eval_src_dst->second);
845 }
846}
847
848template <unsigned int dim, unsigned int degree, typename number>
849template <TensorRank Rank>
850inline void
858
859template <unsigned int dim, unsigned int degree, typename number>
860template <TensorRank Rank>
861inline void
863 BlockVector<number> *dst_solutions)
864{
865 if (fe_eval_src_dst)
866 {
867 fe_eval_src_dst->first.distribute_local_to_global(
868 dst_solutions->block(block_index));
869 }
870}
871
872template <unsigned int dim, unsigned int degree, typename number>
873template <TensorRank Rank>
874inline void
876 BlockVector<number> *dst_solutions)
877{
878 if (fe_eval_src_dst)
879 {
880 fe_eval_src_dst->first.integrate_scatter(integration_flags,
881 dst_solutions->block(block_index));
882 }
883}
884
885template <unsigned int dim, unsigned int degree, typename number>
886inline void
888{
889 for (auto &fe_eval : feeval_deps_scalar)
890 {
891 fe_eval.reinit(cell);
892 }
893 for (auto &fe_eval : feeval_deps_vector)
894 {
895 fe_eval.reinit(cell);
896 }
897 shared_feeval_scalar.reinit(cell);
898}
899
900template <unsigned int dim, unsigned int degree, typename number>
901inline void
903 bool plain)
904{
905 for (auto &fe_eval : feeval_deps_scalar)
906 {
907 fe_eval.eval(src_solutions, plain);
908 }
909 for (auto &fe_eval : feeval_deps_vector)
910 {
911 fe_eval.eval(src_solutions, plain);
912 }
913 // Don't eval `shared_feeval_scalar` because we only use it for information.
914}
915
916template <unsigned int dim, unsigned int degree, typename number>
917inline void
919 unsigned int cell,
920 const BlockVector<number> *src_solutions,
921 bool plain)
922{
923 for (auto &fe_eval : feeval_deps_scalar)
924 {
925 fe_eval.reinit_and_eval(cell, src_solutions, plain);
926 }
927 for (auto &fe_eval : feeval_deps_vector)
928 {
929 fe_eval.reinit_and_eval(cell, src_solutions, plain);
930 }
931 // Don't eval `shared_feeval_scalar` because we only use it for information.
932 shared_feeval_scalar.reinit(cell);
933}
934
935template <unsigned int dim, unsigned int degree, typename number>
936inline void
938{
939 for (auto &fe_eval : feeval_deps_scalar)
940 {
941 fe_eval.eval_without_read();
942 }
943 for (auto &fe_eval : feeval_deps_vector)
944 {
945 fe_eval.eval_without_read();
946 }
947}
948
949template <unsigned int dim, unsigned int degree, typename number>
950inline void
952{
953 const std::vector<FieldAttributes> &field_attributes = *field_attributes_ptr;
954 for (const Types::Index &field_index : solve_block->field_indices)
955 {
956 if (field_attributes[field_index].field_type == TensorRank::Scalar)
957 {
958 feeval_deps_scalar[field_index].integrate();
959 }
960 else /* vector */
961 {
962 feeval_deps_vector[field_index].integrate();
963 }
964 }
965 // Don't integrate `shared_feeval_scalar` because we only use it for information.
966}
967
968template <unsigned int dim, unsigned int degree, typename number>
969inline void
971{
972 const std::vector<FieldAttributes> &field_attributes = *field_attributes_ptr;
973 for (const Types::Index &field_index : solve_block->field_indices)
974 {
975 if (field_attributes[field_index].field_type == TensorRank::Scalar)
976 {
977 feeval_deps_scalar[field_index].distribute(dst_solutions);
978 }
979 else /* vector */
980 {
981 feeval_deps_vector[field_index].distribute(dst_solutions);
982 }
983 }
984}
985
986template <unsigned int dim, unsigned int degree, typename number>
987inline void
989 BlockVector<number> *dst_solutions)
990{
991 const std::vector<FieldAttributes> &field_attributes = *field_attributes_ptr;
992 if (field_attributes[field_index].field_type == TensorRank::Scalar)
993 {
994 feeval_deps_scalar[field_index].distribute(dst_solutions);
995 }
996 else /* vector */
997 {
998 feeval_deps_vector[field_index].distribute(dst_solutions);
999 }
1000}
1001
1002template <unsigned int dim, unsigned int degree, typename number>
1003inline void
1005 BlockVector<number> *dst_solutions)
1006{
1007 const std::vector<FieldAttributes> &field_attributes = *field_attributes_ptr;
1008 for (const Types::Index &field_index : solve_block->field_indices)
1009 {
1010 if (field_attributes[field_index].field_type == TensorRank::Scalar)
1011 {
1012 feeval_deps_scalar[field_index].integrate_and_distribute(dst_solutions);
1013 }
1014 else /* vector */
1015 {
1016 feeval_deps_vector[field_index].integrate_and_distribute(dst_solutions);
1017 }
1018 }
1019}
1020
1021template <unsigned int dim, unsigned int degree, typename number>
1022inline DEAL_II_ALWAYS_INLINE void
1024{
1025 q_point = q;
1026}
1027
1028// there are two catches we can do here.
1029// 1. Dependencies for the dependency type (current, old, src/dst) don't exist.
1030// 2. Dependency is not initialized for values/gradients.
1031// We catch these separately to give more informative error messages.
1032#define GetterTempl(dependency_type) template get<dependency_type>()
1033#define GetterNoTempl(dependency_type) get(dependency_type)
1034#define ReturnGetter(get_handle, Rank, field_index, dependency_type, getter) \
1035 try \
1036 { \
1037 AssertThrowDebug((field_index) < get_relevant_feeval_vector<Rank>().size(), \
1038 dealii::ExcMessage("Error: Field index " + \
1039 std::to_string(field_index) + \
1040 " is not associated with any field.")); \
1041 return get_relevant_feeval_vector<Rank>()[field_index] \
1042 .getter(dependency_type) \
1043 .get_handle(q_point); \
1044 } \
1045 catch (const ExcDepNotInitialized &e) \
1046 { \
1047 std::cerr << "Error when trying to access field with index " << (field_index) \
1048 << " and dependency type " \
1049 << dependency_type_to_string.at(dependency_type) << ":\n" \
1050 << e.what() \
1051 << "Ensure that each dependency is requested in the solve block.\n" \
1052 << std::flush; \
1053 throw; \
1054 } \
1055 catch (const dealii::internal::ExcAccessToUninitializedField &e) \
1056 { \
1057 std::cerr << "Error when trying to access field with index " << (field_index) \
1058 << " and dependency type " \
1059 << dependency_type_to_string.at(dependency_type) \
1060 << ":\nAccess was attempted for values or gradients that were " \
1061 "not requested.\n" \
1062 << std::flush; \
1063 throw; \
1064 }
1065
1066template <unsigned int dim, unsigned int degree, typename number>
1067template <TensorRank Rank, DependencyType type>
1068inline DEAL_II_ALWAYS_INLINE
1071{
1072 ReturnGetter(get_value, Rank, field_index, type, GetterTempl);
1073}
1074
1075template <unsigned int dim, unsigned int degree, typename number>
1076template <TensorRank Rank>
1077inline DEAL_II_ALWAYS_INLINE
1080 DependencyType type) const
1081{
1082 ReturnGetter(get_value, Rank, field_index, type, GetterNoTempl);
1083}
1084
1085template <unsigned int dim, unsigned int degree, typename number>
1086template <TensorRank Rank, DependencyType type>
1087inline DEAL_II_ALWAYS_INLINE
1090{
1091 ReturnGetter(get_gradient, Rank, field_index, type, GetterTempl);
1092}
1093
1094template <unsigned int dim, unsigned int degree, typename number>
1095template <TensorRank Rank>
1096inline DEAL_II_ALWAYS_INLINE
1099 DependencyType type) const
1100{
1101 ReturnGetter(get_gradient, Rank, field_index, type, GetterNoTempl);
1102}
1103
1104template <unsigned int dim, unsigned int degree, typename number>
1105template <TensorRank Rank, DependencyType type>
1106inline DEAL_II_ALWAYS_INLINE
1109{
1110 ReturnGetter(get_hessian, Rank, field_index, type, GetterTempl);
1111}
1112
1113template <unsigned int dim, unsigned int degree, typename number>
1114template <TensorRank Rank>
1115inline DEAL_II_ALWAYS_INLINE
1118 DependencyType type) const
1119{
1120 ReturnGetter(get_hessian, Rank, field_index, type, GetterNoTempl);
1121}
1122
1123template <unsigned int dim, unsigned int degree, typename number>
1124template <TensorRank Rank, DependencyType type>
1125inline DEAL_II_ALWAYS_INLINE
1132
1133template <unsigned int dim, unsigned int degree, typename number>
1134template <TensorRank Rank>
1135inline DEAL_II_ALWAYS_INLINE
1142
1143template <unsigned int dim, unsigned int degree, typename number>
1144template <TensorRank Rank, DependencyType type>
1145inline DEAL_II_ALWAYS_INLINE
1148{
1149 ReturnGetter(get_laplacian, Rank, field_index, type, GetterTempl);
1150}
1151
1152template <unsigned int dim, unsigned int degree, typename number>
1153template <TensorRank Rank>
1154inline DEAL_II_ALWAYS_INLINE
1157 DependencyType type) const
1158{
1159 ReturnGetter(get_laplacian, Rank, field_index, type, GetterNoTempl);
1160}
1161
1162template <unsigned int dim, unsigned int degree, typename number>
1163template <TensorRank Rank, DependencyType type>
1164inline DEAL_II_ALWAYS_INLINE typename FieldContainer<dim, degree, number>::ScalarValue
1166{
1167 static_assert(Rank == 1, "Divergences are only available for vector fields");
1168 ReturnGetter(get_divergence, Rank, field_index, type, GetterTempl);
1169}
1170
1171template <unsigned int dim, unsigned int degree, typename number>
1172template <TensorRank Rank>
1173inline DEAL_II_ALWAYS_INLINE typename FieldContainer<dim, degree, number>::ScalarValue
1175 DependencyType type) const
1176{
1177 static_assert(Rank == 1, "Divergences are only available for vector fields");
1178 ReturnGetter(get_divergence, Rank, field_index, type, GetterNoTempl);
1179}
1180
1181template <unsigned int dim, unsigned int degree, typename number>
1182template <TensorRank Rank, DependencyType type>
1183inline DEAL_II_ALWAYS_INLINE dealii::
1184 SymmetricTensor<2, dim, typename FieldContainer<dim, degree, number>::ScalarValue>
1186 Types::Index field_index) const
1187{
1188 static_assert(Rank == 1, "Symmetric gradients are only available for vector fields");
1189 ReturnGetter(get_symmetric_gradient, Rank, field_index, type, GetterTempl);
1190}
1191
1192template <unsigned int dim, unsigned int degree, typename number>
1193template <TensorRank Rank>
1194inline DEAL_II_ALWAYS_INLINE dealii::
1195 SymmetricTensor<2, dim, typename FieldContainer<dim, degree, number>::ScalarValue>
1197 DependencyType type) const
1198{
1199 static_assert(Rank == 1, "Symmetric gradients are only available for vector fields");
1200 ReturnGetter(get_symmetric_gradient, Rank, field_index, type, GetterNoTempl);
1201}
1202
1203template <unsigned int dim, unsigned int degree, typename number>
1204template <TensorRank Rank, DependencyType type>
1205inline DEAL_II_ALWAYS_INLINE
1206 dealii::Tensor<1,
1207 (dim == 2 ? 1 : dim),
1210{
1211 static_assert(Rank == 1, "Curl is only available for vector fields");
1213 dim > 1,
1214 dealii::ExcMessage(
1215 "Curl is only available for vector fields with dimension greater than 1."));
1216 ReturnGetter(get_curl, Rank, field_index, type, GetterTempl);
1217}
1218
1219template <unsigned int dim, unsigned int degree, typename number>
1220template <TensorRank Rank>
1221inline DEAL_II_ALWAYS_INLINE
1222 dealii::Tensor<1,
1223 (dim == 2 ? 1 : dim),
1226 DependencyType type) const
1227{
1228 static_assert(Rank == 1, "Curl is only available for vector fields");
1230 dim > 1,
1231 dealii::ExcMessage(
1232 "Curl is only available for vector fields with dimension greater than 1."));
1233 ReturnGetter(get_curl, Rank, field_index, type, GetterNoTempl);
1234}
1235
1236template <unsigned int dim, unsigned int degree, typename number>
1237inline DEAL_II_ALWAYS_INLINE
1238 dealii::Point<dim, typename FieldContainer<dim, degree, number>::ScalarValue>
1243
1244template <unsigned int dim, unsigned int degree, typename number>
1245inline DEAL_II_ALWAYS_INLINE typename FieldContainer<dim, degree, number>::ScalarValue
1251
1252template <unsigned int dim, unsigned int degree, typename number>
1253inline DEAL_II_ALWAYS_INLINE unsigned int
1258
1259template <unsigned int dim, unsigned int degree, typename number>
1260template <typename ValType>
1261inline DEAL_II_ALWAYS_INLINE void
1263 const ValType &val)
1264{
1265 AssertThrowDebug((field_index) <
1267 dealii::ExcMessage("Error: Field index " +
1268 std::to_string(field_index) +
1269 " is not associated with any field."));
1270 auto &relevant_feeval_vector =
1272 try
1273 {
1274 relevant_feeval_vector.template get<DependencyType::DST>().submit_value(val,
1275 q_point);
1276 relevant_feeval_vector.integration_flags |= dealii::EvaluationFlags::values;
1277 }
1278 catch (...)
1279 {
1280 std::cerr << "Error when trying to submit value for field with index "
1281 << (field_index)
1282 << ": Error: Submission for field not part of this solve block.\n"
1283 << std::flush;
1284 throw;
1285 }
1286}
1287
1288template <unsigned int dim, unsigned int degree, typename number>
1289template <typename GradType>
1290inline DEAL_II_ALWAYS_INLINE void
1292 const GradType &val)
1293{
1294 AssertThrowDebug((field_index) <
1296 dealii::ExcMessage("Error: Field index " +
1297 std::to_string(field_index) +
1298 " is not associated with any field."));
1299 auto &relevant_feeval_vector =
1301 try
1302 {
1303 relevant_feeval_vector.template get<DependencyType::DST>().submit_gradient(val,
1304 q_point);
1305 relevant_feeval_vector.integration_flags |= dealii::EvaluationFlags::gradients;
1306 }
1307 catch (...)
1308 {
1309 std::cerr << "Error when trying to submit gradient for field with index "
1310 << (field_index)
1311 << ": Error: Submission for field not part of this solve block.\n"
1312 << std::flush;
1313 throw;
1314 }
1315}
1316
1317template <unsigned int dim, unsigned int degree, typename number>
1318template <typename ValType>
1319inline DEAL_II_ALWAYS_INLINE void
1321 Types::Index field_index,
1322 unsigned int dof_index)
1323{
1324 AssertThrowDebug((field_index) <
1326 dealii::ExcMessage("Error: Field index " +
1327 std::to_string(field_index) +
1328 " is not associated with any field."));
1329 auto &relevant_feeval_vector =
1331 try
1332 {
1333 destination =
1334 relevant_feeval_vector.template get<DependencyType::DST>().get_dof_value(
1335 dof_index);
1336 }
1337 catch (...)
1338 {
1339 std::cerr << "Error when trying to get dof value for field with index "
1340 << (field_index) << ": Error: Field not part of this solve block.\n"
1341 << std::flush;
1342 throw;
1343 }
1344}
1345
1346template <unsigned int dim, unsigned int degree, typename number>
1347template <typename ValType>
1348inline DEAL_II_ALWAYS_INLINE void
1350 const ValType &val,
1351 unsigned int dof_index)
1352{
1353 AssertThrowDebug((field_index) <
1355 dealii::ExcMessage("Error: Field index " +
1356 std::to_string(field_index) +
1357 " is not associated with any field."));
1358 auto &relevant_feevals =
1360 try
1361 {
1362 relevant_feevals.template get<DependencyType::DST>().submit_dof_value(val,
1363 dof_index);
1364 }
1365 catch (...)
1366 {
1367 std::cerr << "Error when trying to submit dof value for field with index "
1368 << (field_index)
1369 << ": Error: Submission for field not part of this solve block.\n"
1370 << std::flush;
1371 throw;
1372 }
1373}
1374
1375template <unsigned int dim, unsigned int degree, typename number>
1376template <TensorRank Rank>
1377inline DEAL_II_ALWAYS_INLINE std::vector<
1378 typename FieldContainer<dim, degree, number>::template FEEValuationDeps<Rank>> &
1380{
1381 if constexpr (Rank == TensorRank::Scalar || dim == 1)
1382 {
1383 return feeval_deps_scalar;
1384 }
1385 else if constexpr (Rank == TensorRank::Vector)
1386 {
1387 return feeval_deps_vector;
1388 }
1389}
1390
1391template <unsigned int dim, unsigned int degree, typename number>
1392template <TensorRank Rank>
1393inline DEAL_II_ALWAYS_INLINE const std::vector<
1394 typename FieldContainer<dim, degree, number>::template FEEValuationDeps<Rank>> &
1396{
1397 if constexpr (Rank == TensorRank::Scalar || dim == 1)
1398 {
1399 return feeval_deps_scalar;
1400 }
1401 else if constexpr (Rank == TensorRank::Vector)
1402 {
1403 return feeval_deps_vector;
1404 }
1405}
1406
1407template <unsigned int dim, unsigned int degree, typename number>
1408inline DEAL_II_ALWAYS_INLINE void
1410 [[maybe_unused]] Types::Index field_index) const
1411{
1412 // TODO
1413}
1414
1415template <unsigned int dim, unsigned int degree, typename number>
1416inline DEAL_II_ALWAYS_INLINE void
1418 [[maybe_unused]] Types::Index field_index,
1419 [[maybe_unused]] Types::Index dependency_index) const
1420{
1421 // TODO
1422}
1423
1424template <unsigned int dim, unsigned int degree, typename number>
1425inline DEAL_II_ALWAYS_INLINE void
1427 [[maybe_unused]] Types::Index field_index,
1428 [[maybe_unused]] DependencyType dependency_type,
1429 [[maybe_unused]] dealii::EvaluationFlags::EvaluationFlags flag) const
1430{
1431 // TODO
1432}
1433
1434template <unsigned int dim, unsigned int degree, typename number>
1435inline DEAL_II_ALWAYS_INLINE void
1437 [[maybe_unused]] Types::Index field_index,
1438 [[maybe_unused]] DependencyType dependency_type) const
1439{
1440 // TODO
1441}
1442
1443#undef AssertAccessible
1444#undef ReturnGetter
1445#undef GetterTempl
1446#undef GetterNoTempl
1447
1448PRISMS_PF_END_NAMESPACE
Definition field_container.h:605
ExcDepNotInitialized(DependencyType _dependency_type)
Definition field_container.h:607
const char * what() const noexcept override
Definition field_container.h:612
void print_info(std::ostream &out) const override
Definition field_container.h:619
DependencyType dependency_type
Definition field_container.h:625
This class permits the access of a subset of indexed fields and gives an error if any non-allowed fie...
Definition field_container.h:47
std::vector< FEEValuationDeps< Rank > > & get_relevant_feeval_vector()
void set_value_term(Types::Index field_index, const ValType &val)
Set the value of the specified scalar/vector field.
Value< Rank > get_value(Types::Index field_index, DependencyType type) const
Return the value of the specified field.
void set_gradient_term(Types::Index field_index, const GradType &val)
Set the gradient of the specified scalar/vector field.
void submit_dof_value(Types::Index field_index, const ValType &val, unsigned int dof_index)
Set the dof values directly at a node.
Gradient< Rank > get_hessian_diagonal(Types::Index field_index, DependencyType type) const
Return the diagonal of the hessian of the specified field.
dealii::Tensor< int(Rank)+2, dim, ScalarValue > Hessian
Definition field_container.h:68
void eval(const BlockVector< number > *src_solutions, bool plain)
Read solution vector, and evaluate based on dependency flags for all dependencies.
Definition field_container.h:902
void access_valid(Types::Index field_index, DependencyType dependency_type, dealii::EvaluationFlags::EvaluationFlags flag) const
Check that a variable value/gradient/hessians was marked as needed and thus properly initialized.
Definition field_container.h:1426
Hessian< Rank > get_hessian(Types::Index field_index) const
Return the hessian of the specified field.
Value< Rank > get_laplacian(Types::Index field_index, DependencyType type) const
Return the laplacian of the specified field.
FEEval< TensorRank::Scalar > shared_feeval_scalar
FEEvaluation object for generic cell operations.
Definition field_container.h:543
dealii::Tensor< 1, dim, ScalarValue > VectorValue
Typedef for the basic vector that the user manipulates.
Definition field_container.h:57
unsigned int relative_level
Multigrid level.
Definition field_container.h:548
FieldContainer(const std::vector< FieldAttributes > &_field_attributes, const SolutionIndexer< dim, number > &_solution_indexer, unsigned int _relative_level, const DependencyMap &dependency_map, const SolveBlock &_solve_block, const MatrixFree< dim, number > &matrix_free)
Constructor.
Definition field_container.cc:14
dealii::Tensor< 1,(dim==2 ? 1 :dim), ScalarValue > get_curl(Types::Index field_index) const
Return the curl of the specified field.
ScalarValue get_divergence(Types::Index field_index) const
Return the divergence of the specified field.
Hessian< Rank > get_hessian(Types::Index field_index, DependencyType type) const
Return the hessian of the specified field.
void set_q_point(unsigned int q)
Set the current quadrature point.
Definition field_container.h:1023
void submission_valid(Types::Index field_index, DependencyType dependency_type) const
Check that a value is valid for submission.
Definition field_container.h:1436
dealii::FEEvaluation< dim, degree, degree+1, dealii::Tensor< int(Rank), dim >::n_independent_components, number, ScalarValue > FEEval
Definition field_container.h:71
unsigned int q_point
The quadrature point.
Definition field_container.h:553
static constexpr unsigned int dofs_per_component
Definition field_container.h:468
dealii::Tensor< int(Rank)+1, dim, ScalarValue > Gradient
Definition field_container.h:65
dealii::VectorizedArray< number > ScalarValue
Typedef for the basic value that the user manipulates.
Definition field_container.h:52
void integrate()
Integrate the values.
Definition field_container.h:951
dealii::SymmetricTensor< 2, dim, ScalarValue > get_symmetric_gradient(Types::Index field_index) const
Return the symmetric gradient of the specified field.
void reinit_and_eval(unsigned int cell, const BlockVector< number > *src_solutions, bool plain)
Initialize based on cell, read solution vector, and evaluate based on dependency flags for all depend...
Definition field_container.h:918
Value< Rank > get_laplacian(Types::Index field_index) const
Return the laplacian of the specified field.
ScalarValue get_divergence(Types::Index field_index, DependencyType type) const
Return the divergence of the specified field.
std::vector< FEEValuationDeps< TensorRank::Vector > > feeval_deps_vector
Collection of FEEvaluation dependencies for vector fields.
Definition field_container.h:527
const std::vector< FEEValuationDeps< Rank > > & get_relevant_feeval_vector() const
static constexpr TensorRank RankFromVal
Return the tensor rank from the specified template value.
Definition field_container.h:83
void distribute(BlockVector< number > *dst_solutions)
Distribute the integrated values to a solution vector.
Definition field_container.h:970
void reinit(unsigned int cell)
Initialize based on cell for all dependencies.
Definition field_container.h:887
Gradient< Rank > get_gradient(Types::Index field_index, DependencyType type) const
Return the gradient of the specified field.
std::conditional_t< Rank==TensorRank::Scalar||dim==1, ScalarValue, dealii::Tensor< int(Rank), dim, ScalarValue > > Value
Definition field_container.h:60
std::vector< FEEValuationDeps< TensorRank::Scalar > > feeval_deps_scalar
Collection of FEEvaluation dependencies for scalar fields.
Definition field_container.h:522
void feevaluation_exists(Types::Index field_index, Types::Index dependency_index) const
Check whether the entry for the FEEvaluation is within the bounds of the vector and not a nullptr.
Definition field_container.h:1417
void integrate_and_distribute(BlockVector< number > *dst_solutions)
Integrate the values and distribute from local to global.
Definition field_container.h:1004
const std::vector< FieldAttributes > * field_attributes_ptr
Pointer to the vector of field attributes.
Definition field_container.h:512
void eval_without_read()
Evaluate src to quad pts based on dependency flags. Assume feeval has local dof values already.
Definition field_container.h:937
void get_dof_value_to(ValType &destination, Types::Index field_index, unsigned int dof_index)
Get the dof values directly from a node.
dealii::SymmetricTensor< 2, dim, ScalarValue > get_symmetric_gradient(Types::Index field_index, DependencyType type) const
Return the symmetric gradient of the specified field.
Gradient< Rank > get_gradient(Types::Index field_index) const
Return the gradient of the specified field.
unsigned int get_n_q_points() const
Return the number of quadrature points.
Definition field_container.h:1254
Gradient< Rank > get_hessian_diagonal(Types::Index field_index) const
Return the diagonal of the hessian of the specified field.
dealii::Point< dim, ScalarValue > get_q_point_location() const
Return the quadrature point location.
Definition field_container.h:1239
ScalarValue get_element_volume() const
Return the quadrature point location.
Definition field_container.h:1246
static constexpr TensorRank RankFromGrad
Return the tensor rank from the specified template gradient.
Definition field_container.h:100
const SolveBlock * solve_block
Solve block information.
Definition field_container.h:532
const SolutionIndexer< dim, number > * solution_indexer
Pointer to the solution indexer.
Definition field_container.h:517
dealii::Tensor< 1,(dim==2 ? 1 :dim), ScalarValue > get_curl(Types::Index field_index, DependencyType type) const
Return the curl of the specified field.
void feevaluation_size_valid(Types::Index field_index) const
Check whether the entry for the FEEvaluation is within the bounds of the vector.
Definition field_container.h:1409
Value< Rank > get_value(Types::Index field_index) const
Return the value of the specified field.
Class that provides access to solution vectors spread across different groups.
Definition solution_indexer.h:20
Structure to hold the attributes of a solve-block.
Definition solve_block.h:59
static const dealii::QGaussLobatto< dim > quadrature
Quadrature rule.
Definition system_wide.h:41
std::map< Types::Index, Dependency > DependencyMap
Definition dependencies.h:129
#define AssertThrowDebug(cond, exc)
Definition exceptions.h:26
#define AssertAccessible(fe_eval_pair_ptr, dependency_type)
Definition field_container.h:632
#define GetterNoTempl(dependency_type)
Definition field_container.h:1033
#define GetterTempl(dependency_type)
Definition field_container.h:1032
static const std::map< DependencyType, std::string > dependency_type_to_string
Definition field_container.h:556
#define ReturnGetter(get_handle, Rank, field_index, dependency_type, getter)
Definition field_container.h:1034
@ Value
Use value of the variable as a criterion for refinement.
Definition grid_refiner_criterion.h:31
@ Gradient
Use gradient of the variable as a criterion for refinement.
Definition grid_refiner_criterion.h:36
dealii::LinearAlgebra::distributed::BlockVector< number > BlockVector
Typedef for solution block vector.
Definition group_solution_handler.h:29
Definition conditional_ostreams.cc:20
unsigned int Index
Type for field indices.
Definition types.h:19
Type
Factory function to create appropriate reader based on input file type not a member of ReadFieldBase ...
Definition read_field_factory.h:30
Dependency struct containing evaluation flags for each field.
Definition dependencies.h:30
EvalFlags src_flag
Evaluation flags for the DependencyType::SRC solution.
Definition dependencies.h:42
std::vector< EvalFlags > old_flags
Collection of evaluation flags for the old solutions.
Definition dependencies.h:47
EvalFlags flag
Evaluation flags for the current solution.
Definition dependencies.h:36
FEEDepPairPtr fe_eval_src_dst
FEEvaluation for the src and dst solutions.
Definition field_container.h:138
void eval_without_read()
Definition field_container.h:840
void integrate()
Definition field_container.h:851
std::shared_ptr< FEEDepPair > FEEDepPairPtr
Pointer the the FEEDepPair. We have to use ptrs because we don't want to construct fields we don't ne...
Definition field_container.h:128
const FEEval< Rank > & get() const
EvalFlags integration_flags
Destination integration flags. We use this to integrate value and gradient terms, if they exist.
Definition field_container.h:149
void distribute(BlockVector< number > *dst_solutions)
Definition field_container.h:862
void reinit(unsigned int cell)
Definition field_container.h:735
FEEDepPairPtr fe_eval
FEEvaluation for the current solution.
Definition field_container.h:133
void reinit_and_eval(unsigned int cell, const BlockVector< number > *_src_solutions, bool plain)
Definition field_container.h:795
void eval(const BlockVector< number > *_src_solutions, bool plain)
Definition field_container.h:757
FEEValuationDeps()=default
Default constructor.
std::vector< FEEDepPairPtr > fe_eval_old
Collection of FEEvaluation for old solutions (< n-1 state).
Definition field_container.h:143
void integrate_and_distribute(BlockVector< number > *dst_solutions)
Definition field_container.h:875
const SolutionLevel< dim, number > * solution_level
The solution block.
Definition field_container.h:157
std::pair< FEEval< Rank >, EvalFlags > FEEDepPair
dealii::FEEvaluation object and the evaluation flags.
Definition field_container.h:122
unsigned int block_index
The solution block index.
Definition field_container.h:174
unsigned int field_index
The solution field index.
Definition field_container.h:166
The solution vectors with respect to on some multigrid level.
Definition group_solution_handler.h:58
DependencyType
Internal classification for types of variable dependencies.
Definition type_enums.h:94
@ Current
Definition type_enums.h:101
@ DST
Definition type_enums.h:95
@ OldFour
Definition type_enums.h:105
@ OldThree
Definition type_enums.h:104
@ SRC
Definition type_enums.h:96
@ OldOne
Definition type_enums.h:102
@ OldTwo
Definition type_enums.h:103
TensorRank
Tensor rank of the field.
Definition type_enums.h:52
@ Vector
Definition type_enums.h:55
@ Scalar
Definition type_enums.h:54
dealii::EvaluationFlags::EvaluationFlags EvalFlags
Definition types.h:86