FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
function_integral_info.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6#pragma once
7
8#include <kernel/assembly/base.hpp>
9#include <kernel/analytic/function.hpp>
10#include <kernel/util/dist.hpp>
11#include <kernel/lafem/dense_vector.hpp>
12#include <kernel/lafem/dense_vector_blocked.hpp>
13
14namespace FEAT
15{
16 namespace Assembly
17 {
43 template<typename DataType_, typename ValueType_, typename GradientType_, typename HessianType_>
45 {
46 public:
48 typedef DataType_ DataType;
50 typedef ValueType_ ValueType;
52 typedef GradientType_ GradientType;
54 typedef HessianType_ HessianType;
55
58
65 ValueType_ value;
66
73 GradientType_ grad;
74
81 HessianType_ hess;
82
91 DataType_ norm_h0_sqr;
92
101 DataType_ norm_h1_sqr;
102
111 DataType_ norm_h2_sqr;
112
121 DataType_ norm_l1;
122
131 DataType_ norm_lmax;
132
140 ValueType_ norm_l1_comp;
142 ValueType_ norm_lmax_comp;
143
154
165
166 private:
168 static void _push_lmax(DataType_& a, const DataType_& b)
169 {
170 a = Math::max(a, b);
171 }
172
173 template<int n_, int sn_>
174 static void _push_lmax(Tiny::Vector<DataType_, n_, sn_>& a, const Tiny::Vector<DataType_, n_, sn_>& b)
175 {
176 for(int i(0); i < n_; ++i)
177 a[i] = Math::max(a[i], b[i]);
178 }
179
180 static void _write_to(DataType_* ptr, std::size_t& k, const DataType_& x)
181 {
182 ptr[k] = x;
183 ++k;
184 }
185
186 template<int n_, int sn_>
187 static void _write_to(DataType_* ptr, std::size_t& k, const Tiny::Vector<DataType_, n_, sn_>& x)
188 {
189 for(int i(0); i < n_; ++i, ++k)
190 ptr[k] = x[i];
191 }
192
193 template<int m_, int n_, int sm_, int sn_>
194 static void _write_to(DataType_* ptr, std::size_t& k, const Tiny::Matrix<DataType_, m_, n_, sm_, sn_>& x)
195 {
196 for(int i(0); i < m_; ++i)
197 _write_to(ptr, k, x[i]);
198 }
199
200 template<int l_, int m_, int n_, int sl_, int sm_, int sn_>
201 static void _write_to(DataType_* ptr, std::size_t& k, const Tiny::Tensor3<DataType_, l_, m_, n_, sl_, sm_, sn_>& x)
202 {
203 for(int i(0); i < l_; ++i)
204 _write_to(ptr, k, x[i]);
205 }
206
207 static void _read_from(DataType_* ptr, std::size_t& k, DataType_& x)
208 {
209 x = ptr[k];
210 ++k;
211 }
212
213 template<int n_, int sn_>
214 static void _read_from(DataType_* ptr, std::size_t& k, Tiny::Vector<DataType_, n_, sn_>& x)
215 {
216 for(int i(0); i < n_; ++i, ++k)
217 x[i] = ptr[k];
218 }
219
220 template<int m_, int n_, int sm_, int sn_>
221 static void _read_from(DataType_* ptr, std::size_t& k, Tiny::Matrix<DataType_, m_, n_, sm_, sn_>& x)
222 {
223 for(int i(0); i < m_; ++i)
224 _read_from(ptr, k, x[i]);
225 }
226
227 template<int l_, int m_, int n_, int sl_, int sm_, int sn_>
228 static void _read_from(DataType_* ptr, std::size_t& k, Tiny::Tensor3<DataType_, l_, m_, n_, sl_, sm_, sn_>& x)
229 {
230 for(int i(0); i < l_; ++i)
231 _read_from(ptr, k, x[i]);
232 }
233
234 static String _print_val(const DataType_& x, int prec)
235 {
236 return stringify_fp_sci(x, prec);
237 }
238
239 template<int n_, int sn_>
240 static String _print_val(const Tiny::Vector<DataType_, n_, sn_>& x, int prec)
241 {
242 String s = "[";
243 for(int i(0); i < n_; ++i)
244 (s += " ") += stringify_fp_sci(x[i], prec);
245 s += " ]";
246 return s;
247 }
248
249 static String _print_val_sqrt(const DataType_& x, int prec)
250 {
251 return stringify_fp_sci(Math::sqrt(x), prec);
252 }
253
254 template<int n_, int sn_>
255 static String _print_val_sqrt(const Tiny::Vector<DataType_, n_, sn_>& x, int prec)
256 {
257 String s = "[";
258 for(int i(0); i < n_; ++i)
259 (s += " ") += stringify_fp_sci(Math::sqrt(x[i]), prec);
260 s += " ]";
261 return s;
262 }
263
264 static String _print_norm(const DataType_& x, const DataType_&, int prec)
265 {
266 return _print_val(x, prec);
267 }
268
269 template<int n_, int sn_>
270 static String _print_norm(const DataType_& x, const Tiny::Vector<DataType_, n_, sn_>& v, int prec)
271 {
272 return _print_val(x, prec) + " " + _print_val(v, prec);
273 }
274
275 static String _print_norm_sqrt(const DataType_& x, const DataType_&, int prec)
276 {
277 return _print_val(Math::sqrt(x), prec);
278 }
279
280 template<int n_, int sn_>
281 static String _print_norm_sqrt(const DataType_& x, const Tiny::Vector<DataType_, n_, sn_>& v, int prec)
282 {
283 return _print_val(Math::sqrt(x), prec) + " " + _print_val_sqrt(v, prec);
284 }
285
286 template<int m_, int n_, int sm_, int sn_>
287 static DataType _calc_vorticity(const Tiny::Matrix<DataType, m_, n_, sm_, sn_>&)
288 {
289 // R^m -> R^n with m != n ==> nothing to do here
290 return DataType(0);
291 }
292
293 template<int sm_, int sn_>
294 static DataType _calc_vorticity(const Tiny::Matrix<DataType, 2, 2, sm_, sn_>& g)
295 {
296 // 2D: (dx u2 - dy u1)^2
297 // J_ij = d/d_j f_i ==> (J_01 - J_10)^2
298 return Math::sqr(g[1][0] - g[0][1]);
299 }
300
301 template<int sm_, int sn_>
302 static DataType _calc_vorticity(const Tiny::Matrix<DataType, 3, 3, sm_, sn_>& g)
303 {
304 // 3D: (dy u3 - dz u2)^2 + (dz u1 - dx u3)^2 + (dx u2 - dy u1)
305 return
306 Math::sqr(g[2][1] - g[1][2]) + // dy u3 - dz u2 = J_21 - J_12
307 Math::sqr(g[0][2] - g[2][0]) + // dz u1 - dx u3 = J_02 - J_20
308 Math::sqr(g[1][0] - g[0][1]); // dx u2 - dy u1 = J_10 - J_01
309 }
310
312
313 public:
318 max_der(0),
319 value(DataType(0)),
320 grad(DataType(0)),
321 hess(DataType(0)),
325 norm_l1(DataType(0)),
334 {
335 }
336
340 void format()
341 {
342 max_der = 0;
349 norm_l1 = DataType(0);
350 norm_lmax = DataType(0);
358 }
359
368 void push(const FunctionIntegralInfo& other)
369 {
370 value += other.value;
371 grad += other.grad;
372 hess += other.hess;
373 norm_h0_sqr += other.norm_h0_sqr;
374 norm_h1_sqr += other.norm_h1_sqr;
375 norm_h2_sqr += other.norm_h2_sqr;
376 norm_l1 += other.norm_l1;
377 _push_lmax(norm_lmax, other.norm_lmax);
378 norm_h0_sqr_comp += other.norm_h0_sqr_comp;
379 norm_h1_sqr_comp += other.norm_h1_sqr_comp;
380 norm_h2_sqr_comp += other.norm_h2_sqr_comp;
381 norm_l1_comp += other.norm_l1_comp;
382 _push_lmax(norm_lmax_comp, other.norm_lmax_comp);
383 divergence_l2_sqr += other.divergence_l2_sqr;
384 vorticity_l2_sqr += other.vorticity_l2_sqr;
385 }
386
398 void add_value(DataType omega, const DataType& v)
399 {
400 value += omega * v;
401 const DataType av = Math::abs(v);
402 const DataType sv = Math::sqr(v);
403 norm_h0_sqr += omega * sv;
404 norm_l1 += omega * av;
406 }
407
419 template<int n_, int sn_>
421 {
422 value += omega * v;
423 for(int i(0); i < n_; ++i)
424 {
425 const DataType av = Math::abs(v[i]);
426 const DataType sv = Math::sqr(v[i]);
427 norm_h0_sqr += omega * sv;
428 norm_l1 += omega * av;
430 norm_h0_sqr_comp[i] += omega * sv;
431 norm_l1_comp[i] += omega * av;
433 }
434 }
435
447 template<int n_, int sn_>
449 {
450 grad += omega * g;
451 norm_h1_sqr += omega * g.norm_euclid_sqr();
452 }
453
465 template<int m_, int n_, int sm_, int sn_>
467 {
468 grad += omega * g;
469 for(int i(0); i < m_; ++i)
470 {
471 const DataType sv = g[i].norm_euclid_sqr();
472 norm_h1_sqr += omega * sv;
473 norm_h1_sqr_comp[i] += omega * sv;
474 }
475
476 // add divergence component
477 divergence_l2_sqr += omega * Math::sqr(g.trace());
478
479 // add vorticity component (if possible)
480 vorticity_l2_sqr += omega * _calc_vorticity(g);
481 }
482
494 template<int m_, int n_, int sm_, int sn_>
496 {
497 hess += omega * h;
498 norm_h2_sqr += omega * h.norm_hessian_sqr();
499 }
500
512 template<int l_, int m_, int n_, int sl_, int sm_, int sn_>
514 {
515 hess += omega * h;
516 for(int i(0); i < l_; ++i)
517 {
518 const DataType sv = h[i].norm_hessian_sqr();
519 norm_h2_sqr += omega * sv;
520 norm_h2_sqr_comp[i] += omega * sv;
521 }
522 }
523
533 void synchronize(const Dist::Comm& comm)
534 {
535 // nothing to do here?
536 if(comm.size() <= 1)
537 return;
538
539 static constexpr std::size_t max_len = std::size_t(7) +
540 (6u*sizeof(ValueType) + sizeof(GradientType) + sizeof(HessianType)) / sizeof(DataType);
541 DataType v[max_len];
542
543 // write all stuff to array
544 std::size_t k = 0u;
545 _write_to(v, k, value);
546 _write_to(v, k, grad);
547 _write_to(v, k, hess);
548 _write_to(v, k, norm_h0_sqr);
549 _write_to(v, k, norm_h1_sqr);
550 _write_to(v, k, norm_h2_sqr);
551 _write_to(v, k, norm_l1);
552 _write_to(v, k, norm_h0_sqr_comp);
553 _write_to(v, k, norm_h1_sqr_comp);
554 _write_to(v, k, norm_h2_sqr_comp);
555 _write_to(v, k, norm_l1_comp);
556 _write_to(v, k, divergence_l2_sqr);
557 _write_to(v, k, vorticity_l2_sqr);
558 XASSERT(k <= max_len);
559
560 // synchronize
561 comm.allreduce(v, v, k, Dist::op_sum);
562
563 // read stuff form array
564 k = std::size_t(0u);
565 _read_from(v, k, value);
566 _read_from(v, k, grad);
567 _read_from(v, k, hess);
568 _read_from(v, k, norm_h0_sqr);
569 _read_from(v, k, norm_h1_sqr);
570 _read_from(v, k, norm_h2_sqr);
571 _read_from(v, k, norm_l1);
572 _read_from(v, k, norm_h0_sqr_comp);
573 _read_from(v, k, norm_h1_sqr_comp);
574 _read_from(v, k, norm_h2_sqr_comp);
575 _read_from(v, k, norm_l1_comp);
576 _read_from(v, k, divergence_l2_sqr);
577 _read_from(v, k, vorticity_l2_sqr);
578
579 // write lmax values
580 k = std::size_t(0u);
581 _write_to(v, k, norm_lmax);
582 _write_to(v, k, norm_lmax_comp);
583
584 // synchronize
585 comm.allreduce(v, v, k, Dist::op_max);
586
587 // read lmax values
588 k = std::size_t(0u);
589 _read_from(v, k, norm_lmax);
590 _read_from(v, k, norm_lmax_comp);
591 }
592
612 String print_norms(int precision = 0, std::size_t pad_size = 15u, char pad_char = '.') const
613 {
614 String s;
615 s += String("H0-Norm").pad_back(pad_size, pad_char) + ": "
616 + _print_norm_sqrt(norm_h0_sqr, norm_h0_sqr_comp, precision) + "\n";
617 if(max_der >= 1)
618 s += String("H1-Norm").pad_back(pad_size, pad_char) + ": "
619 + _print_norm_sqrt(norm_h1_sqr, norm_h1_sqr_comp, precision) + "\n";
620 if(max_der >= 2)
621 s += String("H2-Norm").pad_back(pad_size, pad_char) + ": "
622 + _print_norm_sqrt(norm_h2_sqr, norm_h2_sqr_comp, precision) + "\n";
623 s += String("L1-Norm").pad_back(pad_size, pad_char) + ": "
624 + _print_norm(norm_l1, norm_l1_comp, precision) + "\n";
625 s += String("Lmax-Norm").pad_back(pad_size, pad_char) + ": "
626 + _print_norm(norm_lmax, norm_lmax_comp, precision);
627 return s;
628 }
629
647 String print_field_info(int precision = 0, std::size_t pad_size = 15u, char pad_char = '.') const
648 {
649 String s;
650 s += String("Kinetic Energy").pad_back(pad_size, pad_char) + ": "
651 + _print_val(norm_h0_sqr * DataType(0.5), precision) + "\n";
652 if(max_der >= 1)
653 {
654 s += String("Vorticity").pad_back(pad_size, pad_char) + ": "
655 + _print_val_sqrt(vorticity_l2_sqr, precision) + "\n";
656 s += String("Divergence").pad_back(pad_size, pad_char) + ": "
657 + _print_val_sqrt(divergence_l2_sqr, precision) + "\n";
658 }
659 return s;
660 }
661 }; // class FunctionIntegralInfo<...>
662
678 template<typename FuncIntInfo_, typename CellVector_>
680 {
681 public:
682 FuncIntInfo_ integral_info;
683 CellVector_ vec;
684
685 FunctionCellIntegralInfo() = default;
686
688 integral_info(),
689 vec(other.vec.clone(LAFEM::CloneMode::Weak))
690 {
691 integral_info.push(other.integral_info);
692 }
693
695 {
696 if(&other == this)
697 return *this;
698 integral_info.format();
699 integral_info.push(other.integral_info);
700 vec.clone(other.vec, LAFEM::CloneMode::Weak);
701 }
702
703 explicit FunctionCellIntegralInfo(const FuncIntInfo_& info, const CellVector_& in_vec) :
704 integral_info(),
705 vec(in_vec.clone(LAFEM::CloneMode::Weak))
706 {
707 integral_info.push(info);
708 }
709
710 explicit FunctionCellIntegralInfo(const FuncIntInfo_& info, CellVector_&& in_vec) :
711 integral_info(),
712 vec(std::move(in_vec))
713 {
714 integral_info.push(info);
715 }
716
717 }; // class FunctionCellIntegralInfo<...>
718
731 template<typename DataType_, typename Function_>
733 {
735 typedef FunctionIntegralInfo<DataType_,
739 };
740
758 template<typename Vector_, typename Space_>
760
762 template<typename DT_, typename IT_, typename Space_>
763 struct DiscreteFunctionIntegral<LAFEM::DenseVector<DT_, IT_>, Space_>
764 {
766 typedef FunctionIntegralInfo<DT_, DT_,
769 };
770
772 template<typename DT_, typename IT_, int bs_, typename Space_>
773 struct DiscreteFunctionIntegral<LAFEM::DenseVectorBlocked<DT_, IT_, bs_>, Space_>
774 {
779 };
780
782 namespace Intern
783 {
784 template<int max_der_>
785 struct AnaFunIntJobHelper;
786
787 template<>
788 struct AnaFunIntJobHelper<0>
789 {
790 template<typename FID_, typename DT_, typename FEV_, typename IPT_>
791 static void work(FID_& fid, const DT_ omega, FEV_& fev, const IPT_& ipt)
792 {
793 fid.add_value(omega, fev.value(ipt));
794 }
795 };
796
797 template<>
798 struct AnaFunIntJobHelper<1>
799 {
800 template<typename FID_, typename DT_, typename FEV_, typename IPT_>
801 static void work(FID_& fid, const DT_ omega, FEV_& fev, const IPT_& ipt)
802 {
803 fid.add_value(omega, fev.value(ipt));
804 fid.add_grad(omega, fev.gradient(ipt));
805 }
806 };
807
808 template<>
809 struct AnaFunIntJobHelper<2>
810 {
811 template<typename FID_, typename DT_, typename FEV_, typename IPT_>
812 static void work(FID_& fid, const DT_ omega, FEV_& fev, const IPT_& ipt)
813 {
814 fid.add_value(omega, fev.value(ipt));
815 fid.add_grad(omega, fev.gradient(ipt));
816 fid.add_hess(omega, fev.hessian(ipt));
817 }
818 };
819
820 template<int max_der_>
821 struct DiscFunIntJobHelper;
822
823 template<>
824 struct DiscFunIntJobHelper<0>
825 {
826 template<typename FID_, typename DT_, typename SED_, typename VT_, int n_, int sn_>
827 static void work(FID_& fid, const DT_ omega, const SED_& sed,
828 const Tiny::Vector<VT_, n_, sn_>& lvec, int n)
829 {
830 typename FID_::ValueType v(DT_(0));
831 for(int i(0); i < n; ++i)
832 {
833 v += lvec[i] * sed.phi[i].value;
834 }
835 fid.add_value(omega, v);
836 }
837 };
838
839 template<>
840 struct DiscFunIntJobHelper<1>
841 {
842 // version for scalar functions
843 template<typename FID_, typename DT_, typename SED_, int n_, int sn_>
844 static void work(FID_& fid, const DT_ omega, const SED_& sed,
845 const Tiny::Vector<DT_, n_, sn_>& lvec, int n)
846 {
847 typename FID_::ValueType v(DT_(0));
848 typename FID_::GradientType g(DT_(0));
849 for(int i(0); i < n; ++i)
850 {
851 v += lvec[i] * sed.phi[i].value;
852 g += lvec[i] * sed.phi[i].grad;
853 }
854 fid.add_value(omega, v);
855 fid.add_grad(omega, g);
856 }
857 // version for vector fields
858 template<typename FID_, typename DT_, typename SED_, int d_, int sd_, int n_, int sn_>
859 static void work(FID_& fid, const DT_ omega, const SED_& sed,
860 const Tiny::Vector<Tiny::Vector<DT_, d_, sd_>, n_, sn_>& lvec, int n)
861 {
862 typename FID_::ValueType v(DT_(0));
863 typename FID_::GradientType g(DT_(0));
864 for(int i(0); i < n; ++i)
865 {
866 v.axpy(sed.phi[i].value, lvec[i]);
867 g.add_outer_product(lvec[i], sed.phi[i].grad);
868 }
869 fid.add_value(omega, v);
870 fid.add_grad(omega, g);
871 }
872 };
873
874 template<>
875 struct DiscFunIntJobHelper<2>
876 {
877 // version for scalar functions
878 template<typename FID_, typename DT_, typename SED_, int n_, int sn_>
879 static void work(FID_& fid, const DT_ omega, const SED_& sed,
880 const Tiny::Vector<DT_, n_, sn_>& lvec, int n)
881 {
882 typename FID_::ValueType v(DT_(0));
883 typename FID_::GradientType g(DT_(0));
884 typename FID_::HessianType h(DT_(0));
885 for(int i(0); i < n; ++i)
886 {
887 v += lvec[i] * sed.phi[i].value;
888 g += lvec[i] * sed.phi[i].grad;
889 h += lvec[i] * sed.phi[i].hess;
890 }
891
892 fid.add_value(omega, v);
893 fid.add_grad(omega, g);
894 fid.add_hess(omega, h);
895 }
896 // version for vector fields
897 template<typename FID_, typename DT_, typename SED_, int d_, int sd_, int n_, int sn_>
898 static void work(FID_& fid, const DT_ omega, const SED_& sed,
899 const Tiny::Vector<Tiny::Vector<DT_, d_, sd_>, n_, sn_>& lvec, int n)
900 {
901 typename FID_::ValueType v(DT_(0));
902 typename FID_::GradientType g(DT_(0));
903 typename FID_::HessianType h(DT_(0));
904 for(int i(0); i < n; ++i)
905 {
906 v.axpy(sed.phi[i].value, lvec[i]);
907 g.add_outer_product(lvec[i], sed.phi[i].grad);
908 h.add_vec_mat_outer_product(lvec[i], sed.phi[i].hess);
909 }
910
911 fid.add_value(omega, v);
912 fid.add_grad(omega, g);
913 fid.add_hess(omega, h);
914 }
915 };
916
917 template<int max_der_>
918 struct ErrFunIntJobHelper;
919
920 template<>
921 struct ErrFunIntJobHelper<0>
922 {
923 // version for scalar functions
924 template<typename FID_, typename DT_, typename FEV_, typename IPT_, typename SED_, int n_, int sn_>
925 static void work(FID_& fid, const DT_ omega, FEV_& fev, const IPT_& ipt, const SED_& sed,
926 const Tiny::Vector<DT_, n_, sn_>& lvec, int n)
927 {
928 typename FID_::ValueType v = fev.value(ipt);
929 for(int i(0); i < n; ++i)
930 {
931 v -= lvec[i] * sed.phi[i].value;
932 }
933
934 fid.add_value(omega, v);
935 }
936
937 // version for vector fields
938 template<typename FID_, typename DT_, typename FEV_, typename IPT_, typename SED_, int d_, int sd_, int n_, int sn_>
939 static void work(FID_& fid, const DT_ omega, FEV_& fev, const IPT_& ipt, const SED_& sed,
940 const Tiny::Vector<Tiny::Vector<DT_, d_, sd_>, n_, sn_>& lvec, int n)
941 {
942 typename FID_::ValueType v = fev.value(ipt);
943 for(int i(0); i < n; ++i)
944 {
945 v.axpy(-sed.phi[i].value, lvec[i]);
946 }
947
948 fid.add_value(omega, v);
949 }
950 };
951
952 template<>
953 struct ErrFunIntJobHelper<1>
954 {
955 // version for scalar functions
956 template<typename FID_, typename DT_, typename FEV_, typename IPT_, typename SED_, int n_, int sn_>
957 static void work(FID_& fid, const DT_ omega, FEV_& fev, const IPT_& ipt, const SED_& sed,
958 const Tiny::Vector<DT_, n_, sn_>& lvec, int n)
959 {
960 typename FID_::ValueType v = fev.value(ipt);
961 typename FID_::GradientType g = fev.gradient(ipt);
962 for(int i(0); i < n; ++i)
963 {
964 v -= lvec[i] * sed.phi[i].value;
965 g -= lvec[i] * sed.phi[i].grad;
966 }
967
968 fid.add_value(omega, v);
969 fid.add_grad(omega, g);
970 }
971
972 // version for vector fields
973 template<typename FID_, typename DT_, typename FEV_, typename IPT_, typename SED_, int d_, int sd_, int n_, int sn_>
974 static void work(FID_& fid, const DT_ omega, FEV_& fev, const IPT_& ipt, const SED_& sed,
975 const Tiny::Vector<Tiny::Vector<DT_, d_, sd_>, n_, sn_>& lvec, int n)
976 {
977 typename FID_::ValueType v = fev.value(ipt);
978 typename FID_::GradientType g = fev.gradient(ipt);
979 for(int i(0); i < n; ++i)
980 {
981 v.axpy(-sed.phi[i].value, lvec[i]);
982 g.add_outer_product(lvec[i], sed.phi[i].grad, -DT_(1));
983 }
984
985 fid.add_value(omega, v);
986 fid.add_grad(omega, g);
987 }
988 };
989
990 template<>
991 struct ErrFunIntJobHelper<2>
992 {
993 // version for scalar functions
994 template<typename FID_, typename DT_, typename FEV_, typename IPT_, typename SED_, int n_, int sn_>
995 static void work(FID_& fid, const DT_ omega, FEV_& fev, const IPT_& ipt, const SED_& sed,
996 const Tiny::Vector<DT_, n_, sn_>& lvec, int n)
997 {
998 typename FID_::ValueType v = fev.value(ipt);
999 typename FID_::GradientType g = fev.gradient(ipt);
1000 typename FID_::HessianType h = fev.hessian(ipt);
1001 for(int i(0); i < n; ++i)
1002 {
1003 v -= lvec[i] * sed.phi[i].value;
1004 g -= lvec[i] * sed.phi[i].grad;
1005 h -= lvec[i] * sed.phi[i].hess;
1006 }
1007
1008 fid.add_value(omega, v);
1009 fid.add_grad(omega, g);
1010 fid.add_hess(omega, h);
1011 }
1012
1013 // version for vector fields
1014 template<typename FID_, typename DT_, typename FEV_, typename IPT_, typename SED_, int d_, int sd_, int n_, int sn_>
1015 static void work(FID_& fid, const DT_ omega, FEV_& fev, const IPT_& ipt, const SED_& sed,
1016 const Tiny::Vector<Tiny::Vector<DT_, d_, sd_>, n_, sn_>& lvec, int n)
1017 {
1018 typename FID_::ValueType v = fev.value(ipt);
1019 typename FID_::GradientType g = fev.gradient(ipt);
1020 typename FID_::HessianType h = fev.hessian(ipt);
1021 for(int i(0); i < n; ++i)
1022 {
1023 v.axpy(-sed.phi[i].value, lvec[i]);
1024 g.add_outer_product(lvec[i], sed.phi[i].grad, -DT_(1));
1025 h.add_vec_mat_outer_product(lvec[i], sed.phi[i].hess, -DT_(1));
1026 }
1027
1028 fid.add_value(omega, v);
1029 fid.add_grad(omega, g);
1030 fid.add_hess(omega, h);
1031 }
1032 };
1033
1035 template<typename Fun_, typename Vec_>
1036 struct ErrCompatHelper
1037 {
1038 // invalid combination of function and vector
1039 static constexpr bool valid = false;
1040 };
1041
1042 template<typename Fun_, typename DT_, typename IT_>
1043 struct ErrCompatHelper<Fun_, LAFEM::DenseVector<DT_, IT_>>
1044 {
1045 // scalar vector, so function must also be scalar
1046 static constexpr bool valid = Fun_::ImageType::is_scalar;
1047 };
1048
1049 template<typename Fun_, typename DT_, typename IT_, int dim_>
1050 struct ErrCompatHelper<Fun_, LAFEM::DenseVectorBlocked<DT_, IT_, dim_>>
1051 {
1052 typedef typename Fun_::ImageType ImageType;
1053 // blocked vector, so function must be a vector field of same dimension
1054 static constexpr bool valid = ImageType::is_vector && (ImageType::image_dim == dim_);
1055 };
1056 } // namespace Intern
1058 } // namespace Assembly
1059} // namespace FEAT
#define XASSERT(expr)
Assertion macro definition.
Definition: assertion.hpp:262
void push(const FunctionIntegralInfo &other)
Assembly helper function: adds another info object.
void add_grad(DataType omega, const Tiny::Matrix< DataType, m_, n_, sm_, sn_ > &g)
Assembly helper function: adds another function gradient.
ValueType_ value
Integral of the function value.
DataType vorticity_l2_sqr
squared L2-norm of the vector field vorticity
ValueType_ ValueType
the function value type
DataType_ norm_lmax
Lmax-norm of the function.
DataType_ norm_h1_sqr
squared H1-semi-norm of the function
DataType_ norm_l1
L1-norm of the function.
void add_hess(DataType omega, const Tiny::Matrix< DataType, m_, n_, sm_, sn_ > &h)
Assembly helper function: adds another function hessian.
ValueType_ norm_lmax_comp
the component-wise Lmax-norm (only for vector fields)
void add_grad(DataType omega, const Tiny::Vector< DataType, n_, sn_ > &g)
Assembly helper function: adds another function gradient.
DataType divergence_l2_sqr
squared L2-norm of the vector field divergence
void synchronize(const Dist::Comm &comm)
Synchronizes the function integral information over a communicator.
int max_der
the maximum derivative for which the integrals have been computed
HessianType_ hess
Integral of the function hessian.
ValueType_ norm_l1_comp
the component-wise L1-norm (only for vector fields)
void add_value(DataType omega, const Tiny::Vector< DataType, n_, sn_ > &v)
Assembly helper function: adds another function value.
ValueType_ norm_h1_sqr_comp
the component-wise squared H1-semi-norm (only for vector fields)
ValueType_ norm_h2_sqr_comp
the component-wise squared H2-semi-norm (only for vector fields)
String print_norms(int precision=0, std::size_t pad_size=15u, char pad_char='.') const
Prints all (computed) norms to a formatted string and returns it.
HessianType_ HessianType
the function hessian type
DataType_ DataType
the underlying scalar data type
String print_field_info(int precision=0, std::size_t pad_size=15u, char pad_char='.') const
Prints the additional field information to a formatted string and returns it.
DataType_ norm_h0_sqr
squared H0-norm (aka L2-norm) of the function
ValueType_ norm_h0_sqr_comp
the component-wise squared H0-norm (only for vector fields)
void format()
Formats the local values.
GradientType_ GradientType
the function gradient type
DataType_ norm_h2_sqr
squared H2-semi-norm of the function
void add_value(DataType omega, const DataType &v)
Assembly helper function: adds another function value.
GradientType_ grad
Integral of the function gradient.
void add_hess(DataType omega, const Tiny::Tensor3< DataType, l_, m_, n_, sl_, sm_, sn_ > &h)
Assembly helper function: adds another function hessian.
Communicator class.
Definition: dist.hpp:1349
void allreduce(const void *sendbuf, void *recvbuf, std::size_t count, const Datatype &datatype, const Operation &op) const
Blocking All-Reduce.
Definition: dist.cpp:655
int size() const
Returns the size of this communicator.
Definition: dist.hpp:1506
String class implementation.
Definition: string.hpp:46
String pad_back(size_type len, char c=' ') const
Pads the back of the string up to a desired length.
Definition: string.hpp:415
Tiny Matrix class template.
CUDA_HOST_DEVICE DataType trace() const
Returns the trace of the matrix.
CUDA_HOST_DEVICE DataType norm_hessian_sqr() const
Returns the Hessian norm square.
Tiny Tensor3 class template.
Tiny Vector class template.
CUDA_HOST_DEVICE DataType norm_euclid_sqr() const
Computes the squared euclid norm of this vector.
const Operation op_max(MPI_MAX)
Operation wrapper for MPI_MAX.
Definition: dist.hpp:273
const Operation op_sum(MPI_SUM)
Operation wrapper for MPI_SUM.
Definition: dist.hpp:271
T_ sqrt(T_ x)
Returns the square-root of a value.
Definition: math.hpp:300
T_ abs(T_ x)
Returns the absolute value.
Definition: math.hpp:275
T_ sqr(T_ x)
Returns the square of a value.
Definition: math.hpp:95
T_ max(T_ a, T_ b)
Returns the maximum of two values.
Definition: math.hpp:137
FEAT namespace.
Definition: adjactor.hpp:12
String stringify_fp_sci(DataType_ value, int precision=0, int width=0, bool sign=false)
Prints a floating point value to a string in scientific notation.
Definition: string.hpp:1088
Helper class to determine the FunctionIntegralInfo type for analytic functions.
FunctionIntegralInfo< DataType_, typename Analytic::EvalTraits< DataType_, Function_ >::ValueType, typename Analytic::EvalTraits< DataType_, Function_ >::GradientType, typename Analytic::EvalTraits< DataType_, Function_ >::HessianType > Type
the FunctionIntegralInfo type for this analytic function
FunctionIntegralInfo< DT_, DT_, Tiny::Vector< DT_, Space_::shape_dim >, Tiny::Matrix< DT_, Space_::shape_dim, Space_::shape_dim > > Type
the FunctionIntegralInfo type for this scalar discrete function
FunctionIntegralInfo< DT_, Tiny::Vector< DT_, bs_ >, Tiny::Matrix< DT_, bs_, Space_::shape_dim >, Tiny::Tensor3< DT_, bs_, Space_::shape_dim, Space_::shape_dim > > Type
the FunctionIntegralInfo type for this blocked discrete function
Helper class to determine the FunctionIntegralInfo type for discrete functions.