MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
bilininteg.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2026, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12// Implementation of Bilinear Form Integrators
13
14#include "fem.hpp"
15#include <cmath>
16#include <algorithm>
17#include <memory>
18
19using namespace std;
20
21namespace mfem
22{
23
25{
26 MFEM_ABORT("BilinearFormIntegrator::AssemblePA(fes)\n"
27 " is not implemented for this class.");
28}
29
31{
32 mfem_error ("BilinearFormIntegrator::AssembleNURBSPA(fes)\n"
33 " is not implemented for this class.");
34}
35
37 const FiniteElementSpace&)
38{
39 MFEM_ABORT("BilinearFormIntegrator::AssemblePA(fes, fes)\n"
40 " is not implemented for this class.");
41}
42
44{
45 MFEM_ABORT("BilinearFormIntegrator::AssemblePABoundary(fes)\n"
46 " is not implemented for this class.");
47}
48
50{
51 MFEM_ABORT("BilinearFormIntegrator::AssemblePAInteriorFaces(...)\n"
52 " is not implemented for this class.");
53}
56{
57 MFEM_ABORT("BilinearFormIntegrator::AssemblePABoundaryFaces(...)\n"
58 " is not implemented for this class.");
59}
60
62{
63 MFEM_ABORT("BilinearFormIntegrator::AssembleDiagonalPA(...)\n"
64 " is not implemented for this class.");
65}
66
68 Vector &emat,
69 const bool add)
70{
71 MFEM_ABORT("BilinearFormIntegrator::AssembleEA(...)\n"
72 " is not implemented for this class.");
73}
74
76 Vector &emat,
77 const bool add)
78{
79 MFEM_ABORT("BilinearFormIntegrator::AssembleEABoundary(...)\n"
80 " is not implemented for this class.");
81}
82
84 &fes,
85 Vector &ea_data_int,
86 Vector &ea_data_ext,
87 const bool add)
88{
89 MFEM_ABORT("BilinearFormIntegrator::AssembleEAInteriorFaces(...)\n"
90 " is not implemented for this class.");
91}
92
94 const FiniteElementSpace &trial_fes,
95 const FiniteElementSpace &test_fes,
96 Vector &emat,
97 const bool add)
98{
99 MFEM_ABORT("BilinearFormIntegrator::AssembleEAInteriorFaces(...)\n"
100 " is not implemented for this class.");
101}
102
104 &fes,
105 Vector &ea_data_bdr,
106 const bool add)
107{
108 MFEM_ABORT("BilinearFormIntegrator::AssembleEABoundaryFaces(...)\n"
109 " is not implemented for this class.");
110}
111
113{
114 MFEM_ABORT("BilinearFormIntegrator::AssembleDiagonalPA_ADAt(...)\n"
115 " is not implemented for this class.");
116}
117
119{
120 MFEM_ABORT("BilinearFormIntegrator:AddMultPA:(...)\n"
121 " is not implemented for this class.");
122}
123
125{
126 MFEM_ABORT("BilinearFormIntegrator:AddAbsMultPA:(...)\n"
127 " is not implemented for this class.");
128}
129
131{
132 MFEM_ABORT("BilinearFormIntegrator::AddMultNURBSPA(...)\n"
133 " is not implemented for this class.");
134}
135
138 MFEM_ABORT("BilinearFormIntegrator::AddMultTransposePA(...)\n"
139 " is not implemented for this class.");
140}
141
143 Vector &) const
144{
145 MFEM_ABORT("BilinearFormIntegrator::AddAbsMultTransposePA(...)\n"
146 " is not implemented for this class.");
148
150{
151 MFEM_ABORT("BilinearFormIntegrator::AssembleMF(...)\n"
152 " is not implemented for this class.");
153}
154
156{
157 MFEM_ABORT("BilinearFormIntegrator::AddMultMF(...)\n"
158 " is not implemented for this class.");
159}
160
162{
163 MFEM_ABORT("BilinearFormIntegrator::AddMultTransposeMF(...)\n"
164 " is not implemented for this class.");
165}
166
168{
169 MFEM_ABORT("BilinearFormIntegrator::AssembleDiagonalMF(...)\n"
170 " is not implemented for this class.");
171}
172
174 const FiniteElement &el, ElementTransformation &Trans,
175 DenseMatrix &elmat)
176{
177 MFEM_ABORT("BilinearFormIntegrator::AssembleElementMatrix(...)\n"
178 " is not implemented for this class.");
179}
180
182 const FiniteElement &el1, const FiniteElement &el2,
183 ElementTransformation &Trans, DenseMatrix &elmat)
184{
185 MFEM_ABORT("BilinearFormIntegrator::AssembleElementMatrix2(...)\n"
186 " is not implemented for this class.");
187}
188
190 const int patch, const FiniteElementSpace &fes, SparseMatrix*& smat)
192 mfem_error ("BilinearFormIntegrator::AssemblePatchMatrix(...)\n"
193 " is not implemented for this class.");
194}
195
197 const FiniteElement &el1, const FiniteElement &el2,
199{
200 MFEM_ABORT("BilinearFormIntegrator::AssembleFaceMatrix(...)\n"
201 " is not implemented for this class.");
202}
203
205 const FiniteElement &trial_fe1, const FiniteElement &test_fe1,
206 const FiniteElement &trial_fe2, const FiniteElement &test_fe2,
208 DenseMatrix &elmat)
209{
210 MFEM_ABORT("AssembleFaceMatrix (mixed form) is not implemented for this"
211 " Integrator class.");
212}
213
215 const FiniteElement &trial_face_fe, const FiniteElement &test_fe1,
216 const FiniteElement &test_fe2, FaceElementTransformations &Trans,
217 DenseMatrix &elmat)
218{
219 MFEM_ABORT("AssembleFaceMatrix (mixed form) is not implemented for this"
220 " Integrator class.");
221}
222
224 const FiniteElement &trial_face_fe,
225 const FiniteElement &test_fe1,
227 DenseMatrix &elmat)
228{
229 MFEM_ABORT("AssembleTraceFaceMatrix (DPG form) is not implemented for this"
230 " Integrator class.");
231}
232
234 const Vector &x, const Vector &dxdn, Vector &y, Vector &dydn) const
235{
236 MFEM_ABORT("Not implemented.");
237}
238
240 const FiniteElement &el, ElementTransformation &Tr, const Vector &elfun,
241 Vector &elvect)
242{
243 // Note: This default implementation is general but not efficient
244 DenseMatrix elmat;
245 AssembleElementMatrix(el, Tr, elmat);
246 elvect.SetSize(elmat.Height());
247 elmat.Mult(elfun, elvect);
248}
249
251 const FiniteElement &el1, const FiniteElement &el2,
252 FaceElementTransformations &Tr, const Vector &elfun, Vector &elvect)
253{
254 // Note: This default implementation is general but not efficient
255 DenseMatrix elmat;
256 AssembleFaceMatrix(el1, el2, Tr, elmat);
257 elvect.SetSize(elmat.Height());
258 elmat.Mult(elfun, elvect);
259}
260
262{
263 IntRule = ir;
264 bfi->SetIntRule(ir);
265}
266
268 const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat)
269{
270 bfi->AssembleElementMatrix(el, Trans, bfi_elmat);
271 // elmat = bfi_elmat^t
272 elmat.Transpose (bfi_elmat);
273}
274
276 const FiniteElement &trial_fe, const FiniteElement &test_fe,
277 ElementTransformation &Trans, DenseMatrix &elmat)
278{
279 bfi->AssembleElementMatrix2(test_fe, trial_fe, Trans, bfi_elmat);
280 // elmat = bfi_elmat^t
281 elmat.Transpose (bfi_elmat);
282}
283
285 const FiniteElement &el1, const FiniteElement &el2,
287{
288 bfi->AssembleFaceMatrix(el1, el2, Trans, bfi_elmat);
289 // elmat = bfi_elmat^t
290 elmat.Transpose (bfi_elmat);
291}
292
294 const FiniteElement &tr_el1, const FiniteElement &te_el1,
295 const FiniteElement &tr_el2, const FiniteElement &te_el2,
297{
298 bfi->AssembleFaceMatrix(te_el1, tr_el1, te_el2, tr_el2, Trans, bfi_elmat);
299 // elmat = bfi_elmat^t
300 elmat.Transpose (bfi_elmat);
301}
302
304{
305 IntRule = ir;
306 bfi->SetIntRule(ir);
307}
308
310 const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat)
311{
312 bfi -> AssembleElementMatrix (el, Trans, elmat);
313 elmat.Lump();
314}
315
317{
318 IntRule = ir;
319 integrator->SetIntRule(ir);
320}
321
323 const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat)
324{
325 integrator->AssembleElementMatrix(el, Trans, elmat);
326 elmat.Invert();
327}
328
330{
331 IntRule = ir;
332 for (int i = 0; i < integrators.Size(); i++)
333 {
334 integrators[i]->SetIntRule(ir);
335 }
336}
337
339 const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat)
340{
341 MFEM_ASSERT(integrators.Size() > 0, "empty SumIntegrator.");
342
343 integrators[0]->AssembleElementMatrix(el, Trans, elmat);
344 for (int i = 1; i < integrators.Size(); i++)
345 {
346 integrators[i]->AssembleElementMatrix(el, Trans, elem_mat);
347 elmat += elem_mat;
348 }
349}
350
352 const FiniteElement &el1, const FiniteElement &el2,
353 ElementTransformation &Trans, DenseMatrix &elmat)
354{
355 MFEM_ASSERT(integrators.Size() > 0, "empty SumIntegrator.");
356
357 integrators[0]->AssembleElementMatrix2(el1, el2, Trans, elmat);
358 for (int i = 1; i < integrators.Size(); i++)
359 {
360 integrators[i]->AssembleElementMatrix2(el1, el2, Trans, elem_mat);
361 elmat += elem_mat;
362 }
363}
364
366 const FiniteElement &el1, const FiniteElement &el2,
368{
369 MFEM_ASSERT(integrators.Size() > 0, "empty SumIntegrator.");
370
371 integrators[0]->AssembleFaceMatrix(el1, el2, Trans, elmat);
372 for (int i = 1; i < integrators.Size(); i++)
373 {
374 integrators[i]->AssembleFaceMatrix(el1, el2, Trans, elem_mat);
375 elmat += elem_mat;
376 }
377}
378
380 const FiniteElement &tr_fe,
381 const FiniteElement &te_fe1, const FiniteElement &te_fe2,
383{
384 MFEM_ASSERT(integrators.Size() > 0, "empty SumIntegrator.");
385
386 integrators[0]->AssembleFaceMatrix(tr_fe, te_fe1, te_fe2, Trans, elmat);
387 for (int i = 1; i < integrators.Size(); i++)
388 {
389 integrators[i]->AssembleFaceMatrix(tr_fe, te_fe1, te_fe2, Trans, elem_mat);
390 elmat += elem_mat;
391 }
392}
393
395{
396 for (int i = 0; i < integrators.Size(); i++)
397 {
398 integrators[i]->AssemblePA(fes);
399 }
400}
401
403{
404 for (int i = 0; i < integrators.Size(); i++)
405 {
406 integrators[i]->AssembleDiagonalPA(diag);
407 }
408}
409
411{
412 for (int i = 0; i < integrators.Size(); i++)
413 {
414 integrators[i]->AssemblePAInteriorFaces(fes);
415 }
416}
417
419{
420 for (int i = 0; i < integrators.Size(); i++)
421 {
422 integrators[i]->AssemblePABoundaryFaces(fes);
423 }
424}
425
426void SumIntegrator::AddMultPA(const Vector& x, Vector& y) const
427{
428 for (int i = 0; i < integrators.Size(); i++)
429 {
430 integrators[i]->AddMultPA(x, y);
431 }
432}
433
435{
436 for (int i = 0; i < integrators.Size(); i++)
437 {
438 integrators[i]->AddAbsMultPA(x, y);
439 }
440}
441
443{
444 for (int i = 0; i < integrators.Size(); i++)
445 {
446 integrators[i]->AddMultTransposePA(x, y);
447 }
448}
449
451{
452 for (int i = 0; i < integrators.Size(); i++)
453 {
454 integrators[i]->AddAbsMultTransposePA(x, y);
455 }
456}
457
459{
460 for (int i = 0; i < integrators.Size(); i++)
461 {
462 integrators[i]->AssembleMF(fes);
463 }
464}
465
466void SumIntegrator::AddMultMF(const Vector& x, Vector& y) const
467{
468 for (int i = 0; i < integrators.Size(); i++)
469 {
470 integrators[i]->AddMultMF(x, y);
471 }
472}
473
475{
476 for (int i = 0; i < integrators.Size(); i++)
477 {
478 integrators[i]->AddMultTransposeMF(x, y);
479 }
480}
481
483{
484 for (int i = 0; i < integrators.Size(); i++)
485 {
486 integrators[i]->AssembleDiagonalMF(diag);
487 }
488}
489
491 const bool add)
492{
493 for (int i = 0; i < integrators.Size(); i++)
494 {
495 integrators[i]->AssembleEA(fes, emat, add);
496 }
497}
498
500 Vector &ea_data_int,
501 Vector &ea_data_ext,
502 const bool add)
503{
504 for (int i = 0; i < integrators.Size(); i++)
505 {
506 integrators[i]->AssembleEAInteriorFaces(fes,ea_data_int,ea_data_ext,add);
507 }
508}
509
511 Vector &ea_data_bdr,
512 const bool add)
513{
514 for (int i = 0; i < integrators.Size(); i++)
515 {
516 integrators[i]->AssembleEABoundaryFaces(fes, ea_data_bdr, add);
517 }
518}
519
521{
522 if (own_integrators)
523 {
524 for (int i = 0; i < integrators.Size(); i++)
525 {
526 delete integrators[i];
527 }
528 }
529}
530
532 const FiniteElement &trial_fe, const FiniteElement &test_fe,
533 ElementTransformation &Trans, DenseMatrix &elmat)
534{
535 MFEM_ASSERT(this->VerifyFiniteElementTypes(trial_fe, test_fe),
537
538 int trial_nd = trial_fe.GetDof(), test_nd = test_fe.GetDof(), i;
539 bool same_shapes = same_calc_shape && (&trial_fe == &test_fe);
540
541#ifdef MFEM_THREAD_SAFE
542 Vector test_shape(test_nd);
543 Vector trial_shape;
544#else
545 test_shape.SetSize(test_nd);
546#endif
547 if (same_shapes)
548 {
549 trial_shape.NewDataAndSize(test_shape.GetData(), trial_nd);
550 }
551 else
552 {
553 trial_shape.SetSize(trial_nd);
554 }
555
556 elmat.SetSize(test_nd, trial_nd);
557
558
559 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
560 if (ir == NULL)
561 {
562 int ir_order = this->GetIntegrationOrder(trial_fe, test_fe, Trans);
563 ir = &IntRules.Get(trial_fe.GetGeomType(), ir_order);
564 }
565
566 elmat = 0.0;
567 for (i = 0; i < ir->GetNPoints(); i++)
568 {
569 const IntegrationPoint &ip = ir->IntPoint(i);
570 Trans.SetIntPoint(&ip);
571
572 this->CalcTestShape(test_fe, Trans, test_shape);
573 this->CalcTrialShape(trial_fe, Trans, trial_shape);
574
575 real_t w = Trans.Weight() * ip.weight;
576
577 if (Q)
578 {
579 w *= Q->Eval(Trans, ip);
580 }
581 AddMult_a_VWt(w, test_shape, trial_shape, elmat);
582 }
583#ifndef MFEM_THREAD_SAFE
584 if (same_shapes)
585 {
586 trial_shape.SetDataAndSize(NULL, 0);
587 }
588#endif
589}
590
592 const FiniteElement &trial_fe, const FiniteElement &test_fe,
593 ElementTransformation &Trans, DenseMatrix &elmat)
594{
595 MFEM_ASSERT(this->VerifyFiniteElementTypes(trial_fe, test_fe),
597
598 space_dim = Trans.GetSpaceDim();
599 int trial_nd = trial_fe.GetDof(), test_nd = test_fe.GetDof(), i;
600 int test_vdim = GetTestVDim(test_fe);
601 int trial_vdim = GetTrialVDim(trial_fe);
602 bool same_shapes = same_calc_shape && (&trial_fe == &test_fe);
603
604 if (MQ)
605 {
606 MFEM_VERIFY(MQ->GetHeight() == test_vdim,
607 "Dimension mismatch in height of matrix coefficient.");
608 MFEM_VERIFY(MQ->GetWidth() == trial_vdim,
609 "Dimension mismatch in width of matrix coefficient.");
610 }
611 if (DQ)
612 {
613 MFEM_VERIFY(trial_vdim == test_vdim,
614 "Diagonal matrix coefficient requires matching "
615 "test and trial vector dimensions.");
616 MFEM_VERIFY(DQ->GetVDim() == trial_vdim,
617 "Dimension mismatch in diagonal matrix coefficient.");
618 }
619 if (VQ)
620 {
621 MFEM_VERIFY(VQ->GetVDim() == 3, "Vector coefficient must have "
622 "dimension equal to three.");
623 }
624
625#ifdef MFEM_THREAD_SAFE
626 Vector V(VQ ? VQ->GetVDim() : 0);
627 Vector D(DQ ? DQ->GetVDim() : 0);
628 DenseMatrix M(MQ ? MQ->GetHeight() : 0, MQ ? MQ->GetWidth() : 0);
629 DenseMatrix test_shape(test_nd, test_vdim);
630 DenseMatrix trial_shape;
631 DenseMatrix shape_tmp(test_nd, trial_vdim);
632#else
633 V.SetSize(VQ ? VQ->GetVDim() : 0);
634 D.SetSize(DQ ? DQ->GetVDim() : 0);
635 M.SetSize(MQ ? MQ->GetHeight() : 0, MQ ? MQ->GetWidth() : 0);
636 test_shape.SetSize(test_nd, test_vdim);
637 shape_tmp.SetSize(test_nd, trial_vdim);
638#endif
639 if (same_shapes)
640 {
641 trial_shape.Reset(test_shape.Data(), trial_nd, trial_vdim);
642 }
643 else
644 {
645 trial_shape.SetSize(trial_nd, trial_vdim);
646 }
647
648 elmat.SetSize(test_nd, trial_nd);
649
650 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
651 if (ir == NULL)
652 {
653 int ir_order = this->GetIntegrationOrder(trial_fe, test_fe, Trans);
654 ir = &IntRules.Get(trial_fe.GetGeomType(), ir_order);
655 }
656
657 elmat = 0.0;
658 for (i = 0; i < ir->GetNPoints(); i++)
659 {
660 const IntegrationPoint &ip = ir->IntPoint(i);
661 Trans.SetIntPoint(&ip);
662
663 this->CalcTestShape(test_fe, Trans, test_shape);
664 if (!same_shapes)
665 {
666 this->CalcTrialShape(trial_fe, Trans, trial_shape);
667 }
668
669 real_t w = Trans.Weight() * ip.weight;
670
671 if (MQ)
672 {
673 MQ->Eval(M, Trans, ip);
674 M *= w;
675 Mult(test_shape, M, shape_tmp);
676 AddMultABt(shape_tmp, trial_shape, elmat);
677 }
678 else if (DQ)
679 {
680 DQ->Eval(D, Trans, ip);
681 D *= w;
682 AddMultADBt(test_shape, D, trial_shape, elmat);
683 }
684 else if (VQ)
685 {
686 VQ->Eval(V, Trans, ip);
687 V *= w;
688
689 for (int j=0; j<test_nd; j++)
690 {
691 // Compute shape_tmp = test_shape x V
692 // V will always be of length 3
693 // shape_dim and test_shape could have reduced dimension
694 // i.e. 1D or 2D
695 if (test_vdim == 3 && trial_vdim == 3)
696 {
697 shape_tmp(j,0) = test_shape(j,1) * V(2) -
698 test_shape(j,2) * V(1);
699 shape_tmp(j,1) = test_shape(j,2) * V(0) -
700 test_shape(j,0) * V(2);
701 shape_tmp(j,2) = test_shape(j,0) * V(1) -
702 test_shape(j,1) * V(0);
703 }
704 else if (test_vdim == 3 && trial_vdim == 2)
705 {
706 shape_tmp(j,0) = test_shape(j,1) * V(2) -
707 test_shape(j,2) * V(1);
708 shape_tmp(j,1) = test_shape(j,2) * V(0) -
709 test_shape(j,0) * V(2);
710 }
711 else if (test_vdim == 3 && trial_vdim == 1)
712 {
713 shape_tmp(j,0) = test_shape(j,1) * V(2) -
714 test_shape(j,2) * V(1);
715 }
716 else if (test_vdim == 2 && trial_vdim == 3)
717 {
718 shape_tmp(j,0) = test_shape(j,1) * V(2);
719 shape_tmp(j,1) = -test_shape(j,0) * V(2);
720 shape_tmp(j,2) = test_shape(j,0) * V(1) -
721 test_shape(j,1) * V(0);
722 }
723 else if (test_vdim == 2 && trial_vdim == 2)
724 {
725 shape_tmp(j,0) = test_shape(j,1) * V(2);
726 shape_tmp(j,1) = -test_shape(j,0) * V(2);
727 }
728 else if (test_vdim == 1 && trial_vdim == 3)
729 {
730 shape_tmp(j,0) = 0.0;
731 shape_tmp(j,1) = -test_shape(j,0) * V(2);
732 shape_tmp(j,2) = test_shape(j,0) * V(1);
733 }
734 else if (test_vdim == 1 && trial_vdim == 1)
735 {
736 shape_tmp(j,0) = 0.0;
737 }
738 }
739 AddMultABt(shape_tmp, trial_shape, elmat);
740 }
741 else
742 {
743 if (Q)
744 {
745 w *= Q -> Eval (Trans, ip);
746 }
747 if (same_shapes)
748 {
749 AddMult_a_AAt (w, test_shape, elmat);
750 }
751 else
752 {
753 AddMult_a_ABt (w, test_shape, trial_shape, elmat);
754 }
755 }
756 }
757#ifndef MFEM_THREAD_SAFE
758 if (same_shapes)
759 {
760 trial_shape.ClearExternalData();
761 }
762#endif
763}
764
766 const FiniteElement &trial_fe, const FiniteElement &test_fe,
767 ElementTransformation &Trans, DenseMatrix &elmat)
768{
769 MFEM_ASSERT(this->VerifyFiniteElementTypes(trial_fe, test_fe),
771
772 MFEM_VERIFY(VQ, "MixedScalarVectorIntegrator: "
773 "VectorCoefficient must be set");
774
775 const FiniteElement * vec_fe = transpose?&trial_fe:&test_fe;
776 const FiniteElement * sca_fe = transpose?&test_fe:&trial_fe;
777
778 space_dim = Trans.GetSpaceDim();
779 int trial_nd = trial_fe.GetDof(), test_nd = test_fe.GetDof(), i;
780 int sca_nd = sca_fe->GetDof();
781 int vec_nd = vec_fe->GetDof();
782 int vdim = GetVDim(*vec_fe);
783 real_t vtmp;
784
785 MFEM_VERIFY(VQ->GetVDim() == vdim, "MixedScalarVectorIntegrator: "
786 "Dimensions of VectorCoefficient and Vector-valued basis "
787 "functions must match");
788
789#ifdef MFEM_THREAD_SAFE
790 Vector V(vdim);
791 DenseMatrix vshape(vec_nd, vdim);
792 Vector shape(sca_nd);
793 Vector vshape_tmp(vec_nd);
794#else
795 V.SetSize(vdim);
796 vshape.SetSize(vec_nd, vdim);
797 shape.SetSize(sca_nd);
798 vshape_tmp.SetSize(vec_nd);
799#endif
800
801 Vector V_test(transpose?shape.GetData():vshape_tmp.GetData(),test_nd);
802 Vector W_trial(transpose?vshape_tmp.GetData():shape.GetData(),trial_nd);
803
804 elmat.SetSize(test_nd, trial_nd);
805
806
807 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
808 if (ir == NULL)
809 {
810 int ir_order = this->GetIntegrationOrder(trial_fe, test_fe, Trans);
811 ir = &IntRules.Get(trial_fe.GetGeomType(), ir_order);
812 }
813
814 elmat = 0.0;
815 for (i = 0; i < ir->GetNPoints(); i++)
816 {
817 const IntegrationPoint &ip = ir->IntPoint(i);
818 Trans.SetIntPoint(&ip);
819
820 this->CalcShape(*sca_fe, Trans, shape);
821 this->CalcVShape(*vec_fe, Trans, vshape);
822
823 real_t w = Trans.Weight() * ip.weight;
824
825 VQ->Eval(V, Trans, ip);
826 V *= w;
827
828 if ( vdim == 2 && cross_2d )
829 {
830 vtmp = V[0];
831 V[0] = -V[1];
832 V[1] = vtmp;
833 }
834
835 vshape.Mult(V,vshape_tmp);
836 AddMultVWt(V_test, W_trial, elmat);
837 }
838}
839
840
842 const FiniteElement &trial_fe, const FiniteElement &test_fe,
843 ElementTransformation &Trans, DenseMatrix &elmat)
844{
845 dim = test_fe.GetDim();
846 int trial_dof = trial_fe.GetDof();
847 int test_dof = test_fe.GetDof();
848 real_t c;
849 Vector d_col;
850
851 dshape.SetSize(trial_dof, dim);
852 gshape.SetSize(trial_dof, dim);
853 Jadj.SetSize(dim);
854 shape.SetSize(test_dof);
855 elmat.SetSize(dim * test_dof, trial_dof);
856
857
858 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
859 elmat = 0.0;
860 elmat_comp.SetSize(test_dof, trial_dof);
861
862 for (int i = 0; i < ir->GetNPoints(); i++)
863 {
864 const IntegrationPoint &ip = ir->IntPoint(i);
865 Trans.SetIntPoint(&ip);
866
867 CalcAdjugate(Trans.Jacobian(), Jadj);
868
869 test_fe.CalcPhysShape(Trans, shape);
870 trial_fe.CalcDShape(ip, dshape);
871
872 Mult(dshape, Jadj, gshape);
873
874 c = ip.weight;
875 if (Q)
876 {
877 c *= Q->Eval(Trans, ip);
878 }
879 shape *= c;
880
881 for (int d = 0; d < dim; ++d)
882 {
883 gshape.GetColumnReference(d, d_col);
884 MultVWt(shape, d_col, elmat_comp);
885 for (int jj = 0; jj < trial_dof; ++jj)
886 {
887 for (int ii = 0; ii < test_dof; ++ii)
888 {
889 elmat(d * test_dof + ii, jj) += elmat_comp(ii, jj);
890 }
891 }
892 }
893 }
894}
895
897 &trial_fe,
898 const FiniteElement &test_fe,
899 const ElementTransformation &Trans)
900{
901 int order = Trans.OrderGrad(&trial_fe) + test_fe.GetOrder() + Trans.OrderJ();
902 return IntRules.Get(trial_fe.GetGeomType(), order);
903}
904
905
908 Q(nullptr), VQ(nullptr), MQ(nullptr), maps(nullptr), geom(nullptr)
909{
910 static Kernels kernels;
911}
912
919
926
933
935( const FiniteElement &el, ElementTransformation &Trans,
936 DenseMatrix &elmat )
937{
938 int nd = el.GetDof();
939 dim = el.GetDim();
940 int spaceDim = Trans.GetSpaceDim();
941 bool square = (dim == spaceDim);
942 real_t w;
943
944 if (VQ)
945 {
946 MFEM_VERIFY(VQ->GetVDim() == spaceDim,
947 "Unexpected dimension for VectorCoefficient");
948 }
949 if (MQ)
950 {
951 MFEM_VERIFY(MQ->GetWidth() == spaceDim,
952 "Unexpected width for MatrixCoefficient");
953 MFEM_VERIFY(MQ->GetHeight() == spaceDim,
954 "Unexpected height for MatrixCoefficient");
955 }
956
957#ifdef MFEM_THREAD_SAFE
958 DenseMatrix dshape(nd, dim), dshapedxt(nd, spaceDim);
959 DenseMatrix dshapedxt_m(nd, MQ ? spaceDim : 0);
960 DenseMatrix M(MQ ? spaceDim : 0);
961 Vector D(VQ ? VQ->GetVDim() : 0);
962#else
963 dshape.SetSize(nd, dim);
964 dshapedxt.SetSize(nd, spaceDim);
965 dshapedxt_m.SetSize(nd, MQ ? spaceDim : 0);
966 M.SetSize(MQ ? spaceDim : 0);
967 D.SetSize(VQ ? VQ->GetVDim() : 0);
968#endif
969 elmat.SetSize(nd);
970
971 const IntegrationRule *ir = GetIntegrationRule(el, Trans);
972 elmat = 0.0;
973 for (int i = 0; i < ir->GetNPoints(); i++)
974 {
975 const IntegrationPoint &ip = ir->IntPoint(i);
976 el.CalcDShape(ip, dshape);
977
978 Trans.SetIntPoint(&ip);
979 w = Trans.Weight();
980 w = ip.weight / (square ? w : w*w*w);
981 // AdjugateJacobian = / adj(J), if J is square
982 // \ adj(J^t.J).J^t, otherwise
983 Mult(dshape, Trans.AdjugateJacobian(), dshapedxt);
984 if (MQ)
985 {
986 MQ->Eval(M, Trans, ip);
987 M *= w;
988 Mult(dshapedxt, M, dshapedxt_m);
989 AddMultABt(dshapedxt_m, dshapedxt, elmat);
990 }
991 else if (VQ)
992 {
993 VQ->Eval(D, Trans, ip);
994 D *= w;
995 AddMultADAt(dshapedxt, D, elmat);
996 }
997 else
998 {
999 if (Q)
1000 {
1001 w *= Q->Eval(Trans, ip);
1002 }
1003 AddMult_a_AAt(w, dshapedxt, elmat);
1004 }
1005 }
1006}
1007
1009 const FiniteElement &trial_fe, const FiniteElement &test_fe,
1010 ElementTransformation &Trans, DenseMatrix &elmat)
1011{
1012 int tr_nd = trial_fe.GetDof();
1013 int te_nd = test_fe.GetDof();
1014 dim = trial_fe.GetDim();
1015 int spaceDim = Trans.GetSpaceDim();
1016 bool square = (dim == spaceDim);
1017 real_t w;
1018
1019 if (VQ)
1020 {
1021 MFEM_VERIFY(VQ->GetVDim() == spaceDim,
1022 "Unexpected dimension for VectorCoefficient");
1023 }
1024 if (MQ)
1025 {
1026 MFEM_VERIFY(MQ->GetWidth() == spaceDim,
1027 "Unexpected width for MatrixCoefficient");
1028 MFEM_VERIFY(MQ->GetHeight() == spaceDim,
1029 "Unexpected height for MatrixCoefficient");
1030 }
1031
1032#ifdef MFEM_THREAD_SAFE
1033 DenseMatrix dshape(tr_nd, dim), dshapedxt(tr_nd, spaceDim);
1034 DenseMatrix te_dshape(te_nd, dim), te_dshapedxt(te_nd, spaceDim);
1035 DenseMatrix invdfdx(dim, spaceDim);
1036 DenseMatrix dshapedxt_m(te_nd, MQ ? spaceDim : 0);
1037 DenseMatrix M(MQ ? spaceDim : 0);
1038 Vector D(VQ ? VQ->GetVDim() : 0);
1039#else
1040 dshape.SetSize(tr_nd, dim);
1041 dshapedxt.SetSize(tr_nd, spaceDim);
1042 te_dshape.SetSize(te_nd, dim);
1043 te_dshapedxt.SetSize(te_nd, spaceDim);
1044 invdfdx.SetSize(dim, spaceDim);
1045 dshapedxt_m.SetSize(te_nd, MQ ? spaceDim : 0);
1046 M.SetSize(MQ ? spaceDim : 0);
1047 D.SetSize(VQ ? VQ->GetVDim() : 0);
1048#endif
1049 elmat.SetSize(te_nd, tr_nd);
1050
1051 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
1052 elmat = 0.0;
1053 for (int i = 0; i < ir->GetNPoints(); i++)
1054 {
1055 const IntegrationPoint &ip = ir->IntPoint(i);
1056 trial_fe.CalcDShape(ip, dshape);
1057 test_fe.CalcDShape(ip, te_dshape);
1058
1059 Trans.SetIntPoint(&ip);
1060 CalcAdjugate(Trans.Jacobian(), invdfdx);
1061 w = Trans.Weight();
1062 w = ip.weight / (square ? w : w*w*w);
1063 Mult(dshape, invdfdx, dshapedxt);
1064 Mult(te_dshape, invdfdx, te_dshapedxt);
1065 // invdfdx, dshape, and te_dshape no longer needed
1066 if (MQ)
1067 {
1068 MQ->Eval(M, Trans, ip);
1069 M *= w;
1070 Mult(te_dshapedxt, M, dshapedxt_m);
1071 AddMultABt(dshapedxt_m, dshapedxt, elmat);
1072 }
1073 else if (VQ)
1074 {
1075 VQ->Eval(D, Trans, ip);
1076 D *= w;
1077 AddMultADAt(dshapedxt, D, elmat);
1078 }
1079 else
1080 {
1081 if (Q)
1082 {
1083 w *= Q->Eval(Trans, ip);
1084 }
1085 dshapedxt *= w;
1086 AddMultABt(te_dshapedxt, dshapedxt, elmat);
1087 }
1088 }
1089}
1090
1092 const FiniteElement &el, ElementTransformation &Tr, const Vector &elfun,
1093 Vector &elvect)
1094{
1095 int nd = el.GetDof();
1096 dim = el.GetDim();
1097 int spaceDim = Tr.GetSpaceDim();
1098 real_t w;
1099
1100 if (VQ)
1101 {
1102 MFEM_VERIFY(VQ->GetVDim() == spaceDim,
1103 "Unexpected dimension for VectorCoefficient");
1104 }
1105 if (MQ)
1106 {
1107 MFEM_VERIFY(MQ->GetWidth() == spaceDim,
1108 "Unexpected width for MatrixCoefficient");
1109 MFEM_VERIFY(MQ->GetHeight() == spaceDim,
1110 "Unexpected height for MatrixCoefficient");
1111 }
1112
1113#ifdef MFEM_THREAD_SAFE
1114 DenseMatrix dshape(nd,dim), invdfdx(dim, spaceDim), M(MQ ? spaceDim : 0);
1115 Vector D(VQ ? VQ->GetVDim() : 0);
1116#else
1117 dshape.SetSize(nd,dim);
1118 invdfdx.SetSize(dim, spaceDim);
1119 M.SetSize(MQ ? spaceDim : 0);
1120 D.SetSize(VQ ? VQ->GetVDim() : 0);
1121#endif
1122 vec.SetSize(dim);
1123 vecdxt.SetSize((VQ || MQ) ? spaceDim : 0);
1124 pointflux.SetSize(spaceDim);
1125
1126 elvect.SetSize(nd);
1127
1128
1129 const IntegrationRule *ir = GetIntegrationRule(el, Tr);
1130 elvect = 0.0;
1131 for (int i = 0; i < ir->GetNPoints(); i++)
1132 {
1133 const IntegrationPoint &ip = ir->IntPoint(i);
1134 el.CalcDShape(ip, dshape);
1135
1136 Tr.SetIntPoint(&ip);
1137 CalcAdjugate(Tr.Jacobian(), invdfdx); // invdfdx = adj(J)
1138 w = ip.weight / Tr.Weight();
1139
1140 if (!MQ && !VQ)
1141 {
1142 dshape.MultTranspose(elfun, vec);
1143 invdfdx.MultTranspose(vec, pointflux);
1144 if (Q)
1145 {
1146 w *= Q->Eval(Tr, ip);
1147 }
1148 }
1149 else
1150 {
1151 dshape.MultTranspose(elfun, vec);
1152 invdfdx.MultTranspose(vec, vecdxt);
1153 if (MQ)
1154 {
1155 MQ->Eval(M, Tr, ip);
1156 M.Mult(vecdxt, pointflux);
1157 }
1158 else
1159 {
1160 VQ->Eval(D, Tr, ip);
1161 for (int j=0; j<spaceDim; ++j)
1162 {
1163 pointflux[j] = D[j] * vecdxt[j];
1164 }
1165 }
1166 }
1167 pointflux *= w;
1168 invdfdx.Mult(pointflux, vec);
1169 dshape.AddMult(vec, elvect);
1170 }
1171}
1172
1174( const FiniteElement &el, ElementTransformation &Trans,
1175 Vector &u, const FiniteElement &fluxelem, Vector &flux, bool with_coef,
1176 const IntegrationRule *ir)
1177{
1178 int nd, spaceDim, fnd;
1179
1180 nd = el.GetDof();
1181 dim = el.GetDim();
1182 spaceDim = Trans.GetSpaceDim();
1183
1184 if (VQ)
1185 {
1186 MFEM_VERIFY(VQ->GetVDim() == spaceDim,
1187 "Unexpected dimension for VectorCoefficient");
1188 }
1189 if (MQ)
1190 {
1191 MFEM_VERIFY(MQ->GetWidth() == spaceDim,
1192 "Unexpected width for MatrixCoefficient");
1193 MFEM_VERIFY(MQ->GetHeight() == spaceDim,
1194 "Unexpected height for MatrixCoefficient");
1195 }
1196
1197#ifdef MFEM_THREAD_SAFE
1198 DenseMatrix dshape(nd,dim), invdfdx(dim, spaceDim);
1199 DenseMatrix M(MQ ? spaceDim : 0);
1200 Vector D(VQ ? VQ->GetVDim() : 0);
1201#else
1202 dshape.SetSize(nd,dim);
1203 invdfdx.SetSize(dim, spaceDim);
1204 M.SetSize(MQ ? spaceDim : 0);
1205 D.SetSize(VQ ? VQ->GetVDim() : 0);
1206#endif
1207 vec.SetSize(dim);
1208 vecdxt.SetSize(spaceDim);
1209 pointflux.SetSize(MQ || VQ ? spaceDim : 0);
1210
1211 if (!ir)
1212 {
1213 ir = &fluxelem.GetNodes();
1214 }
1215 fnd = ir->GetNPoints();
1216 flux.SetSize( fnd * spaceDim );
1217
1218 for (int i = 0; i < fnd; i++)
1219 {
1220 const IntegrationPoint &ip = ir->IntPoint(i);
1221 el.CalcDShape(ip, dshape);
1222 dshape.MultTranspose(u, vec);
1223
1224 Trans.SetIntPoint (&ip);
1225 CalcInverse(Trans.Jacobian(), invdfdx);
1226 invdfdx.MultTranspose(vec, vecdxt);
1227
1228 if (with_coef)
1229 {
1230 if (!MQ && !VQ)
1231 {
1232 if (Q)
1233 {
1234 vecdxt *= Q->Eval(Trans,ip);
1235 }
1236 for (int j = 0; j < spaceDim; j++)
1237 {
1238 flux(fnd*j+i) = vecdxt(j);
1239 }
1240 }
1241 else
1242 {
1243 if (MQ)
1244 {
1245 MQ->Eval(M, Trans, ip);
1246 M.Mult(vecdxt, pointflux);
1247 }
1248 else
1249 {
1250 VQ->Eval(D, Trans, ip);
1251 for (int j=0; j<spaceDim; ++j)
1252 {
1253 pointflux[j] = D[j] * vecdxt[j];
1254 }
1255 }
1256 for (int j = 0; j < spaceDim; j++)
1257 {
1258 flux(fnd*j+i) = pointflux(j);
1259 }
1260 }
1261 }
1262 else
1263 {
1264 for (int j = 0; j < spaceDim; j++)
1265 {
1266 flux(fnd*j+i) = vecdxt(j);
1267 }
1268 }
1269 }
1270}
1271
1273( const FiniteElement &fluxelem, ElementTransformation &Trans,
1274 Vector &flux, Vector* d_energy)
1275{
1276 int nd = fluxelem.GetDof();
1277 dim = fluxelem.GetDim();
1278 int spaceDim = Trans.GetSpaceDim();
1279
1280#ifdef MFEM_THREAD_SAFE
1281 DenseMatrix M;
1282 Vector D(VQ ? VQ->GetVDim() : 0);
1283#else
1284 D.SetSize(VQ ? VQ->GetVDim() : 0);
1285#endif
1286
1287 shape.SetSize(nd);
1288 pointflux.SetSize(spaceDim);
1289 if (d_energy) { vec.SetSize(spaceDim); }
1290 if (MQ) { M.SetSize(spaceDim); }
1291
1292 int order = 2 * fluxelem.GetOrder(); // <--
1293 const IntegrationRule *ir = &IntRules.Get(fluxelem.GetGeomType(), order);
1294 real_t energy = 0.0;
1295 if (d_energy) { *d_energy = 0.0; }
1296
1297 for (int i = 0; i < ir->GetNPoints(); i++)
1298 {
1299 const IntegrationPoint &ip = ir->IntPoint(i);
1300 Trans.SetIntPoint(&ip);
1301 fluxelem.CalcPhysShape(Trans, shape);
1302
1303 pointflux = 0.0;
1304 for (int k = 0; k < spaceDim; k++)
1305 {
1306 for (int j = 0; j < nd; j++)
1307 {
1308 pointflux(k) += flux(k*nd+j)*shape(j);
1309 }
1310 }
1311
1312 real_t w = Trans.Weight() * ip.weight;
1313
1314 if (MQ)
1315 {
1316 MQ->Eval(M, Trans, ip);
1317 energy += w * M.InnerProduct(pointflux, pointflux);
1318 }
1319 else if (VQ)
1320 {
1321 VQ->Eval(D, Trans, ip);
1322 D *= pointflux;
1323 energy += w * (D * pointflux);
1324 }
1325 else
1326 {
1327 real_t e = (pointflux * pointflux);
1328 if (Q) { e *= Q->Eval(Trans, ip); }
1329 energy += w * e;
1330 }
1331
1332 if (d_energy)
1333 {
1334 // transform pointflux to the ref. domain and integrate the components
1335 Trans.Jacobian().MultTranspose(pointflux, vec);
1336 for (int k = 0; k < dim; k++)
1337 {
1338 (*d_energy)[k] += w * vec[k] * vec[k];
1339 }
1340 // TODO: Q, VQ, MQ
1341 }
1342 }
1343
1344 return energy;
1345}
1346
1348 const FiniteElement &trial_fe, const FiniteElement &test_fe,
1349 const bool stroud)
1350{
1351 int order;
1352 if (trial_fe.Space() == FunctionSpace::Pk)
1353 {
1354 order = trial_fe.GetOrder() + test_fe.GetOrder() - 2;
1355 }
1356 else
1357 {
1358 // order = 2*el.GetOrder() - 2; // <-- this seems to work fine too
1359 order = trial_fe.GetOrder() + test_fe.GetOrder() + trial_fe.GetDim() - 1;
1360 }
1361
1362 if (trial_fe.Space() == FunctionSpace::rQk)
1363 {
1364 return RefinedIntRules.Get(trial_fe.GetGeomType(), order);
1365 }
1366
1367 if (stroud)
1368 {
1369 return StroudIntRules.Get(trial_fe.GetGeomType(), order);
1370 }
1371 else
1372 {
1373 return IntRules.Get(trial_fe.GetGeomType(), order);
1374 }
1375}
1376
1378 : BilinearFormIntegrator(ir), Q(nullptr), maps(nullptr), geom(nullptr)
1379{
1380 static Kernels kernels;
1381}
1382
1384 : MassIntegrator(ir)
1385{
1386 Q = &q;
1387}
1388
1390( const FiniteElement &el, ElementTransformation &Trans,
1391 DenseMatrix &elmat )
1392{
1393 int nd = el.GetDof();
1394 // int dim = el.GetDim();
1395 real_t w;
1396
1397#ifdef MFEM_THREAD_SAFE
1398 Vector shape;
1399#endif
1400 elmat.SetSize(nd);
1401 shape.SetSize(nd);
1402
1403
1404 const IntegrationRule *ir = GetIntegrationRule(el, Trans);
1405 elmat = 0.0;
1406 for (int i = 0; i < ir->GetNPoints(); i++)
1407 {
1408 const IntegrationPoint &ip = ir->IntPoint(i);
1409 Trans.SetIntPoint (&ip);
1410
1411 el.CalcPhysShape(Trans, shape);
1412
1413 w = Trans.Weight() * ip.weight;
1414 if (Q)
1415 {
1416 w *= Q -> Eval(Trans, ip);
1417 }
1418
1419 AddMult_a_VVt(w, shape, elmat);
1420 }
1421}
1422
1424 const FiniteElement &trial_fe, const FiniteElement &test_fe,
1425 ElementTransformation &Trans, DenseMatrix &elmat)
1426{
1427 int tr_nd = trial_fe.GetDof();
1428 int te_nd = test_fe.GetDof();
1429 real_t w;
1430
1431#ifdef MFEM_THREAD_SAFE
1433#endif
1434 elmat.SetSize(te_nd, tr_nd);
1435 shape.SetSize(tr_nd);
1436 te_shape.SetSize(te_nd);
1437
1438 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
1439 elmat = 0.0;
1440 for (int i = 0; i < ir->GetNPoints(); i++)
1441 {
1442 const IntegrationPoint &ip = ir->IntPoint(i);
1443 Trans.SetIntPoint (&ip);
1444
1445 trial_fe.CalcPhysShape(Trans, shape);
1446 test_fe.CalcPhysShape(Trans, te_shape);
1447
1448 w = Trans.Weight() * ip.weight;
1449 if (Q)
1450 {
1451 w *= Q -> Eval(Trans, ip);
1452 }
1453
1454 te_shape *= w;
1455 AddMultVWt(te_shape, shape, elmat);
1456 }
1457}
1458
1460 const FiniteElement &test_fe,
1461 const ElementTransformation &Trans,
1462 const bool stroud)
1463{
1464 // int order = trial_fe.GetOrder() + test_fe.GetOrder();
1465 const int order = trial_fe.GetOrder() + test_fe.GetOrder() + Trans.OrderW();
1466
1467 if (trial_fe.Space() == FunctionSpace::rQk)
1468 {
1469 return RefinedIntRules.Get(trial_fe.GetGeomType(), order);
1470 }
1471
1472 if (stroud)
1473 {
1474 return StroudIntRules.Get(trial_fe.GetGeomType(), order);
1475 }
1476 else
1477 {
1478 return IntRules.Get(trial_fe.GetGeomType(), order);
1479 }
1480}
1481
1482
1484 const FiniteElement &el1, const FiniteElement &el2,
1486{
1487 MFEM_ASSERT(Trans.Elem2No < 0,
1488 "support for interior faces is not implemented");
1489
1490 int nd1 = el1.GetDof();
1491 real_t w;
1492
1493#ifdef MFEM_THREAD_SAFE
1494 Vector shape;
1495#endif
1496 elmat.SetSize(nd1);
1497 shape.SetSize(nd1);
1498
1499 const IntegrationRule *ir = IntRule;
1500 if (ir == NULL)
1501 {
1502 int order = 2 * el1.GetOrder();
1503
1504 ir = &IntRules.Get(Trans.GetGeometryType(), order);
1505 }
1506
1507 elmat = 0.0;
1508 for (int i = 0; i < ir->GetNPoints(); i++)
1509 {
1510 const IntegrationPoint &ip = ir->IntPoint(i);
1511
1512 // Set the integration point in the face and the neighboring element
1513 Trans.SetAllIntPoints(&ip);
1514
1515 el1.CalcPhysShape(*Trans.Elem1, shape);
1516
1517 w = Trans.Weight() * ip.weight;
1518 if (Q)
1519 {
1520 w *= Q -> Eval(Trans, ip);
1521 }
1522
1523 AddMult_a_VVt(w, shape, elmat);
1524 }
1525}
1526
1528 const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat)
1529{
1530 int nd = el.GetDof();
1531 dim = el.GetDim();
1532
1533#ifdef MFEM_THREAD_SAFE
1534 DenseMatrix dshape, adjJ, Q_ir;
1535 Vector shape, vec2, BdFidxT;
1536#endif
1537 elmat.SetSize(nd);
1538 dshape.SetSize(nd,dim);
1539 adjJ.SetSize(dim);
1540 shape.SetSize(nd);
1541 vec2.SetSize(dim);
1542 BdFidxT.SetSize(nd);
1543
1544 Vector vec1;
1545
1546
1547 const IntegrationRule *ir = GetIntegrationRule(el, Trans);
1548 if (ir == NULL)
1549 {
1550 int order = Trans.OrderGrad(&el) + Trans.Order() + el.GetOrder();
1551 ir = &IntRules.Get(el.GetGeomType(), order);
1552 }
1553
1554 Q->Eval(Q_ir, Trans, *ir);
1555
1556 elmat = 0.0;
1557 for (int i = 0; i < ir->GetNPoints(); i++)
1558 {
1559 const IntegrationPoint &ip = ir->IntPoint(i);
1560 el.CalcDShape(ip, dshape);
1561 el.CalcShape(ip, shape);
1562
1563 Trans.SetIntPoint(&ip);
1564 CalcAdjugate(Trans.Jacobian(), adjJ);
1565 Q_ir.GetColumnReference(i, vec1);
1566 vec1 *= alpha * ip.weight;
1567
1568 adjJ.Mult(vec1, vec2);
1569 dshape.Mult(vec2, BdFidxT);
1570
1571 AddMultVWt(shape, BdFidxT, elmat);
1572 }
1573}
1574
1575
1577 const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat)
1578{
1579 int nd = el.GetDof();
1580 int dim = el.GetDim();
1581
1582 elmat.SetSize(nd);
1583 dshape.SetSize(nd,dim);
1584 adjJ.SetSize(dim);
1585 shape.SetSize(nd);
1586 grad.SetSize(nd,dim);
1587
1588 const IntegrationRule *ir = GetIntegrationRule(el, Trans);
1589 if (ir == NULL)
1590 {
1591 int order = Trans.OrderGrad(&el) + el.GetOrder();
1592 ir = &IntRules.Get(el.GetGeomType(), order);
1593 }
1594
1595 Q->Eval(Q_nodal, Trans, el.GetNodes()); // sets the size of Q_nodal
1596
1597 elmat = 0.0;
1598 for (int i = 0; i < ir->GetNPoints(); i++)
1599 {
1600 const IntegrationPoint &ip = ir->IntPoint(i);
1601 el.CalcDShape(ip, dshape);
1602 el.CalcShape(ip, shape);
1603
1604 Trans.SetIntPoint(&ip);
1605 CalcAdjugate(Trans.Jacobian(), adjJ);
1606
1607 Mult(dshape, adjJ, grad);
1608
1609 real_t w = alpha * ip.weight;
1610
1611 // elmat(k,l) += \sum_s w*shape(k)*Q_nodal(s,k)*grad(l,s)
1612 for (int k = 0; k < nd; k++)
1613 {
1614 real_t wsk = w*shape(k);
1615 for (int l = 0; l < nd; l++)
1616 {
1617 real_t a = 0.0;
1618 for (int s = 0; s < dim; s++)
1619 {
1620 a += Q_nodal(s,k)*grad(l,s);
1621 }
1622 elmat(k,l) += wsk*a;
1623 }
1624 }
1625 }
1626}
1627
1629 const FiniteElement &trial_fe, const FiniteElement &test_fe,
1630 const ElementTransformation &Trans)
1631{
1632 int order = Trans.OrderGrad(&trial_fe) + Trans.Order() + test_fe.GetOrder();
1633
1634 return IntRules.Get(trial_fe.GetGeomType(), order);
1635}
1636
1638 const FiniteElement &el, const ElementTransformation &Trans)
1639{
1640 return GetRule(el,el,Trans);
1641}
1642
1644( const FiniteElement &el, ElementTransformation &Trans,
1645 DenseMatrix &elmat )
1646{
1647 int nd = el.GetDof();
1648 int spaceDim = Trans.GetSpaceDim();
1649
1650 real_t norm;
1651
1652 // If vdim is not set, set it to the space dimension
1653 vdim = (vdim == -1) ? spaceDim : vdim;
1654
1655 elmat.SetSize(nd*vdim);
1656 shape.SetSize(nd);
1657 partelmat.SetSize(nd);
1658 if (VQ)
1659 {
1660 vec.SetSize(vdim);
1661 }
1662 else if (MQ)
1663 {
1664 mcoeff.SetSize(vdim);
1665 }
1666
1667
1668 const IntegrationRule *ir = GetIntegrationRule(el, Trans);
1669 if (ir == NULL)
1670 {
1671 int order = 2 * el.GetOrder() + Trans.OrderW() + Q_order;
1672
1673 if (el.Space() == FunctionSpace::rQk)
1674 {
1675 ir = &RefinedIntRules.Get(el.GetGeomType(), order);
1676 }
1677 else
1678 {
1679 ir = &IntRules.Get(el.GetGeomType(), order);
1680 }
1681 }
1682
1683 elmat = 0.0;
1684 for (int s = 0; s < ir->GetNPoints(); s++)
1685 {
1686 const IntegrationPoint &ip = ir->IntPoint(s);
1687 Trans.SetIntPoint (&ip);
1688 el.CalcPhysShape(Trans, shape);
1689
1690 norm = ip.weight * Trans.Weight();
1691
1692 MultVVt(shape, partelmat);
1693
1694 if (VQ)
1695 {
1696 VQ->Eval(vec, Trans, ip);
1697 for (int k = 0; k < vdim; k++)
1698 {
1699 elmat.AddMatrix(norm*vec(k), partelmat, nd*k, nd*k);
1700 }
1701 }
1702 else if (MQ)
1703 {
1704 MQ->Eval(mcoeff, Trans, ip);
1705 for (int i = 0; i < vdim; i++)
1706 for (int j = 0; j < vdim; j++)
1707 {
1708 elmat.AddMatrix(norm*mcoeff(i,j), partelmat, nd*i, nd*j);
1709 }
1710 }
1711 else
1712 {
1713 if (Q)
1714 {
1715 norm *= Q->Eval(Trans, ip);
1716 }
1717 partelmat *= norm;
1718 for (int k = 0; k < vdim; k++)
1719 {
1720 elmat.AddMatrix(partelmat, nd*k, nd*k);
1721 }
1722 }
1723 }
1724}
1725
1727 const FiniteElement &trial_fe, const FiniteElement &test_fe,
1728 ElementTransformation &Trans, DenseMatrix &elmat)
1729{
1730 int tr_nd = trial_fe.GetDof();
1731 int te_nd = test_fe.GetDof();
1732
1733 real_t norm;
1734
1735 // If vdim is not set, set it to the space dimension
1736 vdim = (vdim == -1) ? Trans.GetSpaceDim() : vdim;
1737
1738 elmat.SetSize(te_nd*vdim, tr_nd*vdim);
1739 shape.SetSize(tr_nd);
1740 te_shape.SetSize(te_nd);
1741 partelmat.SetSize(te_nd, tr_nd);
1742 if (VQ)
1743 {
1744 vec.SetSize(vdim);
1745 }
1746 else if (MQ)
1747 {
1748 mcoeff.SetSize(vdim);
1749 }
1750
1751
1752 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
1753 if (ir == NULL)
1754 {
1755 int order = (trial_fe.GetOrder() + test_fe.GetOrder() +
1756 Trans.OrderW() + Q_order);
1757
1758 if (trial_fe.Space() == FunctionSpace::rQk)
1759 {
1760 ir = &RefinedIntRules.Get(trial_fe.GetGeomType(), order);
1761 }
1762 else
1763 {
1764 ir = &IntRules.Get(trial_fe.GetGeomType(), order);
1765 }
1766 }
1767
1768 elmat = 0.0;
1769 for (int s = 0; s < ir->GetNPoints(); s++)
1770 {
1771 const IntegrationPoint &ip = ir->IntPoint(s);
1772 Trans.SetIntPoint(&ip);
1773 trial_fe.CalcPhysShape(Trans, shape);
1774 test_fe.CalcPhysShape(Trans, te_shape);
1775
1776 norm = ip.weight * Trans.Weight();
1777
1778 MultVWt(te_shape, shape, partelmat);
1779
1780 if (VQ)
1781 {
1782 VQ->Eval(vec, Trans, ip);
1783 for (int k = 0; k < vdim; k++)
1784 {
1785 elmat.AddMatrix(norm*vec(k), partelmat, te_nd*k, tr_nd*k);
1786 }
1787 }
1788 else if (MQ)
1789 {
1790 MQ->Eval(mcoeff, Trans, ip);
1791 for (int i = 0; i < vdim; i++)
1792 for (int j = 0; j < vdim; j++)
1793 {
1794 elmat.AddMatrix(norm*mcoeff(i,j), partelmat, te_nd*i, tr_nd*j);
1795 }
1796 }
1797 else
1798 {
1799 if (Q)
1800 {
1801 norm *= Q->Eval(Trans, ip);
1802 }
1803 partelmat *= norm;
1804 for (int k = 0; k < vdim; k++)
1805 {
1806 elmat.AddMatrix(partelmat, te_nd*k, tr_nd*k);
1807 }
1808 }
1809 }
1810}
1811
1813 const FiniteElement &trial_fe, const FiniteElement &test_fe,
1814 ElementTransformation &Trans, DenseMatrix &elmat)
1815{
1816 int trial_nd = trial_fe.GetDof(), test_nd = test_fe.GetDof(), i;
1817
1818#ifdef MFEM_THREAD_SAFE
1819 Vector divshape(trial_nd), shape(test_nd);
1820#else
1821 divshape.SetSize(trial_nd);
1822 shape.SetSize(test_nd);
1823#endif
1824
1825 elmat.SetSize(test_nd, trial_nd);
1826
1827 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
1828 if (ir == NULL)
1829 {
1830 int order = trial_fe.GetOrder() + test_fe.GetOrder() - 1; // <--
1831 ir = &IntRules.Get(trial_fe.GetGeomType(), order);
1832 }
1833
1834 elmat = 0.0;
1835 for (i = 0; i < ir->GetNPoints(); i++)
1836 {
1837 const IntegrationPoint &ip = ir->IntPoint(i);
1838 trial_fe.CalcDivShape(ip, divshape);
1839 Trans.SetIntPoint(&ip);
1840 test_fe.CalcPhysShape(Trans, shape);
1841 real_t w = ip.weight;
1842 if (Q)
1843 {
1844 Trans.SetIntPoint(&ip);
1845 w *= Q->Eval(Trans, ip);
1846 }
1847 shape *= w;
1848 AddMultVWt(shape, divshape, elmat);
1849 }
1850}
1851
1853 const FiniteElement &trial_fe, const FiniteElement &test_fe,
1854 ElementTransformation &Trans, DenseMatrix &elmat)
1855{
1856 int trial_nd = trial_fe.GetDof(), test_nd = test_fe.GetDof(), i;
1857 int dim = trial_fe.GetDim();
1858
1859 MFEM_ASSERT(test_fe.GetRangeType() == mfem::FiniteElement::SCALAR &&
1862 "Trial space must be H(Curl) and test space must be H_1");
1863
1864#ifdef MFEM_THREAD_SAFE
1865 DenseMatrix dshape(test_nd, dim);
1866 DenseMatrix dshapedxt(test_nd, dim);
1867 DenseMatrix vshape(trial_nd, dim);
1868 DenseMatrix invdfdx(dim);
1869#else
1870 dshape.SetSize(test_nd, dim);
1871 dshapedxt.SetSize(test_nd, dim);
1872 vshape.SetSize(trial_nd, dim);
1873 invdfdx.SetSize(dim);
1874#endif
1875
1876 elmat.SetSize(test_nd, trial_nd);
1877
1878 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
1879 if (ir == NULL)
1880 {
1881 // The integrand on the reference element is:
1882 // -( Q/det(J) ) u_hat^T adj(J) adj(J)^T grad_hat(v_hat).
1883 //
1884 // For Trans in (P_k)^d, v_hat in P_l, u_hat in ND_m, and dim=sdim=d>=1
1885 // - J_{ij} is in P_{k-1}, so adj(J)_{ij} is in P_{(d-1)*(k-1)}
1886 // - so adj(J)^T grad_hat(v_hat) is in (P_{(d-1)*(k-1)+(l-1)})^d
1887 // - u_hat is in (P_m)^d
1888 // - adj(J)^T u_hat is in (P_{(d-1)*(k-1)+m})^d
1889 // - and u_hat^T adj(J) adj(J)^T grad_hat(v_hat) is in P_n with
1890 // n = 2*(d-1)*(k-1)+(l-1)+m
1891 //
1892 // For Trans in (Q_k)^d, v_hat in Q_l, u_hat in ND_m, and dim=sdim=d>1
1893 // - J_{i*}, J's i-th row, is in ( Q_{k-1,k,k}, Q_{k,k-1,k}, Q_{k,k,k-1} )
1894 // - adj(J)_{*j} is in ( Q_{s,s-1,s-1}, Q_{s-1,s,s-1}, Q_{s-1,s-1,s} )
1895 // with s = (d-1)*k
1896 // - adj(J)^T grad_hat(v_hat) is in Q_{(d-1)*k+(l-1)}
1897 // - u_hat is in ( Q_{m-1,m,m}, Q_{m,m-1,m}, Q_{m,m,m-1} )
1898 // - adj(J)^T u_hat is in Q_{(d-1)*k+(m-1)}
1899 // - and u_hat^T adj(J) adj(J)^T grad_hat(v_hat) is in Q_n with
1900 // n = 2*(d-1)*k+(l-1)+(m-1)
1901 //
1902 // In the next formula we use the expressions for n with k=1, which means
1903 // that the term Q/det(J) is disregarded:
1904 int ir_order = (trial_fe.Space() == FunctionSpace::Pk) ?
1905 (trial_fe.GetOrder() + test_fe.GetOrder() - 1) :
1906 (trial_fe.GetOrder() + test_fe.GetOrder() + 2*(dim-2));
1907 ir = &IntRules.Get(trial_fe.GetGeomType(), ir_order);
1908 }
1909
1910 elmat = 0.0;
1911 for (i = 0; i < ir->GetNPoints(); i++)
1912 {
1913 const IntegrationPoint &ip = ir->IntPoint(i);
1914 test_fe.CalcDShape(ip, dshape);
1915
1916 Trans.SetIntPoint(&ip);
1917 CalcAdjugate(Trans.Jacobian(), invdfdx);
1918 Mult(dshape, invdfdx, dshapedxt);
1919
1920 trial_fe.CalcVShape(Trans, vshape);
1921
1922 real_t w = ip.weight;
1923
1924 if (Q)
1925 {
1926 w *= Q->Eval(Trans, ip);
1927 }
1928 dshapedxt *= -w;
1929
1930 AddMultABt(dshapedxt, vshape, elmat);
1931 }
1932}
1933
1935 const FiniteElement &trial_fe, const FiniteElement &test_fe,
1936 ElementTransformation &Trans, DenseMatrix &elmat)
1937{
1938 int trial_nd = trial_fe.GetDof(), test_nd = test_fe.GetDof(), i;
1939 int dim = trial_fe.GetDim();
1940 int dimc = (dim == 3) ? 3 : 1;
1941
1942 MFEM_ASSERT(trial_fe.GetMapType() == mfem::FiniteElement::H_CURL ||
1944 "At least one of the finite elements must be in H(Curl)");
1945
1946 int curl_nd, vec_nd;
1947 if ( trial_fe.GetMapType() == mfem::FiniteElement::H_CURL )
1948 {
1949 curl_nd = trial_nd;
1950 vec_nd = test_nd;
1951 }
1952 else
1953 {
1954 curl_nd = test_nd;
1955 vec_nd = trial_nd;
1956 }
1957
1958#ifdef MFEM_THREAD_SAFE
1959 DenseMatrix curlshapeTrial(curl_nd, dimc);
1960 DenseMatrix curlshapeTrial_dFT(curl_nd, dimc);
1961 DenseMatrix vshapeTest(vec_nd, dimc);
1962#else
1963 curlshapeTrial.SetSize(curl_nd, dimc);
1964 curlshapeTrial_dFT.SetSize(curl_nd, dimc);
1965 vshapeTest.SetSize(vec_nd, dimc);
1966#endif
1967 Vector shapeTest(vshapeTest.GetData(), vec_nd);
1968
1969 elmat.SetSize(test_nd, trial_nd);
1970
1971 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
1972 if (ir == NULL)
1973 {
1974 int order = trial_fe.GetOrder() + test_fe.GetOrder() - 1; // <--
1975 ir = &IntRules.Get(trial_fe.GetGeomType(), order);
1976 }
1977
1978 elmat = 0.0;
1979 for (i = 0; i < ir->GetNPoints(); i++)
1980 {
1981 const IntegrationPoint &ip = ir->IntPoint(i);
1982
1983 Trans.SetIntPoint(&ip);
1984 if (dim == 3)
1985 {
1986 if ( trial_fe.GetMapType() == mfem::FiniteElement::H_CURL )
1987 {
1988 trial_fe.CalcCurlShape(ip, curlshapeTrial);
1989 test_fe.CalcVShape(Trans, vshapeTest);
1990 }
1991 else
1992 {
1993 test_fe.CalcCurlShape(ip, curlshapeTrial);
1994 trial_fe.CalcVShape(Trans, vshapeTest);
1995 }
1996 MultABt(curlshapeTrial, Trans.Jacobian(), curlshapeTrial_dFT);
1997 }
1998 else
1999 {
2000 if ( trial_fe.GetMapType() == mfem::FiniteElement::H_CURL )
2001 {
2002 trial_fe.CalcCurlShape(ip, curlshapeTrial_dFT);
2003 test_fe.CalcPhysShape(Trans, shapeTest);
2004 }
2005 else
2006 {
2007 test_fe.CalcCurlShape(ip, curlshapeTrial_dFT);
2008 trial_fe.CalcPhysShape(Trans, shapeTest);
2009 }
2010 }
2011
2012 real_t w = ip.weight;
2013
2014 if (Q)
2015 {
2016 w *= Q->Eval(Trans, ip);
2017 }
2018 // Note: shapeTest points to the same data as vshapeTest
2019 vshapeTest *= w;
2020 if ( trial_fe.GetMapType() == mfem::FiniteElement::H_CURL )
2021 {
2022 AddMultABt(vshapeTest, curlshapeTrial_dFT, elmat);
2023 }
2024 else
2025 {
2026 AddMultABt(curlshapeTrial_dFT, vshapeTest, elmat);
2027 }
2028 }
2029}
2030
2032 const FiniteElement &el, ElementTransformation &Tr,
2033 DenseMatrix &elmat)
2034{
2035 int nd = el.GetDof();
2036 real_t w;
2037
2038#ifdef MFEM_THREAD_SAFE
2039 Vector shape;
2040#endif
2041 elmat.SetSize(nd);
2042 shape.SetSize(nd);
2043
2044 const IntegrationRule *ir = IntRule;
2045 if (ir == NULL)
2046 {
2047 int intorder = 2*el.GetOrder() + Tr.OrderW(); // <----------
2048 ir = &IntRules.Get(el.GetGeomType(), intorder);
2049 }
2050
2051 elmat = 0.0;
2052 for (int i = 0; i < ir->GetNPoints(); i++)
2053 {
2054 const IntegrationPoint &ip = ir->IntPoint(i);
2055 el.CalcShape(ip, shape);
2056
2057 Tr.SetIntPoint (&ip);
2058 w = ip.weight / Tr.Weight();
2059
2060 if (Q)
2061 {
2062 w *= Q->Eval(Tr, ip);
2063 }
2064
2065 AddMult_a_VVt(w, shape, elmat);
2066 }
2067}
2068
2070 const FiniteElement &trial_fe,
2071 const FiniteElement &test_fe,
2073 DenseMatrix &elmat)
2074{
2075 int tr_nd = trial_fe.GetDof();
2076 int te_nd = test_fe.GetDof();
2077 real_t w;
2078
2079#ifdef MFEM_THREAD_SAFE
2080 Vector shape, te_shape;
2081#endif
2082 elmat.SetSize(te_nd, tr_nd);
2083 shape.SetSize(tr_nd);
2084 te_shape.SetSize(te_nd);
2085
2086 const IntegrationRule *ir = IntRule;
2087 if (ir == NULL)
2088 {
2089 int order = trial_fe.GetOrder() + test_fe.GetOrder() + Tr.OrderW();
2090
2091 ir = &IntRules.Get(trial_fe.GetGeomType(), order);
2092 }
2093
2094 elmat = 0.0;
2095 for (int i = 0; i < ir->GetNPoints(); i++)
2096 {
2097 const IntegrationPoint &ip = ir->IntPoint(i);
2098 trial_fe.CalcShape(ip, shape);
2099 test_fe.CalcShape(ip, te_shape);
2100
2101 Tr.SetIntPoint (&ip);
2102 w = ip.weight / Tr.Weight();
2103
2104 if (Q)
2105 {
2106 w *= Q->Eval(Tr, ip);
2107 }
2108
2109 te_shape *= w;
2110 AddMultVWt(te_shape, shape, elmat);
2111 }
2112}
2113
2115 const FiniteElement &trial_fe,
2116 const FiniteElement &test_fe,
2117 ElementTransformation &Trans,
2118 DenseMatrix &elmat)
2119{
2120 int dim = trial_fe.GetDim();
2121 int trial_nd = trial_fe.GetDof();
2122 int test_nd = test_fe.GetDof();
2123 int spaceDim = Trans.GetSpaceDim();
2124
2125 int i, l;
2126 real_t det;
2127
2128 elmat.SetSize (test_nd,trial_nd);
2129 dshape.SetSize (trial_nd,dim);
2130 dshapedxt.SetSize(trial_nd, spaceDim);
2131 dshapedxi.SetSize(trial_nd);
2132 invdfdx.SetSize(dim, spaceDim);
2133 shape.SetSize (test_nd);
2134
2135 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
2136 if (ir == NULL)
2137 {
2138 int order;
2139 if (trial_fe.Space() == FunctionSpace::Pk)
2140 {
2141 order = trial_fe.GetOrder() + test_fe.GetOrder() - 1;
2142 }
2143 else
2144 {
2145 order = trial_fe.GetOrder() + test_fe.GetOrder() + dim;
2146 }
2147
2148 if (trial_fe.Space() == FunctionSpace::rQk)
2149 {
2150 ir = &RefinedIntRules.Get(trial_fe.GetGeomType(), order);
2151 }
2152 else
2153 {
2154 ir = &IntRules.Get(trial_fe.GetGeomType(), order);
2155 }
2156 }
2157
2158 elmat = 0.0;
2159 for (i = 0; i < ir->GetNPoints(); i++)
2160 {
2161 const IntegrationPoint &ip = ir->IntPoint(i);
2162
2163 trial_fe.CalcDShape(ip, dshape);
2164
2165 Trans.SetIntPoint (&ip);
2166 CalcInverse (Trans.Jacobian(), invdfdx);
2167 det = Trans.Weight();
2168 Mult (dshape, invdfdx, dshapedxt);
2169
2170 test_fe.CalcPhysShape(Trans, shape);
2171
2172 for (l = 0; l < trial_nd; l++)
2173 {
2174 dshapedxi(l) = dshapedxt(l,xi);
2175 }
2176
2177 shape *= Q->Eval(Trans,ip) * det * ip.weight;
2178 AddMultVWt (shape, dshapedxi, elmat);
2179 }
2180}
2181
2183( const FiniteElement &el, ElementTransformation &Trans,
2184 DenseMatrix &elmat )
2185{
2186 int nd = el.GetDof();
2187 dim = el.GetDim();
2188 int dimc = el.GetCurlDim();
2189 real_t w;
2190
2191#ifdef MFEM_THREAD_SAFE
2192 Vector D;
2193 DenseMatrix curlshape(nd,dimc), curlshape_dFt(nd,dimc), M;
2194#else
2195 curlshape.SetSize(nd,dimc);
2196 curlshape_dFt.SetSize(nd,dimc);
2197#endif
2198 elmat.SetSize(nd);
2199 if (MQ) { M.SetSize(dimc); }
2200 if (DQ) { D.SetSize(dimc); }
2201
2202 const IntegrationRule *ir = GetIntegrationRule(el, Trans);
2203 if (ir == NULL)
2204 {
2205 int order;
2206 if (el.Space() == FunctionSpace::Pk)
2207 {
2208 order = 2*el.GetOrder() - 2;
2209 }
2210 else
2211 {
2212 order = 2*el.GetOrder();
2213 }
2214
2215 ir = &IntRules.Get(el.GetGeomType(), order);
2216 }
2217
2218 elmat = 0.0;
2219 for (int i = 0; i < ir->GetNPoints(); i++)
2220 {
2221 const IntegrationPoint &ip = ir->IntPoint(i);
2222
2223 Trans.SetIntPoint (&ip);
2224
2225 w = ip.weight * Trans.Weight();
2226 el.CalcPhysCurlShape(Trans, curlshape_dFt);
2227
2228 if (MQ)
2229 {
2230 MQ->Eval(M, Trans, ip);
2231 M *= w;
2232 Mult(curlshape_dFt, M, curlshape);
2233 AddMultABt(curlshape, curlshape_dFt, elmat);
2234 }
2235 else if (DQ)
2236 {
2237 DQ->Eval(D, Trans, ip);
2238 D *= w;
2239 AddMultADAt(curlshape_dFt, D, elmat);
2240 }
2241 else if (Q)
2242 {
2243 w *= Q->Eval(Trans, ip);
2244 AddMult_a_AAt(w, curlshape_dFt, elmat);
2245 }
2246 else
2247 {
2248 AddMult_a_AAt(w, curlshape_dFt, elmat);
2249 }
2250 }
2251}
2252
2254 const FiniteElement &test_fe,
2255 ElementTransformation &Trans,
2256 DenseMatrix &elmat)
2257{
2258 int tr_nd = trial_fe.GetDof();
2259 int te_nd = test_fe.GetDof();
2260 dim = trial_fe.GetDim();
2261 int dimc = trial_fe.GetCurlDim();
2262 real_t w;
2263
2264#ifdef MFEM_THREAD_SAFE
2265 Vector D;
2266 DenseMatrix curlshape(tr_nd,dimc), curlshape_dFt(tr_nd,dimc), M;
2267 DenseMatrix te_curlshape(te_nd,dimc), te_curlshape_dFt(te_nd,dimc);
2268#else
2269 curlshape.SetSize(tr_nd,dimc);
2270 curlshape_dFt.SetSize(tr_nd,dimc);
2271 te_curlshape.SetSize(te_nd,dimc);
2272 te_curlshape_dFt.SetSize(te_nd,dimc);
2273#endif
2274 elmat.SetSize(te_nd, tr_nd);
2275
2276 if (MQ) { M.SetSize(dimc); }
2277 if (DQ) { D.SetSize(dimc); }
2278
2279
2280 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
2281 if (ir == NULL)
2282 {
2283 int order;
2284 if (trial_fe.Space() == FunctionSpace::Pk)
2285 {
2286 order = test_fe.GetOrder() + trial_fe.GetOrder() - 2;
2287 }
2288 else
2289 {
2290 order = test_fe.GetOrder() + trial_fe.GetOrder() + trial_fe.GetDim() - 1;
2291 }
2292 ir = &IntRules.Get(trial_fe.GetGeomType(), order);
2293 }
2294
2295 elmat = 0.0;
2296 for (int i = 0; i < ir->GetNPoints(); i++)
2297 {
2298 const IntegrationPoint &ip = ir->IntPoint(i);
2299
2300 Trans.SetIntPoint(&ip);
2301
2302 w = ip.weight * Trans.Weight();
2303 trial_fe.CalcPhysCurlShape(Trans, curlshape_dFt);
2304 test_fe.CalcPhysCurlShape(Trans, te_curlshape_dFt);
2305
2306 if (MQ)
2307 {
2308 MQ->Eval(M, Trans, ip);
2309 M *= w;
2310 Mult(te_curlshape_dFt, M, te_curlshape);
2311 AddMultABt(te_curlshape, curlshape_dFt, elmat);
2312 }
2313 else if (DQ)
2314 {
2315 DQ->Eval(D, Trans, ip);
2316 D *= w;
2317 AddMultADBt(te_curlshape_dFt,D,curlshape_dFt,elmat);
2318 }
2319 else
2320 {
2321 if (Q)
2322 {
2323 w *= Q->Eval(Trans, ip);
2324 }
2325 curlshape_dFt *= w;
2326 AddMultABt(te_curlshape_dFt, curlshape_dFt, elmat);
2327 }
2328 }
2329}
2330
2331void CurlCurlIntegrator
2332::ComputeElementFlux(const FiniteElement &el, ElementTransformation &Trans,
2333 Vector &u, const FiniteElement &fluxelem, Vector &flux,
2334 bool with_coef, const IntegrationRule *ir)
2335{
2336#ifdef MFEM_THREAD_SAFE
2337 DenseMatrix projcurl;
2338#endif
2339
2340 MFEM_VERIFY(ir == NULL, "Integration rule (ir) must be NULL")
2341
2342 fluxelem.ProjectCurl(el, Trans, projcurl);
2343
2344 flux.SetSize(projcurl.Height());
2345 projcurl.Mult(u, flux);
2346
2347 // TODO: Q, wcoef?
2348}
2349
2351 ElementTransformation &Trans,
2352 Vector &flux, Vector *d_energy)
2353{
2354 int nd = fluxelem.GetDof();
2355 dim = fluxelem.GetDim();
2356
2357#ifdef MFEM_THREAD_SAFE
2358 DenseMatrix vshape;
2359#endif
2360 vshape.SetSize(nd, dim);
2361 pointflux.SetSize(dim);
2362 if (d_energy) { vec.SetSize(dim); }
2363
2364 int order = 2 * fluxelem.GetOrder(); // <--
2365 const IntegrationRule &ir = IntRules.Get(fluxelem.GetGeomType(), order);
2366
2367 real_t energy = 0.0;
2368 if (d_energy) { *d_energy = 0.0; }
2369
2370 Vector* pfluxes = NULL;
2371 if (d_energy)
2372 {
2373 pfluxes = new Vector[ir.GetNPoints()];
2374 }
2375
2376 for (int i = 0; i < ir.GetNPoints(); i++)
2377 {
2378 const IntegrationPoint &ip = ir.IntPoint(i);
2379 Trans.SetIntPoint(&ip);
2380
2381 fluxelem.CalcVShape(Trans, vshape);
2382 // fluxelem.CalcVShape(ip, vshape);
2383 vshape.MultTranspose(flux, pointflux);
2384
2385 real_t w = Trans.Weight() * ip.weight;
2386
2387 real_t e = w * (pointflux * pointflux);
2388
2389 if (Q)
2390 {
2391 // TODO
2392 }
2393
2394 energy += e;
2395
2396#if ANISO_EXPERIMENTAL
2397 if (d_energy)
2398 {
2399 pfluxes[i].SetSize(dim);
2400 Trans.Jacobian().MultTranspose(pointflux, pfluxes[i]);
2401
2402 /*
2403 DenseMatrix Jadj(dim, dim);
2404 CalcAdjugate(Trans.Jacobian(), Jadj);
2405 pfluxes[i].SetSize(dim);
2406 Jadj.Mult(pointflux, pfluxes[i]);
2407 */
2408
2409 // pfluxes[i] = pointflux;
2410 }
2411#endif
2412 }
2413
2414 if (d_energy)
2415 {
2416#if ANISO_EXPERIMENTAL
2417 *d_energy = 0.0;
2418 Vector tmp;
2419
2420 int n = (int) round(pow(ir.GetNPoints(), 1.0/3.0));
2421 MFEM_ASSERT(n*n*n == ir.GetNPoints(), "");
2422
2423 // hack: get total variation of 'pointflux' in the x,y,z directions
2424 for (int k = 0; k < n; k++)
2425 for (int l = 0; l < n; l++)
2426 for (int m = 0; m < n; m++)
2427 {
2428 Vector &vec = pfluxes[(k*n + l)*n + m];
2429 if (m > 0)
2430 {
2431 tmp = vec; tmp -= pfluxes[(k*n + l)*n + (m-1)];
2432 (*d_energy)[0] += (tmp * tmp);
2433 }
2434 if (l > 0)
2435 {
2436 tmp = vec; tmp -= pfluxes[(k*n + (l-1))*n + m];
2437 (*d_energy)[1] += (tmp * tmp);
2438 }
2439 if (k > 0)
2440 {
2441 tmp = vec; tmp -= pfluxes[((k-1)*n + l)*n + m];
2442 (*d_energy)[2] += (tmp * tmp);
2443 }
2444 }
2445#else
2446 *d_energy = 1.0;
2447#endif
2448
2449 delete [] pfluxes;
2450 }
2451
2452 return energy;
2453}
2454
2456 const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat)
2457{
2458 int dim = el.GetDim();
2459 int dof = el.GetDof();
2460 int cld = (dim*(dim-1))/2;
2461
2462#ifdef MFEM_THREAD_SAFE
2463 DenseMatrix dshape_hat(dof, dim), dshape(dof, dim);
2464 DenseMatrix curlshape(dim*dof, cld), Jadj(dim);
2465#else
2466 dshape_hat.SetSize(dof, dim);
2467 dshape.SetSize(dof, dim);
2468 curlshape.SetSize(dim*dof, cld);
2469 Jadj.SetSize(dim);
2470#endif
2471
2472
2473 const IntegrationRule *ir = GetIntegrationRule(el, Trans);
2474 if (ir == NULL)
2475 {
2476 // use the same integration rule as diffusion
2477 int order = 2 * Trans.OrderGrad(&el);
2478 ir = &IntRules.Get(el.GetGeomType(), order);
2479 }
2480
2481 elmat.SetSize(dof*dim);
2482 elmat = 0.0;
2483 for (int i = 0; i < ir->GetNPoints(); i++)
2484 {
2485 const IntegrationPoint &ip = ir->IntPoint(i);
2486 el.CalcDShape(ip, dshape_hat);
2487
2488 Trans.SetIntPoint(&ip);
2489 CalcAdjugate(Trans.Jacobian(), Jadj);
2490 real_t w = ip.weight / Trans.Weight();
2491
2492 Mult(dshape_hat, Jadj, dshape);
2493 dshape.GradToCurl(curlshape);
2494
2495 if (Q)
2496 {
2497 w *= Q->Eval(Trans, ip);
2498 }
2499
2500 AddMult_a_AAt(w, curlshape, elmat);
2501 }
2502}
2503
2505 const FiniteElement &el, ElementTransformation &Tr, const Vector &elfun)
2506{
2507 int dim = el.GetDim();
2508 int dof = el.GetDof();
2509
2510#ifdef MFEM_THREAD_SAFE
2511 DenseMatrix dshape_hat(dof, dim), Jadj(dim), grad_hat(dim), grad(dim);
2512#else
2513 dshape_hat.SetSize(dof, dim);
2514
2515 Jadj.SetSize(dim);
2516 grad_hat.SetSize(dim);
2517 grad.SetSize(dim);
2518#endif
2519 DenseMatrix elfun_mat(elfun.GetData(), dof, dim);
2520
2521
2522 const IntegrationRule *ir = GetIntegrationRule(el, Tr);
2523 if (ir == NULL)
2524 {
2525 // use the same integration rule as diffusion
2526 int order = 2 * Tr.OrderGrad(&el);
2527 ir = &IntRules.Get(el.GetGeomType(), order);
2528 }
2529
2530 real_t energy = 0.;
2531 for (int i = 0; i < ir->GetNPoints(); i++)
2532 {
2533 const IntegrationPoint &ip = ir->IntPoint(i);
2534 el.CalcDShape(ip, dshape_hat);
2535
2536 MultAtB(elfun_mat, dshape_hat, grad_hat);
2537
2538 Tr.SetIntPoint(&ip);
2539 CalcAdjugate(Tr.Jacobian(), Jadj);
2540 real_t w = ip.weight / Tr.Weight();
2541
2542 Mult(grad_hat, Jadj, grad);
2543
2544 if (dim == 2)
2545 {
2546 real_t curl = grad(0,1) - grad(1,0);
2547 w *= curl * curl;
2548 }
2549 else
2550 {
2551 real_t curl_x = grad(2,1) - grad(1,2);
2552 real_t curl_y = grad(0,2) - grad(2,0);
2553 real_t curl_z = grad(1,0) - grad(0,1);
2554 w *= curl_x * curl_x + curl_y * curl_y + curl_z * curl_z;
2555 }
2556
2557 if (Q)
2558 {
2559 w *= Q->Eval(Tr, ip);
2560 }
2561
2562 energy += w;
2563 }
2564
2565 elfun_mat.ClearExternalData();
2566
2567 return 0.5 * energy;
2568}
2569
2571 const FiniteElement &trial_fe, const FiniteElement &test_fe,
2572 ElementTransformation &Trans, DenseMatrix &elmat)
2573{
2574 int dim = trial_fe.GetDim();
2575 int trial_dof = trial_fe.GetDof();
2576 int test_dof = test_fe.GetDof();
2577 int dimc = (dim == 3) ? 3 : 1;
2578
2579 MFEM_VERIFY(trial_fe.GetMapType() == mfem::FiniteElement::H_CURL ||
2580 (dim == 2 && trial_fe.GetMapType() == mfem::FiniteElement::VALUE),
2581 "Trial finite element must be either 2D/3D H(Curl) or 2D H1");
2582 MFEM_VERIFY(test_fe.GetMapType() == mfem::FiniteElement::VALUE ||
2584 "Test finite element must be in H1/L2");
2585
2586 bool spaceH1 = (trial_fe.GetMapType() == mfem::FiniteElement::VALUE);
2587
2588 if (spaceH1)
2589 {
2590 dshape.SetSize(trial_dof,dim);
2591 curlshape.SetSize(trial_dof,dim);
2592 dimc = dim;
2593 }
2594 else
2595 {
2596 curlshape.SetSize(trial_dof,dimc);
2597 elmat_comp.SetSize(test_dof, trial_dof);
2598 }
2599 elmat.SetSize(dimc * test_dof, trial_dof);
2600 shape.SetSize(test_dof);
2601 elmat = 0.0;
2602
2603 real_t c;
2604 Vector d_col;
2605
2606 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
2607 if (ir == NULL)
2608 {
2609 int order = trial_fe.GetOrder() + test_fe.GetOrder() + Trans.OrderJ();
2610 ir = &IntRules.Get(trial_fe.GetGeomType(), order);
2611 }
2612
2613 for (int i = 0; i < ir->GetNPoints(); i++)
2614 {
2615 const IntegrationPoint &ip = ir->IntPoint(i);
2616 Trans.SetIntPoint(&ip);
2617 if (spaceH1)
2618 {
2619 trial_fe.CalcPhysDShape(Trans, dshape);
2620 dshape.GradToVectorCurl2D(curlshape);
2621 }
2622 else
2623 {
2624 trial_fe.CalcPhysCurlShape(Trans, curlshape);
2625 }
2626 test_fe.CalcPhysShape(Trans, shape);
2627 c = ip.weight*Trans.Weight();
2628 if (Q)
2629 {
2630 c *= Q->Eval(Trans, ip);
2631 }
2632 shape *= c;
2633
2634 for (int d = 0; d < dimc; ++d)
2635 {
2636 real_t * curldata = &(curlshape.GetData())[d*trial_dof];
2637 for (int jj = 0; jj < trial_dof; ++jj)
2638 {
2639 for (int ii = 0; ii < test_dof; ++ii)
2640 {
2641 elmat(d * test_dof + ii, jj) += shape(ii) * curldata[jj];
2642 }
2643 }
2644 }
2645 }
2646}
2647
2648
2650 const FiniteElement &el,
2651 ElementTransformation &Trans,
2652 DenseMatrix &elmat)
2653{
2654 int dof = el.GetDof();
2655 int spaceDim = Trans.GetSpaceDim();
2656 int vdim = std::max(spaceDim, el.GetRangeDim());
2657
2658 real_t w;
2659
2660#ifdef MFEM_THREAD_SAFE
2661 Vector D(DQ ? DQ->GetVDim() : 0);
2662 DenseMatrix trial_vshape(dof, vdim);
2663 DenseMatrix K(MQ ? MQ->GetVDim() : 0, MQ ? MQ->GetVDim() : 0);
2664#else
2665 trial_vshape.SetSize(dof, vdim);
2666 D.SetSize(DQ ? DQ->GetVDim() : 0);
2667 K.SetSize(MQ ? MQ->GetVDim() : 0, MQ ? MQ->GetVDim() : 0);
2668#endif
2669 DenseMatrix tmp(trial_vshape.Height(), K.Width());
2670
2671 elmat.SetSize(dof);
2672 elmat = 0.0;
2673
2674 const IntegrationRule *ir = GetIntegrationRule(el, Trans);
2675 if (ir == NULL)
2676 {
2677 // int order = 2 * el.GetOrder();
2678 int order = Trans.OrderW() + 2 * el.GetOrder();
2679 ir = &IntRules.Get(el.GetGeomType(), order);
2680 }
2681
2682 for (int i = 0; i < ir->GetNPoints(); i++)
2683 {
2684 const IntegrationPoint &ip = ir->IntPoint(i);
2685
2686 Trans.SetIntPoint (&ip);
2687
2688 el.CalcVShape(Trans, trial_vshape);
2689
2690 w = ip.weight * Trans.Weight();
2691 if (MQ)
2692 {
2693 MQ->Eval(K, Trans, ip);
2694 K *= w;
2695 Mult(trial_vshape,K,tmp);
2696 AddMultABt(tmp,trial_vshape,elmat);
2697 }
2698 else if (DQ)
2699 {
2700 DQ->Eval(D, Trans, ip);
2701 D *= w;
2702 AddMultADAt(trial_vshape, D, elmat);
2703 }
2704 else
2705 {
2706 if (Q)
2707 {
2708 w *= Q -> Eval (Trans, ip);
2709 }
2710 AddMult_a_AAt (w, trial_vshape, elmat);
2711 }
2712 }
2713}
2714
2716 const FiniteElement &trial_fe, const FiniteElement &test_fe,
2717 ElementTransformation &Trans, DenseMatrix &elmat)
2718{
2719 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
2720
2721 if (test_fe.GetRangeType() == FiniteElement::SCALAR
2722 && trial_fe.GetRangeType() == FiniteElement::VECTOR)
2723 {
2724 // assume test_fe is scalar FE and trial_fe is vector FE
2725 int spaceDim = Trans.GetSpaceDim();
2726 int vdim = std::max(spaceDim, trial_fe.GetRangeDim());
2727 int trial_dof = trial_fe.GetDof();
2728 int test_dof = test_fe.GetDof();
2729 real_t w;
2730
2731#ifdef MFEM_THREAD_SAFE
2732 DenseMatrix trial_vshape(trial_dof, spaceDim);
2733 Vector shape(test_dof);
2734 Vector D(DQ ? DQ->GetVDim() : 0);
2735 DenseMatrix K(MQ ? MQ->GetVDim() : 0, MQ ? MQ->GetVDim() : 0);
2736#else
2737 trial_vshape.SetSize(trial_dof, spaceDim);
2738 shape.SetSize(test_dof);
2739 D.SetSize(DQ ? DQ->GetVDim() : 0);
2740 K.SetSize(MQ ? MQ->GetVDim() : 0, MQ ? MQ->GetVDim() : 0);
2741#endif
2742
2743 elmat.SetSize(vdim*test_dof, trial_dof);
2744 if (ir == NULL)
2745 {
2746 int order = (Trans.OrderW() + test_fe.GetOrder() + trial_fe.GetOrder());
2747 ir = &IntRules.Get(test_fe.GetGeomType(), order);
2748 }
2749
2750 elmat = 0.0;
2751 for (int i = 0; i < ir->GetNPoints(); i++)
2752 {
2753 const IntegrationPoint &ip = ir->IntPoint(i);
2754
2755 Trans.SetIntPoint (&ip);
2756
2757 trial_fe.CalcVShape(Trans, trial_vshape);
2758 test_fe.CalcPhysShape(Trans, shape);
2759
2760 w = ip.weight * Trans.Weight();
2761 if (DQ)
2762 {
2763 DQ->Eval(D, Trans, ip);
2764 D *= w;
2765 for (int d = 0; d < vdim; d++)
2766 {
2767 for (int j = 0; j < test_dof; j++)
2768 {
2769 for (int k = 0; k < trial_dof; k++)
2770 {
2771 elmat(d * test_dof + j, k) +=
2772 shape(j) * D(d) * trial_vshape(k, d);
2773 }
2774 }
2775 }
2776 }
2777 else if (MQ)
2778 {
2779 MQ->Eval(K, Trans, ip);
2780 K *= w;
2781 for (int d = 0; d < vdim; d++)
2782 {
2783 for (int j = 0; j < test_dof; j++)
2784 {
2785 for (int k = 0; k < trial_dof; k++)
2786 {
2787 real_t Kv = 0.0;
2788 for (int vd = 0; vd < spaceDim; vd++)
2789 {
2790 Kv += K(d, vd) * trial_vshape(k, vd);
2791 }
2792 elmat(d * test_dof + j, k) += shape(j) * Kv;
2793 }
2794 }
2795 }
2796 }
2797 else
2798 {
2799 if (Q)
2800 {
2801 w *= Q->Eval(Trans, ip);
2802 }
2803 for (int d = 0; d < vdim; d++)
2804 {
2805 for (int j = 0; j < test_dof; j++)
2806 {
2807 for (int k = 0; k < trial_dof; k++)
2808 {
2809 elmat(d * test_dof + j, k) +=
2810 w * shape(j) * trial_vshape(k, d);
2811 }
2812 }
2813 }
2814 }
2815 }
2816 }
2817 else if (test_fe.GetRangeType() == FiniteElement::VECTOR
2818 && trial_fe.GetRangeType() == FiniteElement::VECTOR)
2819 {
2820 // assume both test_fe and trial_fe are vector FE
2821 int spaceDim = Trans.GetSpaceDim();
2822 int trial_vdim = std::max(spaceDim, trial_fe.GetRangeDim());
2823 int test_vdim = std::max(spaceDim, test_fe.GetRangeDim());
2824 int trial_dof = trial_fe.GetDof();
2825 int test_dof = test_fe.GetDof();
2826 real_t w;
2827
2828#ifdef MFEM_THREAD_SAFE
2829 DenseMatrix trial_vshape(trial_dof,trial_vdim);
2830 DenseMatrix test_vshape(test_dof,test_vdim);
2831 Vector D(DQ ? DQ->GetVDim() : 0);
2832 DenseMatrix K(MQ ? MQ->GetVDim() : 0, MQ ? MQ->GetVDim() : 0);
2833#else
2834 trial_vshape.SetSize(trial_dof,trial_vdim);
2835 test_vshape.SetSize(test_dof,test_vdim);
2836 D.SetSize(DQ ? DQ->GetVDim() : 0);
2837 K.SetSize(MQ ? MQ->GetVDim() : 0, MQ ? MQ->GetVDim() : 0);
2838#endif
2839 DenseMatrix tmp(test_vshape.Height(), K.Width());
2840
2841 elmat.SetSize (test_dof, trial_dof);
2842
2843 if (ir == NULL)
2844 {
2845 int order = (Trans.OrderW() + test_fe.GetOrder() + trial_fe.GetOrder());
2846 ir = &IntRules.Get(test_fe.GetGeomType(), order);
2847 }
2848
2849 elmat = 0.0;
2850 for (int i = 0; i < ir->GetNPoints(); i++)
2851 {
2852 const IntegrationPoint &ip = ir->IntPoint(i);
2853
2854 Trans.SetIntPoint (&ip);
2855
2856 trial_fe.CalcVShape(Trans, trial_vshape);
2857 test_fe.CalcVShape(Trans, test_vshape);
2858
2859 w = ip.weight * Trans.Weight();
2860 if (MQ)
2861 {
2862 MQ->Eval(K, Trans, ip);
2863 K *= w;
2864 Mult(test_vshape,K,tmp);
2865 AddMultABt(tmp,trial_vshape,elmat);
2866 }
2867 else if (DQ)
2868 {
2869 DQ->Eval(D, Trans, ip);
2870 D *= w;
2871 AddMultADBt(test_vshape,D,trial_vshape,elmat);
2872 }
2873 else
2874 {
2875 if (Q)
2876 {
2877 w *= Q -> Eval (Trans, ip);
2878 }
2879 AddMult_a_ABt(w,test_vshape,trial_vshape,elmat);
2880 }
2881 }
2882 }
2883 else
2884 {
2885 MFEM_ABORT("VectorFEMassIntegrator::AssembleElementMatrix2(...)\n"
2886 " is not implemented for given trial and test bases.");
2887 }
2888}
2889
2891 const FiniteElement &trial_fe,
2892 const FiniteElement &test_fe,
2893 ElementTransformation &Trans,
2894 DenseMatrix &elmat)
2895{
2896 dim = trial_fe.GetDim();
2897 sdim = Trans.GetSpaceDim();
2898 int trial_dof = trial_fe.GetDof();
2899 int test_dof = test_fe.GetDof();
2900 real_t c;
2901
2902 dshape.SetSize (trial_dof, dim);
2903 gshape.SetSize (trial_dof, sdim);
2904 Jadj.SetSize (dim, sdim);
2905 divshape.SetSize (sdim*trial_dof);
2906 shape.SetSize (test_dof);
2907
2908 elmat.SetSize (test_dof, sdim*trial_dof);
2909
2910 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
2911
2912 elmat = 0.0;
2913
2914 for (int i = 0; i < ir -> GetNPoints(); i++)
2915 {
2916 const IntegrationPoint &ip = ir->IntPoint(i);
2917 Trans.SetIntPoint (&ip);
2918
2919 trial_fe.CalcDShape (ip, dshape);
2920 test_fe.CalcPhysShape (Trans, shape);
2921
2922 // AdjugateJacobian = / adj(J), if J is square
2923 // \ adj(J^t.J).J^t, otherwise
2924 CalcAdjugate(Trans.Jacobian(), Jadj);
2925 Mult (dshape, Jadj, gshape);
2926
2927 gshape.GradToDiv (divshape);
2928
2929 c = ip.weight;
2930 if (dim != sdim) { c /= Trans.Weight(); }
2931 if (Q)
2932 {
2933 c *= Q -> Eval (Trans, ip);
2934 }
2935
2936 // elmat += c * shape * divshape ^ t
2937 shape *= c;
2938 AddMultVWt (shape, divshape, elmat);
2939 }
2940}
2941
2943 const FiniteElement &trial_fe,
2944 const FiniteElement &test_fe,
2945 const ElementTransformation &Trans)
2946{
2947 int order = Trans.OrderGrad(&trial_fe) + test_fe.GetOrder() + Trans.OrderJ();
2948 return IntRules.Get(trial_fe.GetGeomType(), order);
2949}
2950
2951
2953 const FiniteElement &el,
2954 ElementTransformation &Trans,
2955 DenseMatrix &elmat)
2956{
2957 int dof = el.GetDof();
2958 real_t c;
2959
2960#ifdef MFEM_THREAD_SAFE
2961 Vector divshape(dof);
2962#else
2963 divshape.SetSize(dof);
2964#endif
2965 elmat.SetSize(dof);
2966
2967 const IntegrationRule *ir = GetIntegrationRule(el, Trans);
2968 if (ir == NULL)
2969 {
2970 int order = 2 * el.GetOrder() - 2; // <--- OK for RTk
2971 if (el.Space() == FunctionSpace::Uk)
2972 {
2973 order += 2;
2974 }
2975
2976 ir = &IntRules.Get(el.GetGeomType(), order);
2977 }
2978
2979 elmat = 0.0;
2980
2981 for (int i = 0; i < ir -> GetNPoints(); i++)
2982 {
2983 const IntegrationPoint &ip = ir->IntPoint(i);
2984
2985 el.CalcDivShape (ip, divshape);
2986
2987 Trans.SetIntPoint (&ip);
2988 c = ip.weight / Trans.Weight();
2989
2990 if (Q)
2991 {
2992 c *= Q -> Eval (Trans, ip);
2993 }
2994
2995 // elmat += c * divshape * divshape ^ t
2996 AddMult_a_VVt (c, divshape, elmat);
2997 }
2998}
2999
3001 const FiniteElement &trial_fe,
3002 const FiniteElement &test_fe,
3003 ElementTransformation &Trans,
3004 DenseMatrix &elmat)
3005{
3006 int tr_nd = trial_fe.GetDof();
3007 int te_nd = test_fe.GetDof();
3008 real_t c;
3009
3010#ifdef MFEM_THREAD_SAFE
3011 Vector divshape(tr_nd);
3012 Vector te_divshape(te_nd);
3013#else
3014 divshape.SetSize(tr_nd);
3015 te_divshape.SetSize(te_nd);
3016#endif
3017 elmat.SetSize(te_nd,tr_nd);
3018
3019 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
3020 if (ir == NULL)
3021 {
3022 int order = 2 * max(test_fe.GetOrder(),
3023 trial_fe.GetOrder()) - 2; // <--- OK for RTk
3024 ir = &IntRules.Get(test_fe.GetGeomType(), order);
3025 }
3026
3027 elmat = 0.0;
3028
3029 for (int i = 0; i < ir -> GetNPoints(); i++)
3030 {
3031 const IntegrationPoint &ip = ir->IntPoint(i);
3032
3033 trial_fe.CalcDivShape(ip,divshape);
3034 test_fe.CalcDivShape(ip,te_divshape);
3035
3036 Trans.SetIntPoint (&ip);
3037 c = ip.weight / Trans.Weight();
3038
3039 if (Q)
3040 {
3041 c *= Q -> Eval (Trans, ip);
3042 }
3043
3044 te_divshape *= c;
3045 AddMultVWt(te_divshape, divshape, elmat);
3046 }
3047}
3048
3050 const FiniteElement &el,
3051 ElementTransformation &Trans,
3052 DenseMatrix &elmat)
3053{
3054 const int dof = el.GetDof();
3055 dim = el.GetDim();
3056 sdim = Trans.GetSpaceDim();
3057
3058 // If vdim is not set, set it to the space dimension;
3059 vdim = (vdim <= 0) ? sdim : vdim;
3060 const bool square = (dim == sdim);
3061
3062 if (VQ)
3063 {
3064 vcoeff.SetSize(vdim);
3065 }
3066 else if (MQ)
3067 {
3068 mcoeff.SetSize(vdim);
3069 }
3070
3071 dshape.SetSize(dof, dim);
3072 dshapedxt.SetSize(dof, sdim);
3073
3074 elmat.SetSize(vdim * dof);
3075 pelmat.SetSize(dof);
3076
3077 const IntegrationRule *ir = GetIntegrationRule(el, Trans);
3078 if (ir == NULL)
3079 {
3080 ir = &DiffusionIntegrator::GetRule(el,el);
3081 }
3082
3083 elmat = 0.0;
3084
3085 for (int i = 0; i < ir -> GetNPoints(); i++)
3086 {
3087 const IntegrationPoint &ip = ir->IntPoint(i);
3088 el.CalcDShape(ip, dshape);
3089
3090 Trans.SetIntPoint(&ip);
3091 real_t w = Trans.Weight();
3092 w = ip.weight / (square ? w : w*w*w);
3093 // AdjugateJacobian = / adj(J), if J is square
3094 // \ adj(J^t.J).J^t, otherwise
3095 Mult(dshape, Trans.AdjugateJacobian(), dshapedxt);
3096
3097 if (VQ)
3098 {
3099 VQ->Eval(vcoeff, Trans, ip);
3100 for (int k = 0; k < vdim; ++k)
3101 {
3102 Mult_a_AAt(w*vcoeff(k), dshapedxt, pelmat);
3103 elmat.AddMatrix(pelmat, dof*k, dof*k);
3104 }
3105 }
3106 else if (MQ)
3107 {
3108 MQ->Eval(mcoeff, Trans, ip);
3109 for (int ii = 0; ii < vdim; ++ii)
3110 {
3111 for (int jj = 0; jj < vdim; ++jj)
3112 {
3113 Mult_a_AAt(w*mcoeff(ii,jj), dshapedxt, pelmat);
3114 elmat.AddMatrix(pelmat, dof*ii, dof*jj);
3115 }
3116 }
3117 }
3118 else
3119 {
3120 if (Q) { w *= Q->Eval(Trans, ip); }
3121 Mult_a_AAt(w, dshapedxt, pelmat);
3122 for (int k = 0; k < vdim; ++k)
3123 {
3124 elmat.AddMatrix(pelmat, dof*k, dof*k);
3125 }
3126 }
3127 }
3128}
3129
3131 const FiniteElement &el, ElementTransformation &Tr,
3132 const Vector &elfun, Vector &elvect)
3133{
3134 const int dof = el.GetDof();
3135 dim = el.GetDim();
3136 sdim = Tr.GetSpaceDim();
3137
3138 // If vdim is not set, set it to the space dimension;
3139 vdim = (vdim <= 0) ? sdim : vdim;
3140 const bool square = (dim == sdim);
3141
3142 if (VQ)
3143 {
3144 vcoeff.SetSize(vdim);
3145 }
3146 else if (MQ)
3147 {
3148 mcoeff.SetSize(vdim);
3149 }
3150
3151 dshape.SetSize(dof, dim);
3152 dshapedxt.SetSize(dof, sdim);
3153 pelmat.SetSize(dof);
3154
3155 elvect.SetSize(vdim*dof);
3156
3157 // NOTE: DenseMatrix is in column-major order. This is consistent with
3158 // vectors ordered byNODES. In the resulting DenseMatrix, each column
3159 // corresponds to a particular vdim.
3160 DenseMatrix mat_in(elfun.GetData(), dof, vdim);
3161 DenseMatrix mat_out(elvect.GetData(), dof, vdim);
3162
3163
3164 const IntegrationRule *ir = GetIntegrationRule(el, Tr);
3165 if (ir == NULL)
3166 {
3167 ir = &DiffusionIntegrator::GetRule(el,el);
3168 }
3169
3170 elvect = 0.0;
3171 for (int i = 0; i < ir->GetNPoints(); i++)
3172 {
3173 const IntegrationPoint &ip = ir->IntPoint(i);
3174 el.CalcDShape(ip, dshape);
3175
3176 Tr.SetIntPoint(&ip);
3177 real_t w = Tr.Weight();
3178 w = ip.weight / (square ? w : w*w*w);
3179 Mult(dshape, Tr.AdjugateJacobian(), dshapedxt);
3180 MultAAt(dshapedxt, pelmat);
3181
3182 if (VQ)
3183 {
3184 VQ->Eval(vcoeff, Tr, ip);
3185 for (int k = 0; k < vdim; ++k)
3186 {
3187 const Vector vec_in(mat_in.GetColumn(k), dof);
3188 Vector vec_out(mat_out.GetColumn(k), dof);
3189 pelmat.AddMult_a(w*vcoeff(k), vec_in, vec_out);
3190 }
3191 }
3192 else if (MQ)
3193 {
3194 MQ->Eval(mcoeff, Tr, ip);
3195 for (int ii = 0; ii < vdim; ++ii)
3196 {
3197 Vector vec_out(mat_out.GetColumn(ii), dof);
3198 for (int jj = 0; jj < vdim; ++jj)
3199 {
3200 const Vector vec_in(mat_in.GetColumn(jj), dof);
3201 pelmat.AddMult_a(w*mcoeff(ii,jj), vec_in, vec_out);
3202 }
3203 }
3204 }
3205 else
3206 {
3207 if (Q) { w *= Q->Eval(Tr, ip); }
3208 pelmat *= w;
3209 for (int k = 0; k < vdim; ++k)
3210 {
3211 const Vector vec_in(mat_in.GetColumn(k), dof);
3212 Vector vec_out(mat_out.GetColumn(k), dof);
3213 pelmat.AddMult(vec_in, vec_out);
3214 }
3215 }
3216 }
3217}
3218
3220 ElasticityIntegrator &parent_, int i_, int j_)
3221 : parent(parent_),
3222 i_block(i_),
3223 j_block(j_)
3224{ }
3225
3227 const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat)
3228{
3229 int dof = el.GetDof();
3230 int dim = el.GetDim();
3231 real_t w, L, M;
3232
3233 MFEM_ASSERT(dim == Trans.GetSpaceDim(), "");
3234
3235#ifdef MFEM_THREAD_SAFE
3236 DenseMatrix dshape(dof, dim), gshape(dof, dim), pelmat(dof);
3237 Vector divshape(dim*dof);
3238#else
3239 dshape.SetSize(dof, dim);
3240 gshape.SetSize(dof, dim);
3241 pelmat.SetSize(dof);
3242 divshape.SetSize(dim*dof);
3243#endif
3244
3245 elmat.SetSize(dof * dim);
3246
3247 const IntegrationRule *ir = GetIntegrationRule(el, Trans);
3248 if (ir == NULL)
3249 {
3250 int order = 2 * Trans.OrderGrad(&el); // correct order?
3251 ir = &IntRules.Get(el.GetGeomType(), order);
3252 }
3253
3254 elmat = 0.0;
3255
3256 for (int i = 0; i < ir->GetNPoints(); i++)
3257 {
3258 const IntegrationPoint &ip = ir->IntPoint(i);
3259
3260 el.CalcDShape(ip, dshape);
3261
3262 Trans.SetIntPoint(&ip);
3263 w = ip.weight * Trans.Weight();
3264 Mult(dshape, Trans.InverseJacobian(), gshape);
3265 MultAAt(gshape, pelmat);
3266 gshape.GradToDiv (divshape);
3267
3268 M = mu->Eval(Trans, ip);
3269 if (lambda)
3270 {
3271 L = lambda->Eval(Trans, ip);
3272 }
3273 else
3274 {
3275 L = q_lambda * M;
3276 M = q_mu * M;
3277 }
3278
3279 if (L != 0.0)
3280 {
3281 AddMult_a_VVt(L * w, divshape, elmat);
3282 }
3283
3284 if (M != 0.0)
3285 {
3286 for (int d = 0; d < dim; d++)
3287 {
3288 for (int k = 0; k < dof; k++)
3289 for (int l = 0; l < dof; l++)
3290 {
3291 elmat (dof*d+k, dof*d+l) += (M * w) * pelmat(k, l);
3292 }
3293 }
3294 for (int ii = 0; ii < dim; ii++)
3295 for (int jj = 0; jj < dim; jj++)
3296 {
3297 for (int kk = 0; kk < dof; kk++)
3298 for (int ll = 0; ll < dof; ll++)
3299 {
3300 elmat(dof*ii+kk, dof*jj+ll) +=
3301 (M * w) * gshape(kk, jj) * gshape(ll, ii);
3302 }
3303 }
3304 }
3305 }
3306}
3307
3310 Vector &u, const mfem::FiniteElement &fluxelem, Vector &flux,
3311 bool with_coef, const IntegrationRule *ir)
3312{
3313 const int dof = el.GetDof();
3314 const int dim = el.GetDim();
3315 const int tdim = dim*(dim+1)/2; // num. entries in a symmetric tensor
3316 real_t L, M;
3317
3318 MFEM_ASSERT(dim == 2 || dim == 3,
3319 "dimension is not supported: dim = " << dim);
3320 MFEM_ASSERT(dim == Trans.GetSpaceDim(), "");
3321 MFEM_ASSERT(fluxelem.GetMapType() == FiniteElement::VALUE, "");
3322 MFEM_ASSERT(dynamic_cast<const NodalFiniteElement*>(&fluxelem), "");
3323
3324#ifdef MFEM_THREAD_SAFE
3325 DenseMatrix dshape(dof, dim);
3326#else
3327 dshape.SetSize(dof, dim);
3328#endif
3329
3330 real_t gh_data[9], grad_data[9];
3331 DenseMatrix gh(gh_data, dim, dim);
3332 DenseMatrix grad(grad_data, dim, dim);
3333
3334 if (!ir)
3335 {
3336 ir = &fluxelem.GetNodes();
3337 }
3338 const int fnd = ir->GetNPoints();
3339 flux.SetSize(fnd * tdim);
3340
3341 DenseMatrix loc_data_mat(u.GetData(), dof, dim);
3342 for (int i = 0; i < fnd; i++)
3343 {
3344 const IntegrationPoint &ip = ir->IntPoint(i);
3345 el.CalcDShape(ip, dshape);
3346 MultAtB(loc_data_mat, dshape, gh);
3347
3348 Trans.SetIntPoint(&ip);
3349 Mult(gh, Trans.InverseJacobian(), grad);
3350
3351 M = mu->Eval(Trans, ip);
3352 if (lambda)
3353 {
3354 L = lambda->Eval(Trans, ip);
3355 }
3356 else
3357 {
3358 L = q_lambda * M;
3359 M = q_mu * M;
3360 }
3361
3362 // stress = 2*M*e(u) + L*tr(e(u))*I, where
3363 // e(u) = (1/2)*(grad(u) + grad(u)^T)
3364 const real_t M2 = 2.0*M;
3365 if (dim == 2)
3366 {
3367 L *= (grad(0,0) + grad(1,1));
3368 // order of the stress entries: s_xx, s_yy, s_xy
3369 flux(i+fnd*0) = M2*grad(0,0) + L;
3370 flux(i+fnd*1) = M2*grad(1,1) + L;
3371 flux(i+fnd*2) = M*(grad(0,1) + grad(1,0));
3372 }
3373 else if (dim == 3)
3374 {
3375 L *= (grad(0,0) + grad(1,1) + grad(2,2));
3376 // order of the stress entries: s_xx, s_yy, s_zz, s_xy, s_xz, s_yz
3377 flux(i+fnd*0) = M2*grad(0,0) + L;
3378 flux(i+fnd*1) = M2*grad(1,1) + L;
3379 flux(i+fnd*2) = M2*grad(2,2) + L;
3380 flux(i+fnd*3) = M*(grad(0,1) + grad(1,0));
3381 flux(i+fnd*4) = M*(grad(0,2) + grad(2,0));
3382 flux(i+fnd*5) = M*(grad(1,2) + grad(2,1));
3383 }
3384 }
3385}
3386
3388 ElementTransformation &Trans,
3389 Vector &flux, Vector *d_energy)
3390{
3391 const int dof = fluxelem.GetDof();
3392 const int dim = fluxelem.GetDim();
3393 const int tdim = dim*(dim+1)/2; // num. entries in a symmetric tensor
3394 real_t L, M;
3395
3396 // The MFEM_ASSERT constraints in ElasticityIntegrator::ComputeElementFlux
3397 // are assumed here too.
3398 MFEM_ASSERT(d_energy == NULL, "anisotropic estimates are not supported");
3399 MFEM_ASSERT(flux.Size() == dof*tdim, "invalid 'flux' vector");
3400
3401#ifndef MFEM_THREAD_SAFE
3402 shape.SetSize(dof);
3403#else
3404 Vector shape(dof);
3405#endif
3406 real_t pointstress_data[6];
3407 Vector pointstress(pointstress_data, tdim);
3408
3409 // View of the 'flux' vector as a (dof x tdim) matrix
3410 DenseMatrix flux_mat(flux.GetData(), dof, tdim);
3411
3412 // Use the same integration rule as in AssembleElementMatrix, replacing 'el'
3413 // with 'fluxelem' when 'IntRule' is not set.
3414 // Should we be using a different (more accurate) rule here?
3415
3416 const IntegrationRule *ir = GetIntegrationRule(fluxelem, Trans);
3417 if (ir == NULL)
3418 {
3419 int order = 2 * Trans.OrderGrad(&fluxelem);
3420 ir = &IntRules.Get(fluxelem.GetGeomType(), order);
3421 }
3422
3423 real_t energy = 0.0;
3424
3425 for (int i = 0; i < ir->GetNPoints(); i++)
3426 {
3427 const IntegrationPoint &ip = ir->IntPoint(i);
3428 Trans.SetIntPoint(&ip);
3429 fluxelem.CalcPhysShape(Trans, shape);
3430
3431 flux_mat.MultTranspose(shape, pointstress);
3432
3433 real_t w = Trans.Weight() * ip.weight;
3434
3435 M = mu->Eval(Trans, ip);
3436 if (lambda)
3437 {
3438 L = lambda->Eval(Trans, ip);
3439 }
3440 else
3441 {
3442 L = q_lambda * M;
3443 M = q_mu * M;
3444 }
3445
3446 // The strain energy density at a point is given by (1/2)*(s : e) where s
3447 // and e are the stress and strain tensors, respectively. Since we only
3448 // have the stress, we need to compute the strain from the stress:
3449 // s = 2*mu*e + lambda*tr(e)*I
3450 // Taking trace on both sides we find:
3451 // tr(s) = 2*mu*tr(e) + lambda*tr(e)*dim = (2*mu + dim*lambda)*tr(e)
3452 // which gives:
3453 // tr(e) = tr(s)/(2*mu + dim*lambda)
3454 // Then from the first identity above we can find the strain:
3455 // e = (1/(2*mu))*(s - lambda*tr(e)*I)
3456
3457 real_t pt_e; // point strain energy density
3458 const real_t *s = pointstress_data;
3459 if (dim == 2)
3460 {
3461 // s entries: s_xx, s_yy, s_xy
3462 const real_t tr_e = (s[0] + s[1])/(2*(M + L));
3463 L *= tr_e;
3464 pt_e = (0.25/M)*(s[0]*(s[0] - L) + s[1]*(s[1] - L) + 2*s[2]*s[2]);
3465 }
3466 else // (dim == 3)
3467 {
3468 // s entries: s_xx, s_yy, s_zz, s_xy, s_xz, s_yz
3469 const real_t tr_e = (s[0] + s[1] + s[2])/(2*M + 3*L);
3470 L *= tr_e;
3471 pt_e = (0.25/M)*(s[0]*(s[0] - L) + s[1]*(s[1] - L) + s[2]*(s[2] - L) +
3472 2*(s[3]*s[3] + s[4]*s[4] + s[5]*s[5]));
3473 }
3474
3475 energy += w * pt_e;
3476 }
3477 return energy;
3478}
3479
3481 const FiniteElement &el2,
3483 DenseMatrix &elmat)
3484{
3485 int ndof1, ndof2;
3486
3487 real_t un, a, b, w;
3488
3489 dim = el1.GetDim();
3490 ndof1 = el1.GetDof();
3491 Vector vu(dim), nor(dim);
3492
3493 if (Trans.Elem2No >= 0)
3494 {
3495 ndof2 = el2.GetDof();
3496 }
3497 else
3498 {
3499 ndof2 = 0;
3500 }
3501
3502 shape1.SetSize(ndof1);
3503 shape2.SetSize(ndof2);
3504 elmat.SetSize(ndof1 + ndof2);
3505 elmat = 0.0;
3506
3507 const IntegrationRule *ir = IntRule;
3508 if (ir == NULL)
3509 {
3510 int order;
3511 // Assuming order(u)==order(mesh)
3512 if (Trans.Elem2No >= 0)
3513 order = (min(Trans.Elem1->OrderW(), Trans.Elem2->OrderW()) +
3514 2*max(el1.GetOrder(), el2.GetOrder()));
3515 else
3516 {
3517 order = Trans.Elem1->OrderW() + 2*el1.GetOrder();
3518 }
3519 if (el1.Space() == FunctionSpace::Pk)
3520 {
3521 order++;
3522 }
3523 ir = &IntRules.Get(Trans.GetGeometryType(), order);
3524 }
3525
3526 for (int p = 0; p < ir->GetNPoints(); p++)
3527 {
3528 const IntegrationPoint &ip = ir->IntPoint(p);
3529
3530 // Set the integration point in the face and the neighboring elements
3531 Trans.SetAllIntPoints(&ip);
3532
3533 // Access the neighboring elements' integration points
3534 // Note: eip2 will only contain valid data if Elem2 exists
3535 const IntegrationPoint &eip1 = Trans.GetElement1IntPoint();
3536 const IntegrationPoint &eip2 = Trans.GetElement2IntPoint();
3537
3538 el1.CalcPhysShape(*Trans.Elem1, shape1);
3539
3540 u->Eval(vu, *Trans.Elem1, eip1);
3541
3542 if (dim == 1)
3543 {
3544 nor(0) = 2*eip1.x - 1.0;
3545 }
3546 else
3547 {
3548 CalcOrtho(Trans.Jacobian(), nor);
3549 }
3550
3551 un = vu * nor;
3552 a = 0.5 * alpha * un;
3553 b = beta * fabs(un);
3554 // note: if |alpha/2|==|beta| then |a|==|b|, i.e. (a==b) or (a==-b)
3555 // and therefore two blocks in the element matrix contribution
3556 // (from the current quadrature point) are 0
3557
3558 if (rho)
3559 {
3560 real_t rho_p;
3561 if (un >= 0.0 && ndof2)
3562 {
3563 rho_p = rho->Eval(*Trans.Elem2, eip2);
3564 }
3565 else
3566 {
3567 rho_p = rho->Eval(*Trans.Elem1, eip1);
3568 }
3569 a *= rho_p;
3570 b *= rho_p;
3571 }
3572
3573 w = ip.weight * (a+b);
3574 if (w != 0.0)
3575 {
3576 for (int i = 0; i < ndof1; i++)
3577 for (int j = 0; j < ndof1; j++)
3578 {
3579 elmat(i, j) += w * shape1(i) * shape1(j);
3580 }
3581 }
3582
3583 if (ndof2)
3584 {
3585 el2.CalcPhysShape(*Trans.Elem2, shape2);
3586
3587 if (w != 0.0)
3588 for (int i = 0; i < ndof2; i++)
3589 for (int j = 0; j < ndof1; j++)
3590 {
3591 elmat(ndof1+i, j) -= w * shape2(i) * shape1(j);
3592 }
3593
3594 w = ip.weight * (b-a);
3595 if (w != 0.0)
3596 {
3597 for (int i = 0; i < ndof2; i++)
3598 for (int j = 0; j < ndof2; j++)
3599 {
3600 elmat(ndof1+i, ndof1+j) += w * shape2(i) * shape2(j);
3601 }
3602
3603 for (int i = 0; i < ndof1; i++)
3604 for (int j = 0; j < ndof2; j++)
3605 {
3606 elmat(i, ndof1+j) -= w * shape1(i) * shape2(j);
3607 }
3608 }
3609 }
3610 }
3611}
3612
3614 const FiniteElement &test_fe1,
3615 const FiniteElement &trial_fe2,
3616 const FiniteElement &test_fe2,
3618 DenseMatrix &elmat)
3619{
3620 int tr_ndof1, te_ndof1, tr_ndof2, te_ndof2;
3621
3622 real_t un, a, b, w;
3623
3624 dim = test_fe1.GetDim();
3625 tr_ndof1 = trial_fe1.GetDof();
3626 te_ndof1 = test_fe1.GetDof();
3627 Vector vu(dim), nor(dim);
3628
3629 if (Trans.Elem2No >= 0)
3630 {
3631 tr_ndof2 = trial_fe2.GetDof();
3632 te_ndof2 = test_fe2.GetDof();
3633 }
3634 else
3635 {
3636 tr_ndof2 = 0;
3637 te_ndof2 = 0;
3638 }
3639
3640 tr_shape1.SetSize(tr_ndof1);
3641 te_shape1.SetSize(te_ndof1);
3642 tr_shape2.SetSize(tr_ndof2);
3643 te_shape2.SetSize(te_ndof2);
3644 elmat.SetSize(te_ndof1 + te_ndof2, tr_ndof1 + tr_ndof2);
3645 elmat = 0.0;
3646
3647 const IntegrationRule *ir = IntRule;
3648 if (ir == NULL)
3649 {
3650 int order;
3651 // Assuming order(u)==order(mesh)
3652 if (Trans.Elem2No >= 0)
3653 order = (min(Trans.Elem1->OrderW(), Trans.Elem2->OrderW()) +
3654 max(trial_fe1.GetOrder(), trial_fe2.GetOrder()) +
3655 max(test_fe1.GetOrder(), test_fe2.GetOrder()));
3656 else
3657 {
3658 order = Trans.Elem1->OrderW() + trial_fe1.GetOrder() + test_fe1.GetOrder();
3659 }
3660 if (trial_fe1.Space() == FunctionSpace::Pk)
3661 {
3662 order++;
3663 }
3664 ir = &IntRules.Get(Trans.FaceGeom, order);
3665 }
3666
3667 for (int p = 0; p < ir->GetNPoints(); p++)
3668 {
3669 const IntegrationPoint &ip = ir->IntPoint(p);
3670 IntegrationPoint eip1, eip2;
3671 Trans.Loc1.Transform(ip, eip1);
3672 Trans.Elem1->SetIntPoint(&eip1);
3673 if (tr_ndof2 && te_ndof2)
3674 {
3675 Trans.Loc2.Transform(ip, eip2);
3676 Trans.Elem2->SetIntPoint(&eip2);
3677 }
3678 trial_fe1.CalcPhysShape(*Trans.Elem1, tr_shape1);
3679 test_fe1.CalcPhysShape(*Trans.Elem1, te_shape1);
3680
3681 Trans.Face->SetIntPoint(&ip);
3682
3683 u->Eval(vu, *Trans.Elem1, eip1);
3684
3685 if (dim == 1)
3686 {
3687 nor(0) = 2*eip1.x - 1.0;
3688 }
3689 else
3690 {
3691 CalcOrtho(Trans.Face->Jacobian(), nor);
3692 }
3693
3694 un = vu * nor;
3695 a = 0.5 * alpha * un;
3696 b = beta * fabs(un);
3697 // note: if |alpha/2|==|beta| then |a|==|b|, i.e. (a==b) or (a==-b)
3698 // and therefore two blocks in the element matrix contribution
3699 // (from the current quadrature point) are 0
3700
3701 if (rho)
3702 {
3703 real_t rho_p;
3704 if (un >= 0.0 && tr_ndof2 && te_ndof2)
3705 {
3706 Trans.Elem2->SetIntPoint(&eip2);
3707 rho_p = rho->Eval(*Trans.Elem2, eip2);
3708 }
3709 else
3710 {
3711 rho_p = rho->Eval(*Trans.Elem1, eip1);
3712 }
3713 a *= rho_p;
3714 b *= rho_p;
3715 }
3716
3717 w = ip.weight * (a+b);
3718 if (w != 0.0)
3719 {
3720 for (int i = 0; i < te_ndof1; i++)
3721 for (int j = 0; j < tr_ndof1; j++)
3722 {
3723 elmat(i, j) += w * te_shape1(i) * tr_shape1(j);
3724 }
3725 }
3726
3727 if (tr_ndof2 && te_ndof2)
3728 {
3729 trial_fe2.CalcPhysShape(*Trans.Elem2, tr_shape2);
3730 test_fe2.CalcPhysShape(*Trans.Elem2, te_shape2);
3731
3732 if (w != 0.0)
3733 for (int i = 0; i < te_ndof2; i++)
3734 for (int j = 0; j < tr_ndof1; j++)
3735 {
3736 elmat(te_ndof1+i, j) -= w * te_shape2(i) * tr_shape1(j);
3737 }
3738
3739 w = ip.weight * (b-a);
3740 if (w != 0.0)
3741 {
3742 for (int i = 0; i < te_ndof2; i++)
3743 for (int j = 0; j < tr_ndof2; j++)
3744 {
3745 elmat(te_ndof1+i, tr_ndof1+j) += w * te_shape2(i) * tr_shape2(j);
3746 }
3747
3748 for (int i = 0; i < te_ndof1; i++)
3749 for (int j = 0; j < tr_ndof2; j++)
3750 {
3751 elmat(i, tr_ndof1+j) -= w * te_shape1(i) * tr_shape2(j);
3752 }
3753 }
3754 }
3755 }
3756}
3757
3759 Geometry::Type geom, int order, const ElementTransformation &T)
3760{
3761 return IntRules.Get(geom, T.OrderW() + 2*order);
3762}
3763
3765 Geometry::Type geom, int order, const FaceElementTransformations &T)
3766{
3767 return GetRule(geom, order, *T.Elem1);
3768}
3769
3771 const FiniteElement &el1, const FiniteElement &el2,
3773{
3774 int ndof1, ndof2, ndofs;
3775 bool kappa_is_nonzero = (kappa != 0.);
3776 real_t w, wq = 0.0;
3777
3778 dim = el1.GetDim();
3779 ndof1 = el1.GetDof();
3780
3781 nor.SetSize(dim);
3782 nh.SetSize(dim);
3783 ni.SetSize(dim);
3784 adjJ.SetSize(dim);
3785 if (MQ)
3786 {
3787 mq.SetSize(dim);
3788 }
3789
3790 shape1.SetSize(ndof1);
3791 dshape1.SetSize(ndof1, dim);
3792 dshape1dn.SetSize(ndof1);
3793 if (Trans.Elem2No >= 0)
3794 {
3795 ndof2 = el2.GetDof();
3796 shape2.SetSize(ndof2);
3797 dshape2.SetSize(ndof2, dim);
3798 dshape2dn.SetSize(ndof2);
3799 }
3800 else
3801 {
3802 ndof2 = 0;
3803 }
3804
3805 ndofs = ndof1 + ndof2;
3806 elmat.SetSize(ndofs);
3807 elmat = 0.0;
3808 if (kappa_is_nonzero)
3809 {
3810 jmat.SetSize(ndofs);
3811 jmat = 0.;
3812 }
3813
3814 const IntegrationRule *ir = IntRule;
3815 if (ir == NULL)
3816 {
3817 const int order = (ndof2) ? max(el1.GetOrder(),
3818 el2.GetOrder()) : el1.GetOrder();
3819 ir = &GetRule(order, Trans.GetGeometryType());
3820 }
3821
3822 // assemble: < {(Q \nabla u).n},[v] > --> elmat
3823 // kappa < {h^{-1} Q} [u],[v] > --> jmat
3824 for (int p = 0; p < ir->GetNPoints(); p++)
3825 {
3826 const IntegrationPoint &ip = ir->IntPoint(p);
3827
3828 // Set the integration point in the face and the neighboring elements
3829 Trans.SetAllIntPoints(&ip);
3830
3831 // Access the neighboring elements' integration points
3832 // Note: eip2 will only contain valid data if Elem2 exists
3833 const IntegrationPoint &eip1 = Trans.GetElement1IntPoint();
3834 const IntegrationPoint &eip2 = Trans.GetElement2IntPoint();
3835
3836 if (dim == 1)
3837 {
3838 nor(0) = 2*eip1.x - 1.0;
3839 }
3840 else
3841 {
3842 CalcOrtho(Trans.Jacobian(), nor);
3843 }
3844
3845 el1.CalcShape(eip1, shape1);
3846 el1.CalcDShape(eip1, dshape1);
3847 w = ip.weight/Trans.Elem1->Weight();
3848 if (ndof2)
3849 {
3850 w /= 2;
3851 }
3852 if (!MQ)
3853 {
3854 if (Q)
3855 {
3856 w *= Q->Eval(*Trans.Elem1, eip1);
3857 }
3858 ni.Set(w, nor);
3859 }
3860 else
3861 {
3862 nh.Set(w, nor);
3863 MQ->Eval(mq, *Trans.Elem1, eip1);
3865 }
3866 CalcAdjugate(Trans.Elem1->Jacobian(), adjJ);
3867 adjJ.Mult(ni, nh);
3868 if (kappa_is_nonzero)
3869 {
3870 wq = ni * nor;
3871 }
3872 // Note: in the jump term, we use 1/h1 = |nor|/det(J1) which is
3873 // independent of Loc1 and always gives the size of element 1 in
3874 // direction perpendicular to the face. Indeed, for linear transformation
3875 // |nor|=measure(face)/measure(ref. face),
3876 // det(J1)=measure(element)/measure(ref. element),
3877 // and the ratios measure(ref. element)/measure(ref. face) are
3878 // compatible for all element/face pairs.
3879 // For example: meas(ref. tetrahedron)/meas(ref. triangle) = 1/3, and
3880 // for any tetrahedron vol(tet)=(1/3)*height*area(base).
3881 // For interior faces: q_e/h_e=(q1/h1+q2/h2)/2.
3882
3884 for (int i = 0; i < ndof1; i++)
3885 for (int j = 0; j < ndof1; j++)
3886 {
3887 elmat(i, j) += shape1(i) * dshape1dn(j);
3888 }
3889
3890 if (ndof2)
3891 {
3892 el2.CalcShape(eip2, shape2);
3893 el2.CalcDShape(eip2, dshape2);
3894 w = ip.weight/2/Trans.Elem2->Weight();
3895 if (!MQ)
3896 {
3897 if (Q)
3898 {
3899 w *= Q->Eval(*Trans.Elem2, eip2);
3900 }
3901 ni.Set(w, nor);
3902 }
3903 else
3904 {
3905 nh.Set(w, nor);
3906 MQ->Eval(mq, *Trans.Elem2, eip2);
3908 }
3909 CalcAdjugate(Trans.Elem2->Jacobian(), adjJ);
3910 adjJ.Mult(ni, nh);
3911 if (kappa_is_nonzero)
3912 {
3913 wq += ni * nor;
3914 }
3915
3917
3918 for (int i = 0; i < ndof1; i++)
3919 for (int j = 0; j < ndof2; j++)
3920 {
3921 elmat(i, ndof1 + j) += shape1(i) * dshape2dn(j);
3922 }
3923
3924 for (int i = 0; i < ndof2; i++)
3925 for (int j = 0; j < ndof1; j++)
3926 {
3927 elmat(ndof1 + i, j) -= shape2(i) * dshape1dn(j);
3928 }
3929
3930 for (int i = 0; i < ndof2; i++)
3931 for (int j = 0; j < ndof2; j++)
3932 {
3933 elmat(ndof1 + i, ndof1 + j) -= shape2(i) * dshape2dn(j);
3934 }
3935 }
3936
3937 if (kappa_is_nonzero)
3938 {
3939 // only assemble the lower triangular part of jmat
3940 wq *= kappa;
3941 for (int i = 0; i < ndof1; i++)
3942 {
3943 const real_t wsi = wq*shape1(i);
3944 for (int j = 0; j <= i; j++)
3945 {
3946 jmat(i, j) += wsi * shape1(j);
3947 }
3948 }
3949 if (ndof2)
3950 {
3951 for (int i = 0; i < ndof2; i++)
3952 {
3953 const int i2 = ndof1 + i;
3954 const real_t wsi = wq*shape2(i);
3955 for (int j = 0; j < ndof1; j++)
3956 {
3957 jmat(i2, j) -= wsi * shape1(j);
3958 }
3959 for (int j = 0; j <= i; j++)
3960 {
3961 jmat(i2, ndof1 + j) += wsi * shape2(j);
3962 }
3963 }
3964 }
3965 }
3966 }
3967
3968 // elmat := -elmat + sigma*elmat^t + jmat
3969 if (kappa_is_nonzero)
3970 {
3971 for (int i = 0; i < ndofs; i++)
3972 {
3973 for (int j = 0; j < i; j++)
3974 {
3975 real_t aij = elmat(i,j), aji = elmat(j,i), mij = jmat(i,j);
3976 elmat(i,j) = sigma*aji - aij + mij;
3977 elmat(j,i) = sigma*aij - aji + mij;
3978 }
3979 elmat(i,i) = (sigma - 1.)*elmat(i,i) + jmat(i,i);
3980 }
3981 }
3982 else
3983 {
3984 for (int i = 0; i < ndofs; i++)
3985 {
3986 for (int j = 0; j < i; j++)
3987 {
3988 real_t aij = elmat(i,j), aji = elmat(j,i);
3989 elmat(i,j) = sigma*aji - aij;
3990 elmat(j,i) = sigma*aij - aji;
3991 }
3992 elmat(i,i) *= (sigma - 1.);
3993 }
3994 }
3995}
3996
3998 int order, Geometry::Type geom)
3999{
4000 // order is typically the maximum of the order of the left and right elements
4001 // neighboring the given face.
4002 return IntRules.Get(geom, 2*order);
4003}
4004
4006 int order, FaceElementTransformations &T)
4007{
4008 return GetRule(order, T.GetGeometryType());
4009}
4010
4011// static method
4013 const int dim, const int row_ndofs, const int col_ndofs,
4014 const int row_offset, const int col_offset,
4015 const real_t jmatcoef, const Vector &col_nL, const Vector &col_nM,
4016 const Vector &row_shape, const Vector &col_shape,
4017 const Vector &col_dshape_dnM, const DenseMatrix &col_dshape,
4018 DenseMatrix &elmat, DenseMatrix &jmat)
4019{
4020 for (int jm = 0, j = col_offset; jm < dim; ++jm)
4021 {
4022 for (int jdof = 0; jdof < col_ndofs; ++jdof, ++j)
4023 {
4024 const real_t t2 = col_dshape_dnM(jdof);
4025 for (int im = 0, i = row_offset; im < dim; ++im)
4026 {
4027 const real_t t1 = col_dshape(jdof, jm) * col_nL(im);
4028 const real_t t3 = col_dshape(jdof, im) * col_nM(jm);
4029 const real_t tt = t1 + ((im == jm) ? t2 : 0.0) + t3;
4030 for (int idof = 0; idof < row_ndofs; ++idof, ++i)
4031 {
4032 elmat(i, j) += row_shape(idof) * tt;
4033 }
4034 }
4035 }
4036 }
4037
4038 if (jmatcoef == 0.0) { return; }
4039
4040 for (int d = 0; d < dim; ++d)
4041 {
4042 const int jo = col_offset + d*col_ndofs;
4043 const int io = row_offset + d*row_ndofs;
4044 for (int jdof = 0, j = jo; jdof < col_ndofs; ++jdof, ++j)
4045 {
4046 const real_t sj = jmatcoef * col_shape(jdof);
4047 for (int i = max(io,j), idof = i - io; idof < row_ndofs; ++idof, ++i)
4048 {
4049 jmat(i, j) += row_shape(idof) * sj;
4050 }
4051 }
4052 }
4053}
4054
4056 const FiniteElement &el1, const FiniteElement &el2,
4058{
4059#ifdef MFEM_THREAD_SAFE
4060 // For descriptions of these variables, see the class declaration.
4065 Vector nor;
4066 Vector nL1, nL2;
4067 Vector nM1, nM2;
4070#endif
4071
4072 const int dim = el1.GetDim();
4073 const int ndofs1 = el1.GetDof();
4074 const int ndofs2 = (Trans.Elem2No >= 0) ? el2.GetDof() : 0;
4075 const int nvdofs = dim*(ndofs1 + ndofs2);
4076
4077 // Initially 'elmat' corresponds to the term:
4078 // < { sigma(u) . n }, [v] > =
4079 // < { (lambda div(u) I + mu (grad(u) + grad(u)^T)) . n }, [v] >
4080 // But eventually, it's going to be replaced by:
4081 // elmat := -elmat + alpha*elmat^T + jmat
4082 elmat.SetSize(nvdofs);
4083 elmat = 0.;
4084
4085 const bool kappa_is_nonzero = (kappa != 0.0);
4086 if (kappa_is_nonzero)
4087 {
4088 jmat.SetSize(nvdofs);
4089 jmat = 0.;
4090 }
4091
4092 adjJ.SetSize(dim);
4093 shape1.SetSize(ndofs1);
4094 dshape1.SetSize(ndofs1, dim);
4095 dshape1_ps.SetSize(ndofs1, dim);
4096 nor.SetSize(dim);
4097 nL1.SetSize(dim);
4098 nM1.SetSize(dim);
4099 dshape1_dnM.SetSize(ndofs1);
4100
4101 if (ndofs2)
4102 {
4103 shape2.SetSize(ndofs2);
4104 dshape2.SetSize(ndofs2, dim);
4105 dshape2_ps.SetSize(ndofs2, dim);
4106 nL2.SetSize(dim);
4107 nM2.SetSize(dim);
4108 dshape2_dnM.SetSize(ndofs2);
4109 }
4110
4111 const IntegrationRule *ir = IntRule;
4112 if (ir == NULL)
4113 {
4114 // a simple choice for the integration order; is this OK?
4115 const int order = 2 * max(el1.GetOrder(), ndofs2 ? el2.GetOrder() : 0);
4116 ir = &IntRules.Get(Trans.GetGeometryType(), order);
4117 }
4118
4119 for (int pind = 0; pind < ir->GetNPoints(); ++pind)
4120 {
4121 const IntegrationPoint &ip = ir->IntPoint(pind);
4122
4123 // Set the integration point in the face and the neighboring elements
4124 Trans.SetAllIntPoints(&ip);
4125
4126 // Access the neighboring elements' integration points
4127 // Note: eip2 will only contain valid data if Elem2 exists
4128 const IntegrationPoint &eip1 = Trans.GetElement1IntPoint();
4129 const IntegrationPoint &eip2 = Trans.GetElement2IntPoint();
4130
4131 el1.CalcShape(eip1, shape1);
4132 el1.CalcDShape(eip1, dshape1);
4133
4134 CalcAdjugate(Trans.Elem1->Jacobian(), adjJ);
4136
4137 if (dim == 1)
4138 {
4139 nor(0) = 2*eip1.x - 1.0;
4140 }
4141 else
4142 {
4143 CalcOrtho(Trans.Jacobian(), nor);
4144 }
4145
4146 real_t w, wLM;
4147 if (ndofs2)
4148 {
4149 el2.CalcShape(eip2, shape2);
4150 el2.CalcDShape(eip2, dshape2);
4151 CalcAdjugate(Trans.Elem2->Jacobian(), adjJ);
4153
4154 w = ip.weight/2;
4155 const real_t w2 = w / Trans.Elem2->Weight();
4156 const real_t wL2 = w2 * lambda->Eval(*Trans.Elem2, eip2);
4157 const real_t wM2 = w2 * mu->Eval(*Trans.Elem2, eip2);
4158 nL2.Set(wL2, nor);
4159 nM2.Set(wM2, nor);
4160 wLM = (wL2 + 2.0*wM2);
4162 }
4163 else
4164 {
4165 w = ip.weight;
4166 wLM = 0.0;
4167 }
4168
4169 {
4170 const real_t w1 = w / Trans.Elem1->Weight();
4171 const real_t wL1 = w1 * lambda->Eval(*Trans.Elem1, eip1);
4172 const real_t wM1 = w1 * mu->Eval(*Trans.Elem1, eip1);
4173 nL1.Set(wL1, nor);
4174 nM1.Set(wM1, nor);
4175 wLM += (wL1 + 2.0*wM1);
4177 }
4178
4179 const real_t jmatcoef = kappa * (nor*nor) * wLM;
4180
4181 // (1,1) block
4183 dim, ndofs1, ndofs1, 0, 0, jmatcoef, nL1, nM1,
4185
4186 if (ndofs2 == 0) { continue; }
4187
4188 // In both elmat and jmat, shape2 appears only with a minus sign.
4189 shape2.Neg();
4190
4191 // (1,2) block
4193 dim, ndofs1, ndofs2, 0, dim*ndofs1, jmatcoef, nL2, nM2,
4195 // (2,1) block
4197 dim, ndofs2, ndofs1, dim*ndofs1, 0, jmatcoef, nL1, nM1,
4199 // (2,2) block
4201 dim, ndofs2, ndofs2, dim*ndofs1, dim*ndofs1, jmatcoef, nL2, nM2,
4203 }
4204
4205 // elmat := -elmat + alpha*elmat^t + jmat
4206 if (kappa_is_nonzero)
4207 {
4208 for (int i = 0; i < nvdofs; ++i)
4209 {
4210 for (int j = 0; j < i; ++j)
4211 {
4212 real_t aij = elmat(i,j), aji = elmat(j,i), mij = jmat(i,j);
4213 elmat(i,j) = alpha*aji - aij + mij;
4214 elmat(j,i) = alpha*aij - aji + mij;
4215 }
4216 elmat(i,i) = (alpha - 1.)*elmat(i,i) + jmat(i,i);
4217 }
4218 }
4219 else
4220 {
4221 for (int i = 0; i < nvdofs; ++i)
4222 {
4223 for (int j = 0; j < i; ++j)
4224 {
4225 real_t aij = elmat(i,j), aji = elmat(j,i);
4226 elmat(i,j) = alpha*aji - aij;
4227 elmat(j,i) = alpha*aij - aji;
4228 }
4229 elmat(i,i) *= (alpha - 1.);
4230 }
4231 }
4232}
4233
4234
4236 const FiniteElement &trial_face_fe, const FiniteElement &test_fe1,
4237 const FiniteElement &test_fe2, FaceElementTransformations &Trans,
4238 DenseMatrix &elmat)
4239{
4240 int i, j, face_ndof, ndof1, ndof2;
4241 int order;
4242
4243 real_t w;
4244
4245 face_ndof = trial_face_fe.GetDof();
4246 ndof1 = test_fe1.GetDof();
4247
4248 face_shape.SetSize(face_ndof);
4249 shape1.SetSize(ndof1);
4250
4251 if (Trans.Elem2No >= 0)
4252 {
4253 ndof2 = test_fe2.GetDof();
4254 shape2.SetSize(ndof2);
4255 }
4256 else
4257 {
4258 ndof2 = 0;
4259 }
4260
4261 elmat.SetSize(ndof1 + ndof2, face_ndof);
4262 elmat = 0.0;
4263
4264 const IntegrationRule *ir = IntRule;
4265 if (ir == NULL)
4266 {
4267 if (Trans.Elem2No >= 0)
4268 {
4269 order = max(test_fe1.GetOrder(), test_fe2.GetOrder());
4270 }
4271 else
4272 {
4273 order = test_fe1.GetOrder();
4274 }
4275 order += trial_face_fe.GetOrder();
4276 if (trial_face_fe.GetMapType() == FiniteElement::VALUE)
4277 {
4278 order += Trans.OrderW();
4279 }
4280 ir = &IntRules.Get(Trans.GetGeometryType(), order);
4281 }
4282
4283 for (int p = 0; p < ir->GetNPoints(); p++)
4284 {
4285 const IntegrationPoint &ip = ir->IntPoint(p);
4286
4287 // Set the integration point in the face and the neighboring elements
4288 Trans.SetAllIntPoints(&ip);
4289
4290 // Trace finite element shape function
4291 trial_face_fe.CalcShape(ip, face_shape);
4292 // Side 1 finite element shape function
4293 test_fe1.CalcPhysShape(*Trans.Elem1, shape1);
4294 if (ndof2)
4295 {
4296 // Side 2 finite element shape function
4297 test_fe2.CalcPhysShape(*Trans.Elem2, shape2);
4298 }
4299 w = ip.weight;
4300 if (trial_face_fe.GetMapType() == FiniteElement::VALUE)
4301 {
4302 w *= Trans.Weight();
4303 }
4304 face_shape *= w;
4305 for (i = 0; i < ndof1; i++)
4306 for (j = 0; j < face_ndof; j++)
4307 {
4308 elmat(i, j) += shape1(i) * face_shape(j);
4309 }
4310 if (ndof2)
4311 {
4312 // Subtract contribution from side 2
4313 for (i = 0; i < ndof2; i++)
4314 for (j = 0; j < face_ndof; j++)
4315 {
4316 elmat(ndof1+i, j) -= shape2(i) * face_shape(j);
4317 }
4318 }
4319 }
4320}
4321
4323 const FiniteElement &trial_face_fe, const FiniteElement &test_fe1,
4324 const FiniteElement &test_fe2, FaceElementTransformations &Trans,
4325 DenseMatrix &elmat)
4326{
4327 int i, j, face_ndof, ndof1, ndof2, dim;
4328 int order;
4329
4330 MFEM_VERIFY(trial_face_fe.GetMapType() == FiniteElement::VALUE, "");
4331
4332 face_ndof = trial_face_fe.GetDof();
4333 ndof1 = test_fe1.GetDof();
4334 dim = test_fe1.GetDim();
4335
4336 face_shape.SetSize(face_ndof);
4337 normal.SetSize(dim);
4338 shape1.SetSize(ndof1,dim);
4339 shape1_n.SetSize(ndof1);
4340
4341 if (Trans.Elem2No >= 0)
4342 {
4343 ndof2 = test_fe2.GetDof();
4344 shape2.SetSize(ndof2,dim);
4345 shape2_n.SetSize(ndof2);
4346 }
4347 else
4348 {
4349 ndof2 = 0;
4350 }
4351
4352 elmat.SetSize(ndof1 + ndof2, face_ndof);
4353 elmat = 0.0;
4354
4355 const IntegrationRule *ir = IntRule;
4356 if (ir == NULL)
4357 {
4358 if (Trans.Elem2No >= 0)
4359 {
4360 order = max(test_fe1.GetOrder(), test_fe2.GetOrder()) - 1;
4361 }
4362 else
4363 {
4364 order = test_fe1.GetOrder() - 1;
4365 }
4366 order += trial_face_fe.GetOrder();
4367 ir = &IntRules.Get(Trans.GetGeometryType(), order);
4368 }
4369
4370 for (int p = 0; p < ir->GetNPoints(); p++)
4371 {
4372 const IntegrationPoint &ip = ir->IntPoint(p);
4373 IntegrationPoint eip1, eip2;
4374 // Trace finite element shape function
4375 trial_face_fe.CalcShape(ip, face_shape);
4376 Trans.Loc1.Transf.SetIntPoint(&ip);
4377 CalcOrtho(Trans.Loc1.Transf.Jacobian(), normal);
4378 // Side 1 finite element shape function
4379 Trans.Loc1.Transform(ip, eip1);
4380 test_fe1.CalcVShape(eip1, shape1);
4381 shape1.Mult(normal, shape1_n);
4382 if (ndof2)
4383 {
4384 // Side 2 finite element shape function
4385 Trans.Loc2.Transform(ip, eip2);
4386 test_fe2.CalcVShape(eip2, shape2);
4387 Trans.Loc2.Transf.SetIntPoint(&ip);
4388 CalcOrtho(Trans.Loc2.Transf.Jacobian(), normal);
4389 shape2.Mult(normal, shape2_n);
4390 }
4391 face_shape *= ip.weight;
4392 for (i = 0; i < ndof1; i++)
4393 for (j = 0; j < face_ndof; j++)
4394 {
4395 elmat(i, j) += shape1_n(i) * face_shape(j);
4396 }
4397 if (ndof2)
4398 {
4399 // Subtract contribution from side 2
4400 for (i = 0; i < ndof2; i++)
4401 for (j = 0; j < face_ndof; j++)
4402 {
4403 elmat(ndof1+i, j) -= shape2_n(i) * face_shape(j);
4404 }
4405 }
4406 }
4407}
4408
4410 const FiniteElement &trial_face_fe,
4411 const FiniteElement &test_fe,
4413 DenseMatrix &elmat)
4414{
4415 MFEM_VERIFY(test_fe.GetMapType() == FiniteElement::VALUE,
4416 "TraceIntegrator::AssembleTraceFaceMatrix: Test space should be H1");
4417 MFEM_VERIFY(trial_face_fe.GetMapType() == FiniteElement::INTEGRAL,
4418 "TraceIntegrator::AssembleTraceFaceMatrix: Trial space should be RT trace");
4419
4420 int i, j, face_ndof, ndof;
4421 int order;
4422
4423 face_ndof = trial_face_fe.GetDof();
4424 ndof = test_fe.GetDof();
4425
4426 face_shape.SetSize(face_ndof);
4427 shape.SetSize(ndof);
4428
4429 elmat.SetSize(ndof, face_ndof);
4430 elmat = 0.0;
4431
4432 const IntegrationRule *ir = IntRule;
4433 if (ir == NULL)
4434 {
4435 order = test_fe.GetOrder();
4436 order += trial_face_fe.GetOrder();
4437 ir = &IntRules.Get(Trans.GetGeometryType(), order);
4438 }
4439
4440 int iel = Trans.Elem1->ElementNo;
4441 if (iel != elem)
4442 {
4443 MFEM_VERIFY(elem == Trans.Elem2->ElementNo, "Elem != Trans.Elem2->ElementNo");
4444 }
4445
4446 real_t scale = 1.0;
4447 if (iel != elem) { scale = -1.; }
4448 for (int p = 0; p < ir->GetNPoints(); p++)
4449 {
4450 const IntegrationPoint &ip = ir->IntPoint(p);
4451
4452 // Set the integration point in the face and the neighboring elements
4453 Trans.SetAllIntPoints(&ip);
4454 // Trace finite element shape function
4455 trial_face_fe.CalcPhysShape(Trans,face_shape);
4456
4457 // Finite element shape function
4458 ElementTransformation * eltrans = (iel == elem) ? Trans.Elem1 : Trans.Elem2;
4459 test_fe.CalcPhysShape(*eltrans, shape);
4460
4461 face_shape *= Trans.Weight()*ip.weight*scale;
4462 for (i = 0; i < ndof; i++)
4463 {
4464 for (j = 0; j < face_ndof; j++)
4465 {
4466 elmat(i, j) += shape(i) * face_shape(j);
4467 }
4468 }
4469 }
4470}
4471
4473 const FiniteElement &trial_face_fe,
4474 const FiniteElement &test_fe,
4476 DenseMatrix &elmat)
4477{
4478 int i, j, face_ndof, ndof, dim;
4479 int order;
4480
4481 MFEM_VERIFY(test_fe.GetMapType() == FiniteElement::H_DIV,
4482 "NormalTraceIntegrator::AssembleTraceFaceMatrix: Test space should be RT");
4483 MFEM_VERIFY(trial_face_fe.GetMapType() == FiniteElement::VALUE,
4484 "NormalTraceIntegrator::AssembleTraceFaceMatrix: Trial space should be H1 (trace)");
4485
4486 face_ndof = trial_face_fe.GetDof();
4487 ndof = test_fe.GetDof();
4488 dim = test_fe.GetDim();
4489
4490 face_shape.SetSize(face_ndof);
4491 normal.SetSize(dim);
4492 shape.SetSize(ndof,dim);
4493 shape_n.SetSize(ndof);
4494
4495 elmat.SetSize(ndof, face_ndof);
4496 elmat = 0.0;
4497
4498 const IntegrationRule *ir = IntRule;
4499 if (ir == NULL)
4500 {
4501 order = test_fe.GetOrder();
4502 order += trial_face_fe.GetOrder();
4503 ir = &IntRules.Get(Trans.GetGeometryType(), order);
4504 }
4505
4506 int iel = Trans.Elem1->ElementNo;
4507 if (iel != elem)
4508 {
4509 MFEM_VERIFY(elem == Trans.Elem2->ElementNo, "Elem != Trans.Elem2->ElementNo");
4510 }
4511
4512 real_t scale = 1.0;
4513 if (iel != elem) { scale = -1.; }
4514
4515 for (int p = 0; p < ir->GetNPoints(); p++)
4516 {
4517 const IntegrationPoint &ip = ir->IntPoint(p);
4518 Trans.SetAllIntPoints(&ip);
4519 trial_face_fe.CalcPhysShape(Trans, face_shape);
4520 CalcOrtho(Trans.Jacobian(),normal);
4521 ElementTransformation * etrans = (iel == elem) ? Trans.Elem1 : Trans.Elem2;
4522 test_fe.CalcVShape(*etrans, shape);
4523 shape.Mult(normal, shape_n);
4524 face_shape *= ip.weight*scale;
4525
4526 for (i = 0; i < ndof; i++)
4527 {
4528 for (j = 0; j < face_ndof; j++)
4529 {
4530 elmat(i, j) += shape_n(i) * face_shape(j);
4531 }
4532 }
4533 }
4534}
4535
4537 const FiniteElement &trial_face_fe,
4538 const FiniteElement &test_fe,
4540 DenseMatrix &elmat)
4541{
4542
4543 MFEM_VERIFY(test_fe.GetMapType() == FiniteElement::H_CURL,
4544 "TangentTraceIntegrator::AssembleTraceFaceMatrix: Test space should be ND");
4545
4546 int face_ndof, ndof, dim;
4547 int order;
4548 dim = test_fe.GetDim();
4549 if (dim == 3)
4550 {
4551 std::string msg =
4552 "Trial space should be ND face trace and test space should be a ND vector field in 3D ";
4553 MFEM_VERIFY(trial_face_fe.GetMapType() == FiniteElement::H_CURL &&
4554 trial_face_fe.GetDim() == 2 && test_fe.GetDim() == 3, msg);
4555 }
4556 else
4557 {
4558 std::string msg =
4559 "Trial space should be H1 edge trace and test space should be a ND vector field in 2D";
4560 MFEM_VERIFY(trial_face_fe.GetMapType() == FiniteElement::VALUE &&
4561 trial_face_fe.GetDim() == 1 && test_fe.GetDim() == 2, msg);
4562 }
4563 face_ndof = trial_face_fe.GetDof();
4564 ndof = test_fe.GetDof();
4565
4566 int dimc = (dim == 3) ? 3 : 1;
4567
4568 face_shape.SetSize(face_ndof,dimc);
4569 shape_n.SetSize(ndof,dimc);
4570 shape.SetSize(ndof,dim);
4571 normal.SetSize(dim);
4572 DenseMatrix face_shape_n(face_ndof,dimc);
4573
4574 elmat.SetSize(ndof, face_ndof);
4575 elmat = 0.0;
4576
4577 const IntegrationRule *ir = IntRule;
4578 if (ir == NULL)
4579 {
4580 order = test_fe.GetOrder();
4581 order += trial_face_fe.GetOrder();
4582 ir = &IntRules.Get(Trans.GetGeometryType(), order);
4583 }
4584
4585 int iel = Trans.Elem1->ElementNo;
4586 if (iel != elem)
4587 {
4588 MFEM_VERIFY(elem == Trans.Elem2->ElementNo, "Elem != Trans.Elem2->ElementNo");
4589 }
4590
4591 real_t scale = 1.0;
4592 if (iel != elem) { scale = -1.; }
4593 for (int p = 0; p < ir->GetNPoints(); p++)
4594 {
4595 const IntegrationPoint &ip = ir->IntPoint(p);
4596 // Set the integration point in the face and the neighboring elements
4597 Trans.SetAllIntPoints(&ip);
4598 // Trace finite element shape function
4599 if (dim == 3)
4600 {
4601 trial_face_fe.CalcVShape(Trans,face_shape);
4602 }
4603 else
4604 {
4605 face_shape.GetColumnReference(0,temp);
4606 trial_face_fe.CalcPhysShape(Trans,temp);
4607 }
4608 CalcOrtho(Trans.Jacobian(),normal);
4609 ElementTransformation * eltrans = (iel == elem) ? Trans.Elem1 : Trans.Elem2;
4610 test_fe.CalcVShape(*eltrans, shape);
4611
4612 // rotate
4613 cross_product(normal, shape, shape_n);
4614
4615 const real_t w = scale*ip.weight;
4616 AddMult_a_ABt(w,shape_n, face_shape, elmat);
4617 }
4618}
4619
4621 const FiniteElement &dom_fe, const FiniteElement &ran_fe,
4622 ElementTransformation &Trans, DenseMatrix &elmat)
4623{
4624 int spaceDim = Trans.GetSpaceDim();
4625 elmat.SetSize(ran_fe.GetDof(), spaceDim*dom_fe.GetDof());
4626 Vector n(spaceDim), shape(dom_fe.GetDof());
4627
4628 const IntegrationRule &ran_nodes = ran_fe.GetNodes();
4629 for (int i = 0; i < ran_nodes.Size(); i++)
4630 {
4631 const IntegrationPoint &ip = ran_nodes.IntPoint(i);
4632 Trans.SetIntPoint(&ip);
4633 CalcOrtho(Trans.Jacobian(), n);
4634 dom_fe.CalcShape(ip, shape);
4635 for (int j = 0; j < shape.Size(); j++)
4636 {
4637 for (int d = 0; d < spaceDim; d++)
4638 {
4639 elmat(i, j+d*shape.Size()) = shape(j)*n(d);
4640 }
4641 }
4642 }
4643}
4644
4645
4646namespace internal
4647{
4648
4649// Scalar shape functions scaled by scalar coefficient.
4650// Used in the implementation of class ScalarProductInterpolator below.
4651struct ShapeCoefficient : public VectorCoefficient
4652{
4653 Coefficient &Q;
4654 const FiniteElement &fe;
4655
4656 ShapeCoefficient(Coefficient &q, const FiniteElement &fe_)
4657 : VectorCoefficient(fe_.GetDof()), Q(q), fe(fe_) { }
4658
4660 void Eval(Vector &V, ElementTransformation &T,
4661 const IntegrationPoint &ip) override
4662 {
4663 V.SetSize(vdim);
4664 fe.CalcPhysShape(T, V);
4665 V *= Q.Eval(T, ip);
4666 }
4667};
4668
4669}
4670
4671void
4673 const FiniteElement &ran_fe,
4674 ElementTransformation &Trans,
4675 DenseMatrix &elmat)
4676{
4677 internal::ShapeCoefficient dom_shape_coeff(*Q, dom_fe);
4678
4679 elmat.SetSize(ran_fe.GetDof(),dom_fe.GetDof());
4680
4681 Vector elmat_as_vec(elmat.Data(), ran_fe.GetDof()*dom_fe.GetDof());
4682
4683 ran_fe.Project(dom_shape_coeff, Trans, elmat_as_vec);
4684}
4685
4686
4687void
4689 const FiniteElement &dom_fe,
4690 const FiniteElement &ran_fe,
4691 ElementTransformation &Trans,
4692 DenseMatrix &elmat)
4693{
4694 // Vector shape functions scaled by scalar coefficient
4695 struct VShapeCoefficient : public MatrixCoefficient
4696 {
4697 Coefficient &Q;
4698 const FiniteElement &fe;
4699
4700 VShapeCoefficient(Coefficient &q, const FiniteElement &fe_, int sdim)
4701 : MatrixCoefficient(fe_.GetDof(), sdim), Q(q), fe(fe_) { }
4702
4703 void Eval(DenseMatrix &M, ElementTransformation &T,
4704 const IntegrationPoint &ip) override
4705 {
4706 M.SetSize(height, width);
4707 fe.CalcPhysVShape(T, M);
4708 M *= Q.Eval(T, ip);
4709 }
4710 };
4711
4712 VShapeCoefficient dom_shape_coeff(*Q, dom_fe, Trans.GetSpaceDim());
4713
4714 elmat.SetSize(ran_fe.GetDof(),dom_fe.GetDof());
4715
4716 Vector elmat_as_vec(elmat.Data(), ran_fe.GetDof()*dom_fe.GetDof());
4717
4718 ran_fe.ProjectMatrixCoefficient(dom_shape_coeff, Trans, elmat_as_vec);
4719}
4720
4721
4722void
4724 const FiniteElement &dom_fe,
4725 const FiniteElement &ran_fe,
4726 ElementTransformation &Trans,
4727 DenseMatrix &elmat)
4728{
4729 // Scalar shape functions scaled by vector coefficient
4730 struct VecShapeCoefficient : public MatrixCoefficient
4731 {
4733 const FiniteElement &fe;
4734 Vector vc, shape;
4735
4736 VecShapeCoefficient(VectorCoefficient &vq, const FiniteElement &fe_)
4737 : MatrixCoefficient(fe_.GetDof(), vq.GetVDim()), VQ(vq), fe(fe_),
4738 vc(width), shape(height) { }
4739
4740 void Eval(DenseMatrix &M, ElementTransformation &T,
4741 const IntegrationPoint &ip) override
4742 {
4743 M.SetSize(height, width);
4744 VQ.Eval(vc, T, ip);
4745 fe.CalcPhysShape(T, shape);
4746 MultVWt(shape, vc, M);
4747 }
4748 };
4749
4750 VecShapeCoefficient dom_shape_coeff(*VQ, dom_fe);
4751
4752 elmat.SetSize(ran_fe.GetDof(),dom_fe.GetDof());
4753
4754 Vector elmat_as_vec(elmat.Data(), ran_fe.GetDof()*dom_fe.GetDof());
4755
4756 ran_fe.ProjectMatrixCoefficient(dom_shape_coeff, Trans, elmat_as_vec);
4757}
4758
4759
4760void
4762 const FiniteElement &dom_fe,
4763 const FiniteElement &ran_fe,
4764 ElementTransformation &Trans,
4765 DenseMatrix &elmat)
4766{
4767 // Vector coefficient product with vector shape functions
4768 struct VCrossVShapeCoefficient : public VectorCoefficient
4769 {
4771 const FiniteElement &fe;
4772 DenseMatrix vshape;
4773 Vector vc;
4774
4775 VCrossVShapeCoefficient(VectorCoefficient &vq, const FiniteElement &fe_)
4776 : VectorCoefficient(fe_.GetDof()), VQ(vq), fe(fe_),
4777 vshape(vdim, vq.GetVDim()), vc(vq.GetVDim()) { }
4778
4779 using VectorCoefficient::Eval;
4780 void Eval(Vector &V, ElementTransformation &T,
4781 const IntegrationPoint &ip) override
4782 {
4783 V.SetSize(vdim);
4784 VQ.Eval(vc, T, ip);
4785 fe.CalcPhysVShape(T, vshape);
4786 for (int k = 0; k < vdim; k++)
4787 {
4788 V(k) = vc(0) * vshape(k,1) - vc(1) * vshape(k,0);
4789 }
4790 }
4791 };
4792
4793 VCrossVShapeCoefficient dom_shape_coeff(*VQ, dom_fe);
4794
4795 elmat.SetSize(ran_fe.GetDof(),dom_fe.GetDof());
4796
4797 Vector elmat_as_vec(elmat.Data(), elmat.Height()*elmat.Width());
4798
4799 ran_fe.Project(dom_shape_coeff, Trans, elmat_as_vec);
4800}
4801
4802void
4804 const FiniteElement &dom_fe,
4805 const FiniteElement &ran_fe,
4806 ElementTransformation &Trans,
4807 DenseMatrix &elmat)
4808{
4809 // Vector coefficient product with vector shape functions
4810 struct VCrossVShapeCoefficient : public MatrixCoefficient
4811 {
4813 const FiniteElement &fe;
4814 DenseMatrix vshape;
4815 Vector vc;
4816
4817 VCrossVShapeCoefficient(VectorCoefficient &vq, const FiniteElement &fe_)
4818 : MatrixCoefficient(fe_.GetDof(), vq.GetVDim()), VQ(vq), fe(fe_),
4819 vshape(height, width), vc(width)
4820 {
4821 MFEM_ASSERT(width == 3, "");
4822 }
4823
4824 void Eval(DenseMatrix &M, ElementTransformation &T,
4825 const IntegrationPoint &ip) override
4826 {
4827 M.SetSize(height, width);
4828 VQ.Eval(vc, T, ip);
4829 fe.CalcPhysVShape(T, vshape);
4830 for (int k = 0; k < height; k++)
4831 {
4832 M(k,0) = vc(1) * vshape(k,2) - vc(2) * vshape(k,1);
4833 M(k,1) = vc(2) * vshape(k,0) - vc(0) * vshape(k,2);
4834 M(k,2) = vc(0) * vshape(k,1) - vc(1) * vshape(k,0);
4835 }
4836 }
4837 };
4838
4839 VCrossVShapeCoefficient dom_shape_coeff(*VQ, dom_fe);
4840
4841 if (ran_fe.GetRangeType() == FiniteElement::SCALAR)
4842 {
4843 elmat.SetSize(ran_fe.GetDof()*VQ->GetVDim(),dom_fe.GetDof());
4844 }
4845 else
4846 {
4847 elmat.SetSize(ran_fe.GetDof(),dom_fe.GetDof());
4848 }
4849
4850 Vector elmat_as_vec(elmat.Data(), elmat.Height()*elmat.Width());
4851
4852 ran_fe.ProjectMatrixCoefficient(dom_shape_coeff, Trans, elmat_as_vec);
4853}
4854
4855
4856namespace internal
4857{
4858
4859// Vector shape functions dot product with a vector coefficient.
4860// Used in the implementation of class VectorInnerProductInterpolator below.
4861struct VDotVShapeCoefficient : public VectorCoefficient
4862{
4864 const FiniteElement &fe;
4865 DenseMatrix vshape;
4866 Vector vc;
4867
4868 VDotVShapeCoefficient(VectorCoefficient &vq, const FiniteElement &fe_)
4869 : VectorCoefficient(fe_.GetDof()), VQ(vq), fe(fe_),
4870 vshape(vdim, vq.GetVDim()), vc(vq.GetVDim()) { }
4871
4873 void Eval(Vector &V, ElementTransformation &T,
4874 const IntegrationPoint &ip) override
4875 {
4876 V.SetSize(vdim);
4877 VQ.Eval(vc, T, ip);
4878 fe.CalcPhysVShape(T, vshape);
4879 vshape.Mult(vc, V);
4880 }
4881};
4882
4883}
4884
4885void
4887 const FiniteElement &dom_fe,
4888 const FiniteElement &ran_fe,
4889 ElementTransformation &Trans,
4890 DenseMatrix &elmat)
4891{
4892 internal::VDotVShapeCoefficient dom_shape_coeff(*VQ, dom_fe);
4893
4894 elmat.SetSize(ran_fe.GetDof(),dom_fe.GetDof());
4895
4896 Vector elmat_as_vec(elmat.Data(), elmat.Height()*elmat.Width());
4897
4898 ran_fe.Project(dom_shape_coeff, Trans, elmat_as_vec);
4899}
4900
4901}
int Size() const
Return the logical size of the array.
Definition array.hpp:192
Abstract base class BilinearFormIntegrator.
virtual void AssembleFaceMatrix(const FiniteElement &el1, const FiniteElement &el2, FaceElementTransformations &Trans, DenseMatrix &elmat)
virtual void AssembleEABoundary(const FiniteElementSpace &fes, Vector &ea_data_bdr, const bool add=true)
virtual void AssemblePABoundaryFaces(const FiniteElementSpace &fes)
virtual void AssembleDiagonalPA(Vector &diag)
Assemble diagonal and add it to Vector diag.
void AssembleElementVector(const FiniteElement &el, ElementTransformation &Tr, const Vector &elfun, Vector &elvect) override
Perform the local action of the BilinearFormIntegrator. Note that the default implementation in the b...
virtual void AssemblePAInteriorFaces(const FiniteElementSpace &fes)
virtual void AssembleTraceFaceMatrix(int elem, const FiniteElement &trial_face_fe, const FiniteElement &test_fe, FaceElementTransformations &Trans, DenseMatrix &elmat)
void AssembleFaceVector(const FiniteElement &el1, const FiniteElement &el2, FaceElementTransformations &Tr, const Vector &elfun, Vector &elvect) override
Perform the local action of the BilinearFormIntegrator resulting from a face integral term....
virtual void AssembleEA(const FiniteElementSpace &fes, Vector &emat, const bool add=true)
Method defining element assembly.
virtual void AssembleElementMatrix(const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat)
Given a particular Finite Element computes the element matrix elmat.
virtual void AddMultTransposeMF(const Vector &x, Vector &y) const
void AssembleMF(const FiniteElementSpace &fes) override
Method defining matrix-free assembly.
void AssemblePA(const FiniteElementSpace &fes) override
Method defining partial assembly.
virtual void AssembleDiagonalPA_ADAt(const Vector &D, Vector &diag)
Assemble diagonal of ( is this integrator) and add it to diag.
virtual void AssembleEAInteriorFaces(const FiniteElementSpace &fes, Vector &ea_data_int, Vector &ea_data_ext, const bool add=true)
virtual void AddMultTransposePA(const Vector &x, Vector &y) const
Method for partially assembled transposed action.
void AddMultPA(const Vector &x, Vector &y) const override
Method for partially assembled action.
virtual void AssembleElementMatrix2(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans, DenseMatrix &elmat)
virtual void AssembleEABoundaryFaces(const FiniteElementSpace &fes, Vector &ea_data_bdr, const bool add=true)
virtual void AssembleDiagonalMF(Vector &diag)
Assemble diagonal and add it to Vector diag.
virtual void AddAbsMultPA(const Vector &x, Vector &y) const
virtual void AssemblePatchMatrix(const int patch, const FiniteElementSpace &fes, SparseMatrix *&smat)
virtual void AssemblePABoundary(const FiniteElementSpace &fes)
virtual void AddMultPAFaceNormalDerivatives(const Vector &x, const Vector &dxdn, Vector &y, Vector &dydn) const
Method for partially assembled action.
virtual void AddAbsMultTransposePA(const Vector &x, Vector &y) const
void AddMultMF(const Vector &x, Vector &y) const override
virtual void AddMultNURBSPA(const Vector &x, Vector &y) const
Method for partially assembled action on NURBS patches.
virtual void AssembleNURBSPA(const FiniteElementSpace &fes)
Method defining partial assembly on NURBS patches.
void AssembleFaceMatrix(const FiniteElement &el1, const FiniteElement &el2, FaceElementTransformations &Trans, DenseMatrix &elmat) override
Base class Coefficients that optionally depend on space and time. These are used by the BilinearFormI...
virtual real_t Eval(ElementTransformation &T, const IntegrationPoint &ip)=0
Evaluate the coefficient in the element described by T at the point ip.
static const IntegrationRule & GetRule(const FiniteElement &el, const ElementTransformation &Trans)
VectorCoefficient * Q
void AssembleElementMatrix(const FiniteElement &, ElementTransformation &, DenseMatrix &) override
Given a particular Finite Element computes the element matrix elmat.
void AssembleElementMatrix2(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
void AssembleElementMatrix(const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat) override
Given a particular Finite Element computes the element matrix elmat.
MatrixCoefficient * MQ
real_t ComputeFluxEnergy(const FiniteElement &fluxelem, ElementTransformation &Trans, Vector &flux, Vector *d_energy=NULL) override
Virtual method required for Zienkiewicz-Zhu type error estimators.
DiagonalMatrixCoefficient * DQ
void AssembleFaceMatrix(const FiniteElement &el1, const FiniteElement &el2, FaceElementTransformations &Trans, DenseMatrix &elmat) override
const IntegrationRule & GetRule(int order, FaceElementTransformations &T)
static void AssembleBlock(const int dim, const int row_ndofs, const int col_ndofs, const int row_offset, const int col_offset, const real_t jmatcoef, const Vector &col_nL, const Vector &col_nM, const Vector &row_shape, const Vector &col_shape, const Vector &col_dshape_dnM, const DenseMatrix &col_dshape, DenseMatrix &elmat, DenseMatrix &jmat)
void AssembleFaceMatrix(const FiniteElement &el1, const FiniteElement &el2, FaceElementTransformations &Trans, DenseMatrix &elmat) override
VectorCoefficient * u
static const IntegrationRule & GetRule(Geometry::Type geom, int order, const FaceElementTransformations &T)
const FaceGeometricFactors * geom
Not owned.
void AssembleFaceMatrix(const FiniteElement &el1, const FiniteElement &el2, FaceElementTransformations &Trans, DenseMatrix &elmat) override
Data type dense matrix using column-major storage.
Definition densemat.hpp:24
void AddMult_a(real_t a, const Vector &x, Vector &y) const
y += a * A.x
Definition densemat.cpp:241
void Mult(const real_t *x, real_t *y) const
Matrix vector multiplication.
Definition densemat.cpp:108
void MultTranspose(const real_t *x, real_t *y) const
Multiply a vector with the transpose matrix.
Definition densemat.cpp:158
void Transpose()
(*this) = (*this)^t
void GetColumnReference(int c, Vector &col)
Definition densemat.hpp:340
real_t InnerProduct(const real_t *x, const real_t *y) const
Compute y^t A x.
Definition densemat.cpp:281
real_t * Data() const
Returns the matrix data array. Warning: this method casts away constness.
Definition densemat.hpp:131
real_t * GetData() const
Returns the matrix data array. Warning: this method casts away constness.
Definition densemat.hpp:135
void AddMult(const Vector &x, Vector &y, const real_t a=1.0) const override
y += a * A.x
Definition densemat.cpp:194
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
Definition densemat.hpp:125
void Reset(real_t *d, int h, int w)
Change the data array and the size of the DenseMatrix.
Definition densemat.hpp:107
void ClearExternalData()
Definition densemat.hpp:112
void Invert()
Replaces the current matrix with its inverse.
Definition densemat.cpp:674
void AddMatrix(DenseMatrix &A, int ro, int co)
Perform (ro+i,co+j)+=A(i,j) for 0<=i.
void GradToCurl(DenseMatrix &curl)
void GetColumn(int c, Vector &col) const
void GradToVectorCurl2D(DenseMatrix &curl)
void GradToDiv(Vector &div)
void AssembleElementMatrix2(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
real_t ComputeFluxEnergy(const FiniteElement &fluxelem, ElementTransformation &Trans, Vector &flux, Vector *d_energy=NULL) override
Virtual method required for Zienkiewicz-Zhu type error estimators.
DiffusionIntegrator(const IntegrationRule *ir=nullptr)
Construct a diffusion integrator with coefficient Q = 1.
void AssembleElementMatrix(const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat) override
void AssembleElementVector(const FiniteElement &el, ElementTransformation &Tr, const Vector &elfun, Vector &elvect) override
Perform the local action of the BilinearFormIntegrator.
static const IntegrationRule & GetRule(const FiniteElement &trial_fe, const FiniteElement &test_fe, const bool stroud=false)
MatrixCoefficient * MQ
void AssembleElementMatrix2(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
void ComputeElementFlux(const FiniteElement &el, ElementTransformation &Trans, Vector &u, const FiniteElement &fluxelem, Vector &flux, bool with_coef=true, const IntegrationRule *ir=NULL) override
Virtual method required for Zienkiewicz-Zhu type error estimators.
VectorCoefficient * VQ
void AssembleElementMatrix(const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat) override
Given a particular Finite Element computes the element matrix elmat.
void AssembleElementMatrix2(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
ElasticityComponentIntegrator(ElasticityIntegrator &parent_, int i_, int j_)
Given an ElasticityIntegrator, create an integrator that represents the th component block.
void ComputeElementFlux(const FiniteElement &el, ElementTransformation &Trans, Vector &u, const FiniteElement &fluxelem, Vector &flux, bool with_coef=true, const IntegrationRule *ir=NULL) override
real_t ComputeFluxEnergy(const FiniteElement &fluxelem, ElementTransformation &Trans, Vector &flux, Vector *d_energy=NULL) override
void AssembleElementMatrix(const FiniteElement &el, ElementTransformation &Tr, DenseMatrix &elmat) override
Given a particular Finite Element computes the element matrix elmat.
virtual int Order() const =0
Return the order of the current element we are using for the transformation.
Geometry::Type GetGeometryType() const
Return the Geometry::Type of the reference element.
Definition eltrans.hpp:175
virtual int OrderGrad(const FiniteElement *fe) const =0
Return the order of .
const DenseMatrix & InverseJacobian()
Return the inverse of the Jacobian matrix of the transformation at the currently set IntegrationPoint...
Definition eltrans.hpp:158
const DenseMatrix & AdjugateJacobian()
Return the adjugate of the Jacobian matrix of the transformation at the currently set IntegrationPoin...
Definition eltrans.hpp:148
virtual int GetSpaceDim() const =0
Get the dimension of the target (physical) space.
real_t Weight()
Return the weight of the Jacobian matrix of the transformation at the currently set IntegrationPoint....
Definition eltrans.hpp:144
virtual int OrderJ() const =0
Return the order of the elements of the Jacobian of the transformation.
const DenseMatrix & Jacobian()
Return the Jacobian matrix of the transformation at the currently set IntegrationPoint,...
Definition eltrans.hpp:132
virtual int OrderW() const =0
Return the order of the determinant of the Jacobian (weight) of the transformation.
void SetIntPoint(const IntegrationPoint *ip)
Set the integration point ip that weights and Jacobians will be evaluated at.
Definition eltrans.hpp:106
A specialized ElementTransformation class representing a face and its two neighboring elements.
Definition eltrans.hpp:750
ElementTransformation * Elem2
Definition eltrans.hpp:791
ElementTransformation * Elem1
Definition eltrans.hpp:791
const IntegrationPoint & GetElement1IntPoint()
Get a const reference to the integration point in neighboring element 1 corresponding to the currentl...
Definition eltrans.hpp:846
ElementTransformation * Face
Definition eltrans.hpp:792
const IntegrationPoint & GetElement2IntPoint()
Get a const reference to the integration point in neighboring element 2 corresponding to the currentl...
Definition eltrans.hpp:856
IntegrationPointTransformation Loc1
Definition eltrans.hpp:793
void SetAllIntPoints(const IntegrationPoint *face_ip)
Set the integration point in the Face and the two neighboring elements, if present.
Definition eltrans.hpp:835
IntegrationPointTransformation Loc2
Definition eltrans.hpp:793
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:210
Abstract class for all finite elements.
Definition fe_base.hpp:294
virtual void CalcVShape(const IntegrationPoint &ip, DenseMatrix &shape) const
Evaluate the values of all shape functions of a vector finite element in reference space at the given...
Definition fe_base.cpp:50
virtual void ProjectMatrixCoefficient(MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const
Given a matrix coefficient and a transformation, compute an approximation ("projection") in the local...
Definition fe_base.cpp:154
int GetRangeDim() const
Returns the vector dimension for vector-valued finite elements, which is also the dimension of the in...
Definition fe_base.hpp:387
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...
Definition fe_base.hpp:414
void CalcPhysDShape(ElementTransformation &Trans, DenseMatrix &dshape) const
Evaluate the gradients of all shape functions of a scalar finite element in physical space at the poi...
Definition fe_base.cpp:202
virtual void CalcCurlShape(const IntegrationPoint &ip, DenseMatrix &curl_shape) const
Evaluate the curl of all shape functions of a vector finite element in reference space at the given p...
Definition fe_base.cpp:75
int GetDim() const
Returns the reference space dimension for the finite element.
Definition fe_base.hpp:381
int GetMapType() const
Returns the FiniteElement::MapType of the element describing how reference functions are mapped to ph...
Definition fe_base.hpp:436
int GetRangeType() const
Returns the FiniteElement::RangeType of the element, one of {SCALAR, VECTOR}.
Definition fe_base.hpp:427
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
Definition fe_base.hpp:476
virtual void CalcDShape(const IntegrationPoint &ip, DenseMatrix &dshape) const =0
Evaluate the gradients of all shape functions of a scalar finite element in reference space at the gi...
Geometry::Type GetGeomType() const
Returns the Geometry::Type of the reference element.
Definition fe_base.hpp:407
virtual void CalcDivShape(const IntegrationPoint &ip, Vector &divshape) const
Evaluate the divergence of all shape functions of a vector finite element in reference space at the g...
Definition fe_base.cpp:62
int Space() const
Returns the type of FunctionSpace on the element.
Definition fe_base.hpp:424
virtual void Project(Coefficient &coeff, ElementTransformation &Trans, Vector &dofs) const
Given a coefficient and a transformation, compute its projection (approximation) in the local finite ...
Definition fe_base.cpp:136
void CalcPhysVShape(ElementTransformation &Trans, DenseMatrix &shape) const
Equivalent to the CalcVShape() method with the same arguments.
Definition fe_base.hpp:524
int GetCurlDim() const
Definition fe_base.hpp:398
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const =0
Evaluate the values of all shape functions of a scalar finite element in reference space at the given...
virtual void ProjectCurl(const FiniteElement &fe, ElementTransformation &Trans, DenseMatrix &curl) const
Compute the discrete curl matrix from the given FiniteElement onto 'this' FiniteElement....
Definition fe_base.cpp:178
virtual void CalcPhysCurlShape(ElementTransformation &Trans, DenseMatrix &curl_shape) const
Evaluate the curl of all shape functions of a vector finite element in physical space at the point de...
Definition fe_base.cpp:81
int GetDof() const
Returns the number of degrees of freedom in the finite element.
Definition fe_base.hpp:410
void CalcPhysShape(ElementTransformation &Trans, Vector &shape) const
Evaluate the values of all shape functions of a scalar finite element in physical space at the point ...
Definition fe_base.cpp:192
@ Pk
Polynomials of order k.
Definition fe_base.hpp:280
@ Uk
Rational polynomials of order k.
Definition fe_base.hpp:283
@ rQk
Refined tensor products of polynomials of order k.
Definition fe_base.hpp:282
void AssembleElementMatrix2(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
static const IntegrationRule & GetRule(const FiniteElement &trial_fe, const FiniteElement &test_fe, const ElementTransformation &Trans)
void AssembleElementMatrix(const FiniteElement &, ElementTransformation &, DenseMatrix &) override
Given a particular Finite Element computes the element matrix elmat.
IsoparametricTransformation Transf
Definition eltrans.hpp:733
void Transform(const IntegrationPoint &, IntegrationPoint &)
Definition eltrans.cpp:587
Class for integration point with weight.
Definition intrules.hpp:35
Class for an integration rule - an Array of IntegrationPoint.
Definition intrules.hpp:96
int GetNPoints() const
Returns the number of the points in the integration rule.
Definition intrules.hpp:255
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
Definition intrules.hpp:258
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
virtual void SetIntRule(const IntegrationRule *ir)
Prescribe a fixed IntegrationRule to use, or set to null to let the integrator choose an appropriate ...
const IntegrationRule * GetIntegrationRule() const
Equivalent to GetIntRule, but retained for backward compatibility with applications.
const IntegrationRule * IntRule
void SetIntRule(const IntegrationRule *ir) override
Prescribe a fixed IntegrationRule to use, or set to null to let the integrator choose an appropriate ...
void AssembleElementMatrix(const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat) override
Given a particular Finite Element computes the element matrix elmat.
int OrderW() const override
Return the order of the determinant of the Jacobian (weight) of the transformation.
Definition eltrans.cpp:493
void SetIntRule(const IntegrationRule *ir) override
Prescribe a fixed IntegrationRule to use, or set to null to let the integrator choose an appropriate ...
void AssembleElementMatrix(const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat) override
Given a particular Finite Element computes the element matrix elmat.
void AssembleElementMatrix(const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat) override
static const IntegrationRule & GetRule(const FiniteElement &trial_fe, const FiniteElement &test_fe, const ElementTransformation &Trans, const bool stroud=false)
MassIntegrator(const IntegrationRule *ir=nullptr)
void AssembleElementMatrix2(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
int GetVDim() const
For backward compatibility get the width of the matrix.
virtual void Eval(DenseMatrix &K, ElementTransformation &T, const IntegrationPoint &ip)=0
Evaluate the matrix coefficient in the element described by T at the point ip, storing the result in ...
int GetWidth() const
Get the width of the matrix.
int GetHeight() const
Get the height of the matrix.
void AssembleElementMatrix2(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
virtual const char * FiniteElementTypeFailureMessage() const
virtual bool VerifyFiniteElementTypes(const FiniteElement &trial_fe, const FiniteElement &test_fe) const
void AssembleElementMatrix2(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
virtual void CalcTestShape(const FiniteElement &test_fe, ElementTransformation &Trans, Vector &shape)
virtual void CalcTrialShape(const FiniteElement &trial_fe, ElementTransformation &Trans, Vector &shape)
virtual int GetIntegrationOrder(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans)
virtual int GetIntegrationOrder(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans)
virtual const char * FiniteElementTypeFailureMessage() const
virtual bool VerifyFiniteElementTypes(const FiniteElement &trial_fe, const FiniteElement &test_fe) const
virtual void CalcVShape(const FiniteElement &vector_fe, ElementTransformation &Trans, DenseMatrix &shape_)
virtual int GetVDim(const FiniteElement &vector_fe)
void AssembleElementMatrix2(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
virtual void CalcShape(const FiniteElement &scalar_fe, ElementTransformation &Trans, Vector &shape_)
void AssembleElementMatrix2(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
virtual const char * FiniteElementTypeFailureMessage() const
VectorCoefficient * VQ
virtual int GetIntegrationOrder(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans)
virtual int GetTestVDim(const FiniteElement &test_fe)
MatrixCoefficient * MQ
virtual void CalcTestShape(const FiniteElement &test_fe, ElementTransformation &Trans, DenseMatrix &shape)
virtual int GetTrialVDim(const FiniteElement &trial_fe)
virtual bool VerifyFiniteElementTypes(const FiniteElement &trial_fe, const FiniteElement &test_fe) const
virtual void CalcTrialShape(const FiniteElement &trial_fe, ElementTransformation &Trans, DenseMatrix &shape)
DiagonalMatrixCoefficient * DQ
Class for standard nodal finite elements.
Definition fe_base.hpp:798
void AssembleElementMatrix2(const FiniteElement &dom_fe, const FiniteElement &ran_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
void AssembleTraceFaceMatrix(int ielem, const FiniteElement &trial_face_fe, const FiniteElement &test_fe, FaceElementTransformations &Trans, DenseMatrix &elmat) override
void AssembleFaceMatrix(const FiniteElement &trial_face_fe, const FiniteElement &test_fe1, const FiniteElement &test_fe2, FaceElementTransformations &Trans, DenseMatrix &elmat) override
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Definition operator.hpp:68
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
Definition operator.hpp:74
void AssembleElementMatrix2(const FiniteElement &nd_fe, const FiniteElement &l2_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
void AssembleElementMatrix2(const FiniteElement &dom_fe, const FiniteElement &ran_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
void AssembleElementMatrix2(const FiniteElement &dom_fe, const FiniteElement &ran_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
Data type sparse matrix.
Definition sparsemat.hpp:51
const IntegrationRule & Get(int GeomType, int Order)
Returns a Stroud integration rule for given GeomType and Order.
void AssembleEABoundaryFaces(const FiniteElementSpace &fes, Vector &ea_data_bdr, const bool add) override
void AddMultTransposePA(const Vector &x, Vector &y) const override
Method for partially assembled transposed action.
void SetIntRule(const IntegrationRule *ir) override
Prescribe a fixed IntegrationRule to use, or set to null to let the integrator choose an appropriate ...
void AddAbsMultTransposePA(const Vector &x, Vector &y) const override
void AssembleMF(const FiniteElementSpace &fes) override
Method defining matrix-free assembly.
void AddMultMF(const Vector &x, Vector &y) const override
void AssembleEAInteriorFaces(const FiniteElementSpace &fes, Vector &ea_data_int, Vector &ea_data_ext, const bool add) override
void AssembleEA(const FiniteElementSpace &fes, Vector &emat, const bool add) override
Method defining element assembly.
void AssembleDiagonalPA(Vector &diag) override
Assemble diagonal and add it to Vector diag.
void AddMultPA(const Vector &x, Vector &y) const override
Method for partially assembled action.
void AssemblePA(const FiniteElementSpace &fes) override
Method defining partial assembly.
void AssembleElementMatrix2(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
void AssembleFaceMatrix(const FiniteElement &el1, const FiniteElement &el2, FaceElementTransformations &Trans, DenseMatrix &elmat) override
void AssembleDiagonalMF(Vector &diag) override
Assemble diagonal and add it to Vector diag.
void AddAbsMultPA(const Vector &x, Vector &y) const override
void AssembleElementMatrix(const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat) override
Given a particular Finite Element computes the element matrix elmat.
void AssemblePABoundaryFaces(const FiniteElementSpace &fes) override
void AddMultTransposeMF(const Vector &x, Vector &y) const override
void AssemblePAInteriorFaces(const FiniteElementSpace &fes) override
void AssembleTraceFaceMatrix(int elem, const FiniteElement &trial_face_fe, const FiniteElement &test_fe, FaceElementTransformations &Trans, DenseMatrix &elmat)
void AssembleTraceFaceMatrix(int elem, const FiniteElement &trial_face_fe, const FiniteElement &test_fe, FaceElementTransformations &Trans, DenseMatrix &elmat)
void AssembleFaceMatrix(const FiniteElement &trial_face_fe, const FiniteElement &test_fe1, const FiniteElement &test_fe2, FaceElementTransformations &Trans, DenseMatrix &elmat) override
void AssembleFaceMatrix(const FiniteElement &el1, const FiniteElement &el2, FaceElementTransformations &Trans, DenseMatrix &elmat) override
void SetIntRule(const IntegrationRule *ir) override
Prescribe a fixed IntegrationRule to use, or set to null to let the integrator choose an appropriate ...
void AssembleElementMatrix(const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat) override
Given a particular Finite Element computes the element matrix elmat.
void AssembleElementMatrix2(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
Base class for vector Coefficients that optionally depend on time and space.
int GetVDim()
Returns dimension of the vector.
virtual void Eval(Vector &V, ElementTransformation &T, const IntegrationPoint &ip)=0
Evaluate the vector coefficient in the element described by T at the point ip, storing the result in ...
void AssembleElementMatrix2(const FiniteElement &nd_fe, const FiniteElement &rt_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
void AssembleElementMatrix(const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat) override
Assemble an element matrix.
real_t GetElementEnergy(const FiniteElement &el, ElementTransformation &Tr, const Vector &elfun) override
Compute element energy: .
void AssembleElementMatrix(const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat) override
Given a particular Finite Element computes the element matrix elmat.
void AssembleElementVector(const FiniteElement &el, ElementTransformation &Tr, const Vector &elfun, Vector &elvect) override
Perform the local action of the BilinearFormIntegrator. Note that the default implementation in the b...
static const IntegrationRule & GetRule(const FiniteElement &trial_fe, const FiniteElement &test_fe, const ElementTransformation &Trans)
void AssembleElementMatrix2(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
void AssembleElementMatrix2(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
void AssembleElementMatrix(const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat) override
Given a particular Finite Element computes the element matrix elmat.
void AssembleElementMatrix2(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
void AssembleElementMatrix2(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
void AssembleElementMatrix(const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat) override
Given a particular Finite Element computes the element matrix elmat.
void AssembleElementMatrix2(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
DiagonalMatrixCoefficient * DQ
void AssembleElementMatrix2(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
void AssembleElementMatrix2(const FiniteElement &rt_fe, const FiniteElement &l2_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
VectorCoefficient * VQ
void AssembleElementMatrix2(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
MatrixCoefficient * MQ
void AssembleElementMatrix(const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat) override
Given a particular Finite Element computes the element matrix elmat.
void AssembleElementMatrix2(const FiniteElement &dom_fe, const FiniteElement &ran_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
Vector data type.
Definition vector.hpp:82
void Neg()
(*this) = -(*this)
Definition vector.cpp:376
void SetDataAndSize(real_t *d, int s)
Set the Vector data and size.
Definition vector.hpp:191
Vector & Set(const real_t a, const Vector &x)
(*this) = a * x
Definition vector.cpp:341
int Size() const
Returns the size of the vector.
Definition vector.hpp:234
void SetSize(int s)
Resize the vector to size s.
Definition vector.hpp:633
void NewDataAndSize(real_t *d, int s)
Set the Vector data and size, deleting the old data, if owned.
Definition vector.hpp:197
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
Definition vector.hpp:243
int dimc
Definition maxwell.cpp:123
int dim
Definition ex24.cpp:53
real_t b
Definition lissajous.cpp:42
real_t a
Definition lissajous.cpp:41
StroudIntegrationRules StroudIntRules
A global object with all Stroud integration rules (defined in intrules.cpp)
void CalcOrtho(const DenseMatrix &J, Vector &n)
void AddMult_a_ABt(real_t a, const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &ABt)
ABt += a * A * B^t.
real_t u(const Vector &xvec)
Definition lor_mms.hpp:22
void mfem_error(const char *msg)
Definition error.cpp:154
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
Definition table.cpp:505
void MultVWt(const Vector &v, const Vector &w, DenseMatrix &VWt)
void add(const Vector &v1, const Vector &v2, Vector &v)
Definition vector.cpp:414
void MultABt(const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &ABt)
Multiply a matrix A with the transpose of a matrix B: A*Bt.
void CalcInverse(const DenseMatrix &a, DenseMatrix &inva)
void AddMult_a_VWt(const real_t a, const Vector &v, const Vector &w, DenseMatrix &VWt)
VWt += a * v w^t.
void AddMult_a_VVt(const real_t a, const Vector &v, DenseMatrix &VVt)
VVt += a * v v^t.
void CalcAdjugate(const DenseMatrix &a, DenseMatrix &adja)
void AddMultVWt(const Vector &v, const Vector &w, DenseMatrix &VWt)
VWt += v w^t.
void MultVVt(const Vector &v, DenseMatrix &vvt)
Make a matrix from a vector V.Vt.
void AddMultABt(const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &ABt)
ABt += A * B^t.
void AddMult_a_AAt(real_t a, const DenseMatrix &A, DenseMatrix &AAt)
AAt += a * A * A^t.
void MultAAt(const DenseMatrix &a, DenseMatrix &aat)
Calculate the matrix A.At.
void AddMultADBt(const DenseMatrix &A, const Vector &D, const DenseMatrix &B, DenseMatrix &ADBt)
ADBt = A D B^t, where D is diagonal.
ComplexDenseMatrix * MultAtB(const ComplexDenseMatrix &A, const ComplexDenseMatrix &B)
Multiply the complex conjugate transpose of a matrix A with a matrix B. A^H*B.
float real_t
Definition config.hpp:46
void Mult_a_AAt(real_t a, const DenseMatrix &A, DenseMatrix &AAt)
AAt = a * A * A^t.
IntegrationRules RefinedIntRules(1, Quadrature1D::GaussLegendre)
A global object with all refined integration rules.
Definition intrules.hpp:552
void AddMultADAt(const DenseMatrix &A, const Vector &D, DenseMatrix &ADAt)
ADAt += A D A^t, where D is diagonal.
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
Definition intrules.hpp:549
STL namespace.
real_t p(const Vector &x, real_t t)
MFEM_HOST_DEVICE real_t norm(const Complex &z)