FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
pointstar_factory.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/util/math.hpp>
9#include <kernel/lafem/dense_vector.hpp>
10#include <kernel/lafem/sparse_matrix_csr.hpp>
11#include <kernel/lafem/sparse_matrix_banded.hpp>
12#include <kernel/lafem/pointstar_structure.hpp>
13
14#include <stack>
15
16namespace FEAT
17{
18 namespace LAFEM
19 {
25 template<typename DataType_, typename IndexType_>
27 {
28 protected:
33
35 _m(m), _d(d)
36 {
37 XASSERTM(m >= Index(3), "You need at least 3 inner nodes per dimension");
38 XASSERTM(d >= Index(1), "You need at least 1 dimension");
39 }
40
41 virtual ~PointstarFactoryBase() {}
42
43 public:
51
58 virtual DataType_ lambda_min() const = 0;
59
66 virtual DataType_ lambda_max() const = 0;
67
74 virtual DataType_ spectral_cond() const
75 {
76 return lambda_max() / lambda_min();
77 }
78
89 {
90 // compute vector length
91 Index neq(1);
92 for(Index i(0); i < _d; ++i)
93 neq *= _m;
94
95 // create vector
96 DenseVector<DataType_, IndexType_> vector(neq, DataType_(1));
97 DataType_* v = vector.elements();
98
99 // compute x scaling factor
100 const DataType_ xsf = DataType_(Math::pi<DataType_>()) / DataType_(_m+1);
101
102 for(Index i(0); i < neq; ++i)
103 {
104 for(Index quo(1); quo < neq; quo *= _m)
105 {
106 v[i] *= Math::sin(xsf * DataType_(((i / quo) % _m) + Index(1)));
107 }
108 }
109
110 // return vector
111 return vector;
112 }
113
124 {
125 // compute vector length
126 Index neq(1);
127 for(Index i(0); i < _d; ++i)
128 neq *= _m;
129
130 // create vector
131 DenseVector<DataType_, IndexType_> vector(neq, DataType_(1));
132 DataType_* v = vector.elements();
133
134 // compute x scaling factor
135 const DataType_ xsf = DataType_(1) / DataType_(_m+1);
136
137 for(Index i(0); i < neq; ++i)
138 {
139 for(Index quo(1); quo < neq; quo *= _m)
140 {
141 // compute coordinate x in (0,1)
142 DataType_ x(xsf * DataType_(((i / quo) % _m) + Index(1)));
143 v[i] *= DataType_(4) * x * (DataType_(1) - x);
144 }
145 }
146
147 // return vector
148 return vector;
149 }
150 }; // PointstarFactoryBase
151
165 template<typename DataType_, typename IndexType_>
167 public PointstarFactoryBase<DataType_, IndexType_>
168 {
169 public:
180 PointstarFactoryBase<DataType_, IndexType_>(m, d)
181 {
182 }
183
184 virtual ~PointstarFactoryFD() {}
185
193 {
194 // declare some variables
195 Index i,j,k,l,n,neq,nnze,bpl,rpb,rps,b;
196 IndexType_ *epr,*dor,*ior,*col_idx;
197 DataType_ *data;
198 const Index m(this->_m), d(this->_d);
199
200 // calculate number of equations and non-zero entries
201 neq = m;
202 nnze = 3*m - 2;
203 for(i = 1; i < d; ++i)
204 {
205 nnze *= m;
206 nnze += 2*(m-1) * neq;
207 neq *= m;
208 }
209
210 // create five vectors
211 DenseVector<IndexType_, IndexType_> vec_row_ptr(neq+IndexType_(1));
212 DenseVector<IndexType_, IndexType_> vec_col_idx(nnze);
213 DenseVector<IndexType_, IndexType_> vec_dor(neq, IndexType_(0));
214 DenseVector<IndexType_, IndexType_> vec_epr(neq, IndexType_(1));
216
217 // get data
218 data = vec_data.elements();
219
220 // get epr
221 epr = vec_epr.elements();
222
223 // get dor
224 dor = vec_dor.elements();
225
226 // get ior
227 ior = vec_row_ptr.elements();
228
229 // get column indices
230 col_idx = vec_col_idx.elements();
231
232 /* In this step we will recursively calculate the number of non-zero
233 * elements in a row (= epr), and the number of non-zero elements left of
234 * the main diagonal element in a row (= dor).
235 * The indices of the first element of a row (= ior) and the indices of
236 * the main diagonal elements (= dor) will later be recalculated from
237 * epr and dor.
238 */
239
240 /* blocks per level */
241 bpl = 1;
242
243 /* rows per block */
244 rpb = neq;
245
246 /* go through all levels */
247 for(l = 0; l < d; ++l)
248 {
249 /* rows per sub-block */
250 rps = rpb / m;
251
252 /* go through all blocks */
253 for(b = 0; b < bpl; ++b)
254 {
255 /* index of b-th block */
256 k = rpb * b;
257
258 /* add the right diagonal to sub-block 1 */
259 for(j = 0; j < rps; ++j)
260 ++epr[k+j];
261
262 /* add left and right diagonals to sub-blocks 2..m-1 */
263 for(i = 1; i < m - 1; ++i)
264 {
265 /* index of i-th sub-block */
266 n = k + rps*i;
267 for(j = 0; j < rps; ++j)
268 {
269 epr[n+j] += 2;
270 ++dor[n+j];
271 }
272 }
273
274 /* add left diagonal to sub-block m */
275 n = k + rps*(m - 1);
276 for(j = 0; j < rps; ++j)
277 {
278 ++epr[n+j];
279 ++dor[n+j];
280 }
281 }
282
283 /* increase blocks per level */
284 bpl *= m;
285
286 /* decrease rows per block */
287 rpb = rps;
288 }
289
290 /* initialize row and diagonal pointer arrays */
291 ior[0] = 0;
292 for(i = 0; i < neq; ++i)
293 {
294 ior[i+1] = ior[i] + epr[i];
295 dor[i] += ior[i];
296 }
297
298 /* initialize data array */
299 const DataType_ v1 = DataType_(2*d);
300 const DataType_ v2 = DataType_(-1);
301 for(i = 0; i < neq; ++i)
302 {
303 /* left of main diagonal */
304 for(j = ior[i]; j < dor[i]; ++j)
305 data[j] = v2;
306
307 /* main diagonal */
308 data[dor[i]] = v1;
309
310 /* right of main diagonal */
311 for(j = dor[i]+1; j < ior[i+1]; ++j)
312 data[j] = v2;
313 }
314
315 /* We will now overwrite epr with the number of non-zero elements
316 * right of the main diagonal element of a row.
317 * At the same time, we can already set the indices of the main
318 * diagonal elements.
319 */
320 for(i = 0; i < neq; ++i)
321 {
322 epr[i] = ior[i+1] - dor[i] - 1;
323 col_idx[dor[i]] = IndexType_(i);
324 }
325
326 /* Now we need to calculate the indices for the off-main-diagonal
327 * non-zero elements.
328 * Once again, we will do this recursively ^_^
329 *
330 * We will go through every level of the matrix, and in each level,
331 * we will set the indices of the diagonal-matrix blocks which to
332 * not belong to the main diagonal.
333 */
334
335 /* blocks per level */
336 bpl = 1;
337
338 /* rows per block */
339 rpb = neq;
340
341 /* go through all levels */
342 for(l = 0; l < d; ++l)
343 {
344 /* rows per sub-block */
345 rps = rpb / m;
346
347 /* go through all blocks */
348 for(b = 0; b < bpl; ++b)
349 {
350 /* index of b-th block */
351 k = rpb * b;
352
353 /* go through the first m-1 sub-blocks */
354 for(i = 0; i < rpb - rps; ++i)
355 {
356 /* and this is where the magic happens */
357 col_idx[dor[k+i]+epr[k+i]] = IndexType_(k + i + rps);
358 col_idx[dor[neq-k-i-1]-epr[k+i]] = IndexType_(neq - k - i - rps - 1);
359 }
360
361 for(i = 0; i < rpb - rps; ++i)
362 --epr[k+i];
363 }
364
365 /* increase blocks per level */
366 bpl *= m;
367
368 /* decrease rows per block */
369 rpb = rps;
370 }
371
372 // return the matrix
373 return SparseMatrixCSR<DataType_, IndexType_>(neq, neq, vec_col_idx, vec_data, vec_row_ptr);
374 }
375
386 virtual DataType_ lambda_min() const override
387 {
388 // 4 * d * sin(pi/(2*m+2))^2 = 2 * d * (1 - cos(pi/(m+1)))
389 return DataType_(2) * DataType_(this->_d) *
390 (DataType_(1) - Math::cos(Math::pi<DataType_>() / DataType_(this->_m+1)));
391 }
392
403 virtual DataType_ lambda_max() const override
404 {
405 // 2 * d * (1 + cos(pi/(m+1)))
406 return DataType_(2) * DataType_(this->_d) *
407 (DataType_(1) + Math::cos(Math::pi<DataType_>() / DataType_(this->_m+1)));
408 }
409 }; // class PointstarFactoryFD
410
423 template<typename DataType_, typename IndexType_>
425 public PointstarFactoryBase<DataType_, IndexType_>
426 {
427 public:
435 PointstarFactoryBase<DataType_, IndexType_>(m, Index(2))
436 {
437 }
438
439 virtual ~PointstarFactoryFE() {}
440
450 {
451 // declare some variables
452 Index i,j,k,l,n,neq,nnze,bpl,rpb,rps,b;
453 IndexType_ *epr,*dor,*ior,*col_idx;
454 DataType_ *data;
455 const Index m(this->_m), d(this->_d);
456
457 /* calculate number of equations and non-zero entries */
458 neq = m;
459 nnze = j = 3*m - 2;
460 for(i = 1; i < d; i++)
461 {
462 nnze *= j;
463 neq *= m;
464 }
465
466 // create five vectors
467 DenseVector<IndexType_, IndexType_> vec_row_ptr(neq+IndexType_(1));
468 DenseVector<IndexType_, IndexType_> vec_col_idx(nnze, IndexType_(neq));
469 DenseVector<IndexType_, IndexType_> vec_dor(neq, IndexType_(0));
470 DenseVector<IndexType_, IndexType_> vec_epr(neq, IndexType_(1));
472
473 // get data
474 data = vec_data.elements();
475
476 // get epr
477 epr = vec_epr.elements();
478
479 // get dor
480 dor = vec_dor.elements();
481
482 // get ior
483 ior = vec_row_ptr.elements();
484
485 // get column indices
486 col_idx = vec_col_idx.elements();
487
488 /* In this step we will recursively calculate the number of non-zero
489 * elements in a row (= epr), and the number of non-zero elements left of
490 * the main diagonal element in a row (= dor).
491 * The indices of the first element of a row (= ior) and the indices of
492 * the main diagonal elements (= dor) will later be recalculated from
493 * epr and dor.
494 */
495
496 /* blocks per level */
497 bpl = neq / m;
498
499 /* rows per block */
500 rpb = m;
501
502 /* go through all levels */
503 for(l = 0; l < d; ++l)
504 {
505 /* rows per sub-block */
506 rps = rpb / m;
507
508 /* go through all blocks */
509 for(b = 0; b < bpl; ++b)
510 {
511 /* index of b-th block */
512 k = rpb * b;
513
514 /* add the right diagonal to sub-block 1 */
515 for(j = 0; j < rps; ++j)
516 epr[k+j] *= 2;
517
518 /* add left and right diagonals to sub-blocks 2..m-1 */
519 for(i = 1; i < m - 1; ++i)
520 {
521 /* index of i-th sub-block */
522 n = k + rps*i;
523 for(j = 0; j < rps; ++j)
524 {
525 dor[n+j] += epr[n+j];
526 epr[n+j] *= 3;
527 }
528 }
529
530 /* add left diagonal to sub-block m */
531 n = k + rps*(m - 1);
532 for(j = 0; j < rps; ++j)
533 {
534 dor[n+j] += epr[n+j];
535 epr[n+j] *= 2;
536 }
537 }
538
539 /* decrease blocks per level */
540 bpl /= m;
541
542 /* increase rows per block */
543 rpb *= m;
544 }
545
546 /* initialize row and diagonal pointer arrays */
547 /* calculate row and diagonal indices */
548 ior[0] = 0;
549 for(i = 0; i < neq; ++i)
550 {
551 ior[i+1] = ior[i] + epr[i];
552 dor[i] += ior[i];
553 }
554
555 /* initialize data array */
556 j = Index(3);
557 for(i = 1; i < d; ++i)
558 j *= Index (3);
559 const DataType_ v1 = DataType_(j - Index(1));
560 const DataType_ v2 = DataType_(-1);
561
562 for(i = 0; i < neq; ++i)
563 {
564 /* left of main diagonal */
565 for(j = ior[i]; j < dor[i]; ++j)
566 data[j] = v2;
567
568 /* main diagonal */
569 data[dor[i]] = v1;
570
571 /* right of main diagonal */
572 for(j = dor[i]+1; j < ior[i+1]; ++j)
573 data[j] = v2;
574 }
575
576 /* First, we initialize all indices to lie on the main diagonal.
577 * At the same time, we will reset epr to 1.
578 */
579 for(i = 0; i < neq; ++i)
580 {
581 epr[i] = 1;
582 for(j = ior[i]; j < ior[i+1]; ++j)
583 col_idx[j] = IndexType_(neq+i);
584 }
585
586 /* blocks per level */
587 bpl = neq / m;
588
589 /* rows per block */
590 rpb = m;
591
592 /* go through all levels */
593 for(l = d; l > 0; --l)
594 {
595 /* rows per sub-block */
596 rps = rpb / m;
597
598 /* go through all blocks */
599 for(b = 0; b < bpl; ++b)
600 {
601 /* index of b-th block */
602 k = rpb * b;
603
604 /* go through the first sub-block */
605 for(i = 0; i < rps; ++i)
606 {
607 for(n = 0; 2*n*epr[k+i] < ior[k+i+1]-ior[k+i]; ++n)
608 {
609 for(j = 0; j < epr[k+i]; ++j)
610 {
611 col_idx[ior[k+i]+2*n*epr[k+i]+j+epr[k+i]] += IndexType_(rps);
612 col_idx[ior[neq-k-i]-2*n*epr[k+i]-j-epr[k+i]-1] -= IndexType_(rps);
613 }
614 }
615 epr[k+i] *= 2;
616 epr[k+rpb-i-1] *= 2;
617 }
618
619 /* go through the next m-2 sub-blocks */
620 for(i = rps; i < rpb - rps; ++i)
621 {
622 for(n = 0; 3*n*epr[k+i] < ior[k+i+1]-ior[k+i]; ++n)
623 {
624 for(j = 0; j < epr[k+i]; ++j)
625 {
626 col_idx[ior[k+i]+3*n*epr[k+i]+j+2*epr[k+i]] += IndexType_(rps);
627 col_idx[ior[neq-k-i]-3*n*epr[k+i]-j-2*epr[k+i]-1] -= IndexType_(rps);
628 }
629 }
630 epr[k+i] *= 3;
631 }
632 }
633
634 /* decrease blocks per level */
635 bpl /= m;
636
637 /* increase rows per block */
638 rpb *= m;
639 }
640
641 // finally, update col_idx
642 for(i = 0; i < nnze; ++i)
643 col_idx[i] -= IndexType_(neq);
644
645 // return the matrix
646 return SparseMatrixCSR<DataType_, IndexType_>(neq, neq, vec_col_idx, vec_data, vec_row_ptr);
647 }
648
659 {
660 // create matrix with default values
662
663 // get matrix arrays
664 const IndexType_ m = IndexType_(this->_m);
665 const IndexType_* row_ptr = matrix.row_ptr();
666 const IndexType_* col_idx = matrix.col_ind();
667 DataType_* val = matrix.val();
668
669 // process first vertex line
670 {
671 // process first vertex in first line
672 {
673 const IndexType_ row = 0;
674 for(IndexType_ k(row_ptr[row]); k < row_ptr[row + 1]; ++k)
675 {
676 const IndexType_ col = col_idx[k];
677 if(col == row)
678 val[k] = DataType_(4);
679 else if(col == row+1)
680 val[k] = DataType_(-1);
681 else if(col == row+m)
682 val[k] = DataType_(-1);
683 else if(col == row+m+1)
684 val[k] = DataType_(-2);
685 else
686 throw 0;
687 }
688 }
689
690 // loop over all inner vertices in first line
691 for(IndexType_ jj(1); jj + 1 < m; ++jj)
692 {
693 // loop over all non-zeros
694 const IndexType_ row = jj;
695 for(IndexType_ k(row_ptr[row]); k < row_ptr[row + 1]; ++k)
696 {
697 const IndexType_ col = col_idx[k];
698 if(col == row)
699 val[k] = DataType_(8);
700 else if(col+1 == row)
701 val[k] = DataType_(-1);
702 else if(col == row+1)
703 val[k] = DataType_(-1);
704 else
705 val[k] = DataType_(-2);
706 }
707 }
708
709 // process last vertex in first line
710 {
711 const IndexType_ row = m - 1;
712 for(IndexType_ k(row_ptr[row]); k < row_ptr[row + 1]; ++k)
713 {
714 const IndexType_ col = col_idx[k];
715 if(col == row)
716 val[k] = DataType_(4);
717 else if(col+1 == row)
718 val[k] = DataType_(-1);
719 else if(col == row+m)
720 val[k] = DataType_(-1);
721 else if(col+1 == row+m)
722 val[k] = DataType_(-2);
723 else
724 throw 0;
725 }
726 }
727 }
728
729 // loop over all inner vertex lines
730 for(IndexType_ ii(1); ii + 1 < m; ++ii)
731 {
732 // process first vertex in line ii
733 {
734 const IndexType_ row = ii*m;
735 for(IndexType_ k(row_ptr[row]); k < row_ptr[row + 1]; ++k)
736 {
737 const IndexType_ col = col_idx[k];
738 if(col == row)
739 val[k] = DataType_(8);
740 else if(col+m == row)
741 val[k] = DataType_(-1);
742 else if(col == row+m)
743 val[k] = DataType_(-1);
744 else
745 val[k] = DataType_(-2);
746 }
747 }
748
749 // loop over all inner vertices in line ii
750 for(IndexType_ jj(1); jj + 1 < m; ++jj)
751 {
752 // loop over all non-zeros
753 const IndexType_ row = ii*m + jj;
754 for(IndexType_ k(row_ptr[row]); k < row_ptr[row+1]; ++k)
755 val[k] = DataType_(col_idx[k] == row ? 16 : -2);
756 }
757
758 // process last vertex in line ii
759 {
760 const IndexType_ row = ii*m + m - 1;
761 for(IndexType_ k(row_ptr[row]); k < row_ptr[row + 1]; ++k)
762 {
763 const IndexType_ col = col_idx[k];
764 if(col == row)
765 val[k] = DataType_(8);
766 else if(col+m == row)
767 val[k] = DataType_(-1);
768 else if(col == row+m)
769 val[k] = DataType_(-1);
770 else
771 val[k] = DataType_(-2);
772 }
773 }
774 }
775
776
777 // process last vertex line
778 {
779 // process first vertex in last line
780 {
781 const IndexType_ row = (m-1)*m;
782 for(IndexType_ k(row_ptr[row]); k < row_ptr[row + 1]; ++k)
783 {
784 const IndexType_ col = col_idx[k];
785 if(col == row)
786 val[k] = DataType_(4);
787 else if(col == row+1)
788 val[k] = DataType_(-1);
789 else if(col+m == row)
790 val[k] = DataType_(-1);
791 else if(col+m == row+1)
792 val[k] = DataType_(-2);
793 else
794 throw 0;
795 }
796 }
797
798 // loop over all inner vertices in last line
799 for(IndexType_ jj(1); jj + 1 < m; ++jj)
800 {
801 // loop over all non-zeros
802 const IndexType_ row = (m-1)*m + jj;
803 for(IndexType_ k(row_ptr[row]); k < row_ptr[row + 1]; ++k)
804 {
805 const IndexType_ col = col_idx[k];
806 if(col == row)
807 val[k] = DataType_(8);
808 else if(col+1 == row)
809 val[k] = DataType_(-1);
810 else if(col == row+1)
811 val[k] = DataType_(-1);
812 else
813 val[k] = DataType_(-2);
814 }
815 }
816
817 // process last vertex in last line
818 {
819 const IndexType_ row = (m-1)*m + m - 1;
820 for(IndexType_ k(row_ptr[row]); k < row_ptr[row + 1]; ++k)
821 {
822 const IndexType_ col = col_idx[k];
823 if(col == row)
824 val[k] = DataType_(4);
825 else if(col+1 == row)
826 val[k] = DataType_(-1);
827 else if(col+m == row)
828 val[k] = DataType_(-1);
829 else if(col+m+1 == row)
830 val[k] = DataType_(-2);
831 else
832 throw 0;
833 }
834 }
835 }
836
837 // return modified matrix
838 return matrix;
839 }
840
841
845 virtual DataType_ lambda_min() const override
846 {
847 const DataType_ c(Math::cos(Math::pi<DataType_>() / DataType_(this->_m+1)));
848
849 // lambda_min = 3^d - 1 - \sum_{k=1}^{d-1} 2^{d-k} {d \choose k} \cos\Big(\frac{\pi}{m+1}\Big)^k
850
851 Index v(Index(1)); // v := 2^d
852 Index a(Index(1)); // a := 3^d-1
853 for(Index i(0); i < this->_d; ++i)
854 {
855 v *= Index(2);
856 a *= Index(3);
857 }
858
859 DataType_ y = DataType_(v);
860 for(Index k(1); k < this->_d; ++k)
861 {
862 (y *= c) += DataType_((v *= this->_d - k + Index(1)) /= (Index(2) * k));
863 }
864
865 return DataType_(a - Index(1)) - c*y;
866 }
867
871 virtual DataType_ lambda_max() const override
872 {
873 return DataType_(8) + DataType_(4)*Math::sqr(Math::cos(Math::pi<DataType_>() / DataType_(this->_m+1)));
874 }
875 }; // class PointstarFactory
876
877
883 template<typename DataType_, typename IndexType_>
885 {
886 protected:
888 const std::vector<IndexType_> & _num_of_subintervalls;
890 const std::vector<DataType_> & _dimensions;
892 const Index _d;
893
894 PointstarFactoryBase2(const std::vector<IndexType_> & num_of_subintervalls,
895 const std::vector<DataType_> & dimensions) :
896 _num_of_subintervalls(num_of_subintervalls),
897 _dimensions(dimensions),
898 _d(Index(_dimensions.size()))
899 {
900 XASSERTM(_d >= Index(1), "You need at least 1 dimension");
901 XASSERTM(_d + 1 == _num_of_subintervalls.size(), "Vector-sizes do not match (n_1 = n_2 + 1)!");
902
903 for (Index i(1); i <= _d; ++i)
904 {
905 XASSERTM(_num_of_subintervalls[i] >= Index(4), "You need at least 4 subintervalls per dimension");
906 }
907 }
908
909 virtual ~PointstarFactoryBase2() {}
910
911 public:
919
926 virtual DataType_ lambda_min() const = 0;
927
934 virtual DataType_ lambda_max() const = 0;
935
942 virtual DataType_ spectral_cond() const
943 {
944 return lambda_max() / lambda_min();
945 }
946
957
968 }; // PointstarFactoryBase2
969
980 template<typename DataType_, typename IndexType_>
982 public PointstarFactoryBase2<DataType_, IndexType_>
983 {
984 public:
993 PointstarFactoryFD2(const std::vector<IndexType_> & num_of_subintervalls,
994 const std::vector<DataType_> & dimensions) :
995 PointstarFactoryBase2<DataType_, IndexType_>(num_of_subintervalls, dimensions)
996 {
997 }
998
999 virtual ~PointstarFactoryFD2() {}
1000
1008 {
1009 const IndexType_ d(IndexType_(this->_d));
1010 const IndexType_ * const pnos(this->_num_of_subintervalls.data());
1011 const DataType_ * const pdim(this->_dimensions.data());
1012
1016 SparseMatrixBanded<DataType_, IndexType_> matrix(PointstarStructureFD::value<DataType_, IndexType_>(this->_num_of_subintervalls));
1017 const IndexType_ neq(IndexType_(matrix.rows()));
1018 DataType_ * const pval(matrix.val());
1019
1023 // calculate diagonal entries
1024 DataType_ diagonal_entry(0);
1025 for (IndexType_ i(0); i < d; ++i)
1026 {
1027 diagonal_entry += DataType_(2.0) * Math::sqr(pdim[i] / DataType_(pnos[i + 1]));
1028 }
1029
1030 // Fill diagonal with entries
1031 for (IndexType_ i(0); i < neq; ++i)
1032 {
1033 pval[neq * d + i] = diagonal_entry;
1034 }
1035
1036 // Fill subdiagonals with entries
1037 for (IndexType_ i(0), k(pnos[0] - 1); i < d; ++i, k *= pnos[i] - 1)
1038 {
1039 const DataType_ subdiagonal_entry(-Math::sqr(pdim[i] / DataType_(pnos[i + 1])));
1040
1041 for (IndexType_ j(0); j < neq / k / (pnos[i + 1] - 1); ++j)
1042 {
1043 const IndexType_ k1(neq * d + k * (pnos[i + 1] - 1) * j);
1044 const IndexType_ k2(neq * (i + 1));
1045
1046 if (j != 0)
1047 {
1048 for (IndexType_ l(pnos[i] - 1); l > 0; --l)
1049 {
1050 pval[k1 + k2 - l] = DataType_(0);
1051 pval[k1 - k2 - l + k] = DataType_(0);
1052 }
1053 }
1054
1055 for (IndexType_ l(0); l < k * (pnos[i + 1] - 2); ++l)
1056 {
1057 pval[k1 + l + k2] = subdiagonal_entry;
1058 pval[k1 + l - k2 + k] = subdiagonal_entry;
1059 }
1060 }
1061 }
1062
1063 // return the matrix
1064 return matrix;
1065 }
1066
1077 virtual DataType_ lambda_min() const override
1078 {
1079 DataType_ x(DataType_(0.0));
1080 const IndexType_ * const pnos(this->_num_of_subintervalls.data());
1081 const DataType_ * const pdim(this->_dimensions.data());
1082
1083 for (Index i(0); i < this->_d; ++i)
1084 {
1085 const DataType_ h(pdim[i] / DataType_(pnos[i + 1]));
1086 x += Math::sqr(h) * (DataType_(1.0) - Math::cos(Math::pi<DataType_>() * h / pdim[i]));
1087 }
1088
1089 return DataType_(2) * x;
1090 }
1091
1102 virtual DataType_ lambda_max() const override
1103 {
1104 DataType_ x(DataType_(0.0));
1105 const IndexType_ * const pnos(this->_num_of_subintervalls.data());
1106 const DataType_ * const pdim(this->_dimensions.data());
1107
1108 for (Index i(0); i < this->_d; ++i)
1109 {
1110 const DataType_ h(pdim[i] / DataType_(pnos[i + 1]));
1111 x += Math::sqr(h) * (DataType_(1.0) + Math::cos(Math::pi<DataType_>() * h / pdim[i]));
1112 }
1113
1114 return DataType_(2) * x;
1115 }
1116
1118 {
1119 const IndexType_ * const pnos(this->_num_of_subintervalls.data());
1120 const Index d(this->_d);
1121
1122 // compute vector length
1123 Index size(1);
1124 for (Index i(1); i <= d; ++i)
1125 {
1126 size *= pnos[i] - 1;
1127 }
1128
1129 // create vector
1130 DenseVector<DataType_, IndexType_> vector(size, DataType_(1));
1131 DataType_* v = vector.elements();
1132
1133 for(Index i(0); i < size; ++i)
1134 {
1135 for(Index j(0), quo(1); j < d; ++j, quo *= pnos[j] - 1)
1136 {
1137 // compute x scaling factor
1138 const DataType_ xsf(Math::pi<DataType_>() / DataType_(pnos[j + 1]));
1139 v[i] *= Math::sin(xsf * DataType_(((i / quo) % (pnos[j + 1] - 1)) + Index(1)));
1140 }
1141 }
1142
1143 // return vector
1144 return vector;
1145 }
1146
1157 {
1158 const Index d(this->_d);
1159 const IndexType_ * const pnos(this->_num_of_subintervalls.data());
1160 const DataType_ * const pdim(this->_dimensions.data());
1161
1162 // compute vector length
1163 Index size(1);
1164 for (Index i(1); i <= d; ++i)
1165 {
1166 size *= pnos[i] - 1;
1167 }
1168
1169 // create vector
1170 DenseVector<DataType_, IndexType_> vector(size, DataType_(1));
1171 DataType_* v = vector.elements();
1172
1173 for(Index i(0); i < size; ++i)
1174 {
1175 for(Index j(0), quo(1); j < d; ++j, quo *= pnos[j] - 1)
1176 {
1177 // compute x scaling factor
1178 const DataType_ xsf(pdim[j] / DataType_(pnos[j + 1]));
1179
1180 // compute coordinate x in (0,pdim[j])
1181 DataType_ x(xsf * DataType_(((i / quo) % (pnos[j + 1] - 1)) + Index(1)));
1182
1183 v[i] *= DataType_(4) * x * (DataType_(1) - x);
1184 }
1185 }
1186
1187 // return vector
1188 return vector;
1189 }
1190 }; // class PointstarFactoryFD2
1191
1192 } // namespace LAFEM
1193} // namespace FEAT
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Definition: assertion.hpp:263
Dense data vector class template.
DT_ * elements()
Get a pointer to the data array.
Pointstar factory base class.
virtual DenseVector< DataType_, IndexType_ > eigenvector_min() const =0
Computes the eigenvector of the smallest eigenvalue.
virtual DataType_ lambda_min() const =0
Computes the smallest eigenvalue of the pointstar matrix.
virtual DenseVector< DataType_, IndexType_ > vector_q2_bubble() const =0
Computes a Q2-bubble vector.
const std::vector< DataType_ > & _dimensions
vector with lengths of the n-dimensional hypercube
virtual DataType_ lambda_max() const =0
Computes the largest eigenvalue of the pointstar matrix.
virtual DataType_ spectral_cond() const
Computes the spectral condition number of the pointstar matrix.
const Index _d
number of dimensions
const std::vector< IndexType_ > & _num_of_subintervalls
vector with number of subintervalls per dimension (plus a leading 2).
virtual SparseMatrixBanded< DataType_, IndexType_ > matrix_banded() const =0
Computes the pointstar matrix in banded format.
Pointstar factory base class.
virtual DataType_ lambda_max() const =0
Computes the largest eigenvalue of the pointstar matrix.
Index _m
number of inner nodes per dimension
virtual SparseMatrixCSR< DataType_, IndexType_ > matrix_csr() const =0
Computes the pointstar matrix in CSR format.
DenseVector< DataType_, IndexType_ > vector_q2_bubble() const
Computes a Q2-bubble vector.
virtual DataType_ spectral_cond() const
Computes the spectral condition number of the pointstar matrix.
virtual DenseVector< DataType_, IndexType_ > eigenvector_min() const
Computes the eigenvector of the smallest eigenvalue.
virtual DataType_ lambda_min() const =0
Computes the smallest eigenvalue of the pointstar matrix.
Finite-Differences pointstar matrix factory.
DenseVector< DataType_, IndexType_ > vector_q2_bubble() const override
Computes a Q2-bubble vector.
virtual DataType_ lambda_min() const override
Computes the smallest eigenvalue of the FD-style matrix.
virtual SparseMatrixBanded< DataType_, IndexType_ > matrix_banded() const override
Generates a FD-style pointstar banded matrix.
virtual DataType_ lambda_max() const override
Computes the largest eigenvalue of the FD-style matrix.
virtual DenseVector< DataType_, IndexType_ > eigenvector_min() const override
Computes the eigenvector of the smallest eigenvalue.
PointstarFactoryFD2(const std::vector< IndexType_ > &num_of_subintervalls, const std::vector< DataType_ > &dimensions)
Creates the pointstar factory.
Finite-Differences pointstar matrix factory.
virtual DataType_ lambda_max() const override
Computes the largest eigenvalue of the FD-style matrix.
PointstarFactoryFD(Index m, Index d=Index(2))
Creates the pointstar factory.
virtual DataType_ lambda_min() const override
Computes the smallest eigenvalue of the FD-style matrix.
virtual SparseMatrixCSR< DataType_, IndexType_ > matrix_csr() const override
Generates a FD-style pointstar CSR matrix.
Finite-Element pointstar matrix factory.
virtual DataType_ lambda_min() const override
Computes the smallest eigenvalue of the FE-style matrix.
PointstarFactoryFE(Index m)
Creates the pointstar factory.
virtual SparseMatrixCSR< DataType_, IndexType_ > matrix_csr_neumann() const
Generates a FE-style pointstar CSR matrix with Neumann boundaries.
virtual SparseMatrixCSR< DataType_, IndexType_ > matrix_csr() const override
Generates a FE-style pointstar CSR matrix.
virtual DataType_ lambda_max() const override
Computes the largest eigenvalue of the FE-style matrix.
Index rows() const
Retrieve matrix row count.
DT_ * val()
Retrieve element array.
CSR based sparse matrix.
IT_ * col_ind()
Retrieve column indices array.
DT_ * val()
Retrieve non zero element array.
IT_ * row_ptr()
Retrieve row start index array.
T_ sin(T_ x)
Returns the sine of a value.
Definition: math.hpp:344
T_ sqr(T_ x)
Returns the square of a value.
Definition: math.hpp:95
T_ cos(T_ x)
Returns the cosine of a value.
Definition: math.hpp:386
FEAT namespace.
Definition: adjactor.hpp:12
std::uint64_t Index
Index data type.