MFEM v4.9.0
Finite element discretization library
Loading...
Searching...
No Matches
bilininteg.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, 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{
1350 int order;
1351 if (trial_fe.Space() == FunctionSpace::Pk)
1352 {
1353 order = trial_fe.GetOrder() + test_fe.GetOrder() - 2;
1354 }
1355 else
1356 {
1357 // order = 2*el.GetOrder() - 2; // <-- this seems to work fine too
1358 order = trial_fe.GetOrder() + test_fe.GetOrder() + trial_fe.GetDim() - 1;
1359 }
1360
1361 if (trial_fe.Space() == FunctionSpace::rQk)
1362 {
1363 return RefinedIntRules.Get(trial_fe.GetGeomType(), order);
1364 }
1365 return IntRules.Get(trial_fe.GetGeomType(), order);
1366}
1367
1369 : BilinearFormIntegrator(ir), Q(nullptr), maps(nullptr), geom(nullptr)
1370{
1371 static Kernels kernels;
1372}
1373
1375 : MassIntegrator(ir)
1376{
1377 Q = &q;
1378}
1379
1381( const FiniteElement &el, ElementTransformation &Trans,
1382 DenseMatrix &elmat )
1383{
1384 int nd = el.GetDof();
1385 // int dim = el.GetDim();
1386 real_t w;
1387
1388#ifdef MFEM_THREAD_SAFE
1389 Vector shape;
1390#endif
1391 elmat.SetSize(nd);
1392 shape.SetSize(nd);
1393
1394
1395 const IntegrationRule *ir = GetIntegrationRule(el, Trans);
1396 elmat = 0.0;
1397 for (int i = 0; i < ir->GetNPoints(); i++)
1398 {
1399 const IntegrationPoint &ip = ir->IntPoint(i);
1400 Trans.SetIntPoint (&ip);
1401
1402 el.CalcPhysShape(Trans, shape);
1403
1404 w = Trans.Weight() * ip.weight;
1405 if (Q)
1406 {
1407 w *= Q -> Eval(Trans, ip);
1408 }
1409
1410 AddMult_a_VVt(w, shape, elmat);
1411 }
1412}
1413
1415 const FiniteElement &trial_fe, const FiniteElement &test_fe,
1416 ElementTransformation &Trans, DenseMatrix &elmat)
1417{
1418 int tr_nd = trial_fe.GetDof();
1419 int te_nd = test_fe.GetDof();
1420 real_t w;
1421
1422#ifdef MFEM_THREAD_SAFE
1424#endif
1425 elmat.SetSize(te_nd, tr_nd);
1426 shape.SetSize(tr_nd);
1427 te_shape.SetSize(te_nd);
1428
1429 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
1430 elmat = 0.0;
1431 for (int i = 0; i < ir->GetNPoints(); i++)
1432 {
1433 const IntegrationPoint &ip = ir->IntPoint(i);
1434 Trans.SetIntPoint (&ip);
1435
1436 trial_fe.CalcPhysShape(Trans, shape);
1437 test_fe.CalcPhysShape(Trans, te_shape);
1438
1439 w = Trans.Weight() * ip.weight;
1440 if (Q)
1441 {
1442 w *= Q -> Eval(Trans, ip);
1443 }
1444
1445 te_shape *= w;
1446 AddMultVWt(te_shape, shape, elmat);
1447 }
1448}
1449
1451 const FiniteElement &test_fe,
1452 const ElementTransformation &Trans)
1453{
1454 // int order = trial_fe.GetOrder() + test_fe.GetOrder();
1455 const int order = trial_fe.GetOrder() + test_fe.GetOrder() + Trans.OrderW();
1456
1457 if (trial_fe.Space() == FunctionSpace::rQk)
1458 {
1459 return RefinedIntRules.Get(trial_fe.GetGeomType(), order);
1460 }
1461 return IntRules.Get(trial_fe.GetGeomType(), order);
1462}
1463
1464
1466 const FiniteElement &el1, const FiniteElement &el2,
1468{
1469 MFEM_ASSERT(Trans.Elem2No < 0,
1470 "support for interior faces is not implemented");
1471
1472 int nd1 = el1.GetDof();
1473 real_t w;
1474
1475#ifdef MFEM_THREAD_SAFE
1476 Vector shape;
1477#endif
1478 elmat.SetSize(nd1);
1479 shape.SetSize(nd1);
1480
1481 const IntegrationRule *ir = IntRule;
1482 if (ir == NULL)
1483 {
1484 int order = 2 * el1.GetOrder();
1485
1486 ir = &IntRules.Get(Trans.GetGeometryType(), order);
1487 }
1488
1489 elmat = 0.0;
1490 for (int i = 0; i < ir->GetNPoints(); i++)
1491 {
1492 const IntegrationPoint &ip = ir->IntPoint(i);
1493
1494 // Set the integration point in the face and the neighboring element
1495 Trans.SetAllIntPoints(&ip);
1496
1497 el1.CalcPhysShape(*Trans.Elem1, shape);
1498
1499 w = Trans.Weight() * ip.weight;
1500 if (Q)
1501 {
1502 w *= Q -> Eval(Trans, ip);
1503 }
1504
1505 AddMult_a_VVt(w, shape, elmat);
1506 }
1507}
1508
1510 const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat)
1511{
1512 int nd = el.GetDof();
1513 dim = el.GetDim();
1514
1515#ifdef MFEM_THREAD_SAFE
1516 DenseMatrix dshape, adjJ, Q_ir;
1517 Vector shape, vec2, BdFidxT;
1518#endif
1519 elmat.SetSize(nd);
1520 dshape.SetSize(nd,dim);
1521 adjJ.SetSize(dim);
1522 shape.SetSize(nd);
1523 vec2.SetSize(dim);
1524 BdFidxT.SetSize(nd);
1525
1526 Vector vec1;
1527
1528
1529 const IntegrationRule *ir = GetIntegrationRule(el, Trans);
1530 if (ir == NULL)
1531 {
1532 int order = Trans.OrderGrad(&el) + Trans.Order() + el.GetOrder();
1533 ir = &IntRules.Get(el.GetGeomType(), order);
1534 }
1535
1536 Q->Eval(Q_ir, Trans, *ir);
1537
1538 elmat = 0.0;
1539 for (int i = 0; i < ir->GetNPoints(); i++)
1540 {
1541 const IntegrationPoint &ip = ir->IntPoint(i);
1542 el.CalcDShape(ip, dshape);
1543 el.CalcShape(ip, shape);
1544
1545 Trans.SetIntPoint(&ip);
1546 CalcAdjugate(Trans.Jacobian(), adjJ);
1547 Q_ir.GetColumnReference(i, vec1);
1548 vec1 *= alpha * ip.weight;
1549
1550 adjJ.Mult(vec1, vec2);
1551 dshape.Mult(vec2, BdFidxT);
1552
1553 AddMultVWt(shape, BdFidxT, elmat);
1554 }
1555}
1556
1557
1559 const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat)
1560{
1561 int nd = el.GetDof();
1562 int dim = el.GetDim();
1563
1564 elmat.SetSize(nd);
1565 dshape.SetSize(nd,dim);
1566 adjJ.SetSize(dim);
1567 shape.SetSize(nd);
1568 grad.SetSize(nd,dim);
1569
1570 const IntegrationRule *ir = GetIntegrationRule(el, Trans);
1571 if (ir == NULL)
1572 {
1573 int order = Trans.OrderGrad(&el) + el.GetOrder();
1574 ir = &IntRules.Get(el.GetGeomType(), order);
1575 }
1576
1577 Q->Eval(Q_nodal, Trans, el.GetNodes()); // sets the size of Q_nodal
1578
1579 elmat = 0.0;
1580 for (int i = 0; i < ir->GetNPoints(); i++)
1581 {
1582 const IntegrationPoint &ip = ir->IntPoint(i);
1583 el.CalcDShape(ip, dshape);
1584 el.CalcShape(ip, shape);
1585
1586 Trans.SetIntPoint(&ip);
1587 CalcAdjugate(Trans.Jacobian(), adjJ);
1588
1589 Mult(dshape, adjJ, grad);
1590
1591 real_t w = alpha * ip.weight;
1592
1593 // elmat(k,l) += \sum_s w*shape(k)*Q_nodal(s,k)*grad(l,s)
1594 for (int k = 0; k < nd; k++)
1595 {
1596 real_t wsk = w*shape(k);
1597 for (int l = 0; l < nd; l++)
1598 {
1599 real_t a = 0.0;
1600 for (int s = 0; s < dim; s++)
1601 {
1602 a += Q_nodal(s,k)*grad(l,s);
1603 }
1604 elmat(k,l) += wsk*a;
1605 }
1606 }
1607 }
1608}
1609
1611 const FiniteElement &trial_fe, const FiniteElement &test_fe,
1612 const ElementTransformation &Trans)
1613{
1614 int order = Trans.OrderGrad(&trial_fe) + Trans.Order() + test_fe.GetOrder();
1615
1616 return IntRules.Get(trial_fe.GetGeomType(), order);
1617}
1618
1620 const FiniteElement &el, const ElementTransformation &Trans)
1621{
1622 return GetRule(el,el,Trans);
1623}
1624
1626( const FiniteElement &el, ElementTransformation &Trans,
1627 DenseMatrix &elmat )
1628{
1629 int nd = el.GetDof();
1630 int spaceDim = Trans.GetSpaceDim();
1631
1632 real_t norm;
1633
1634 // If vdim is not set, set it to the space dimension
1635 vdim = (vdim == -1) ? spaceDim : vdim;
1636
1637 elmat.SetSize(nd*vdim);
1638 shape.SetSize(nd);
1639 partelmat.SetSize(nd);
1640 if (VQ)
1641 {
1642 vec.SetSize(vdim);
1643 }
1644 else if (MQ)
1645 {
1646 mcoeff.SetSize(vdim);
1647 }
1648
1649
1650 const IntegrationRule *ir = GetIntegrationRule(el, Trans);
1651 if (ir == NULL)
1652 {
1653 int order = 2 * el.GetOrder() + Trans.OrderW() + Q_order;
1654
1655 if (el.Space() == FunctionSpace::rQk)
1656 {
1657 ir = &RefinedIntRules.Get(el.GetGeomType(), order);
1658 }
1659 else
1660 {
1661 ir = &IntRules.Get(el.GetGeomType(), order);
1662 }
1663 }
1664
1665 elmat = 0.0;
1666 for (int s = 0; s < ir->GetNPoints(); s++)
1667 {
1668 const IntegrationPoint &ip = ir->IntPoint(s);
1669 Trans.SetIntPoint (&ip);
1670 el.CalcPhysShape(Trans, shape);
1671
1672 norm = ip.weight * Trans.Weight();
1673
1674 MultVVt(shape, partelmat);
1675
1676 if (VQ)
1677 {
1678 VQ->Eval(vec, Trans, ip);
1679 for (int k = 0; k < vdim; k++)
1680 {
1681 elmat.AddMatrix(norm*vec(k), partelmat, nd*k, nd*k);
1682 }
1683 }
1684 else if (MQ)
1685 {
1686 MQ->Eval(mcoeff, Trans, ip);
1687 for (int i = 0; i < vdim; i++)
1688 for (int j = 0; j < vdim; j++)
1689 {
1690 elmat.AddMatrix(norm*mcoeff(i,j), partelmat, nd*i, nd*j);
1691 }
1692 }
1693 else
1694 {
1695 if (Q)
1696 {
1697 norm *= Q->Eval(Trans, ip);
1698 }
1699 partelmat *= norm;
1700 for (int k = 0; k < vdim; k++)
1701 {
1702 elmat.AddMatrix(partelmat, nd*k, nd*k);
1703 }
1704 }
1705 }
1706}
1707
1709 const FiniteElement &trial_fe, const FiniteElement &test_fe,
1710 ElementTransformation &Trans, DenseMatrix &elmat)
1711{
1712 int tr_nd = trial_fe.GetDof();
1713 int te_nd = test_fe.GetDof();
1714
1715 real_t norm;
1716
1717 // If vdim is not set, set it to the space dimension
1718 vdim = (vdim == -1) ? Trans.GetSpaceDim() : vdim;
1719
1720 elmat.SetSize(te_nd*vdim, tr_nd*vdim);
1721 shape.SetSize(tr_nd);
1722 te_shape.SetSize(te_nd);
1723 partelmat.SetSize(te_nd, tr_nd);
1724 if (VQ)
1725 {
1726 vec.SetSize(vdim);
1727 }
1728 else if (MQ)
1729 {
1730 mcoeff.SetSize(vdim);
1731 }
1732
1733
1734 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
1735 if (ir == NULL)
1736 {
1737 int order = (trial_fe.GetOrder() + test_fe.GetOrder() +
1738 Trans.OrderW() + Q_order);
1739
1740 if (trial_fe.Space() == FunctionSpace::rQk)
1741 {
1742 ir = &RefinedIntRules.Get(trial_fe.GetGeomType(), order);
1743 }
1744 else
1745 {
1746 ir = &IntRules.Get(trial_fe.GetGeomType(), order);
1747 }
1748 }
1749
1750 elmat = 0.0;
1751 for (int s = 0; s < ir->GetNPoints(); s++)
1752 {
1753 const IntegrationPoint &ip = ir->IntPoint(s);
1754 Trans.SetIntPoint(&ip);
1755 trial_fe.CalcPhysShape(Trans, shape);
1756 test_fe.CalcPhysShape(Trans, te_shape);
1757
1758 norm = ip.weight * Trans.Weight();
1759
1760 MultVWt(te_shape, shape, partelmat);
1761
1762 if (VQ)
1763 {
1764 VQ->Eval(vec, Trans, ip);
1765 for (int k = 0; k < vdim; k++)
1766 {
1767 elmat.AddMatrix(norm*vec(k), partelmat, te_nd*k, tr_nd*k);
1768 }
1769 }
1770 else if (MQ)
1771 {
1772 MQ->Eval(mcoeff, Trans, ip);
1773 for (int i = 0; i < vdim; i++)
1774 for (int j = 0; j < vdim; j++)
1775 {
1776 elmat.AddMatrix(norm*mcoeff(i,j), partelmat, te_nd*i, tr_nd*j);
1777 }
1778 }
1779 else
1780 {
1781 if (Q)
1782 {
1783 norm *= Q->Eval(Trans, ip);
1784 }
1785 partelmat *= norm;
1786 for (int k = 0; k < vdim; k++)
1787 {
1788 elmat.AddMatrix(partelmat, te_nd*k, tr_nd*k);
1789 }
1790 }
1791 }
1792}
1793
1795 const FiniteElement &trial_fe, const FiniteElement &test_fe,
1796 ElementTransformation &Trans, DenseMatrix &elmat)
1797{
1798 int trial_nd = trial_fe.GetDof(), test_nd = test_fe.GetDof(), i;
1799
1800#ifdef MFEM_THREAD_SAFE
1801 Vector divshape(trial_nd), shape(test_nd);
1802#else
1803 divshape.SetSize(trial_nd);
1804 shape.SetSize(test_nd);
1805#endif
1806
1807 elmat.SetSize(test_nd, trial_nd);
1808
1809 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
1810 if (ir == NULL)
1811 {
1812 int order = trial_fe.GetOrder() + test_fe.GetOrder() - 1; // <--
1813 ir = &IntRules.Get(trial_fe.GetGeomType(), order);
1814 }
1815
1816 elmat = 0.0;
1817 for (i = 0; i < ir->GetNPoints(); i++)
1818 {
1819 const IntegrationPoint &ip = ir->IntPoint(i);
1820 trial_fe.CalcDivShape(ip, divshape);
1821 Trans.SetIntPoint(&ip);
1822 test_fe.CalcPhysShape(Trans, shape);
1823 real_t w = ip.weight;
1824 if (Q)
1825 {
1826 Trans.SetIntPoint(&ip);
1827 w *= Q->Eval(Trans, ip);
1828 }
1829 shape *= w;
1830 AddMultVWt(shape, divshape, elmat);
1831 }
1832}
1833
1835 const FiniteElement &trial_fe, const FiniteElement &test_fe,
1836 ElementTransformation &Trans, DenseMatrix &elmat)
1837{
1838 int trial_nd = trial_fe.GetDof(), test_nd = test_fe.GetDof(), i;
1839 int dim = trial_fe.GetDim();
1840
1841 MFEM_ASSERT(test_fe.GetRangeType() == mfem::FiniteElement::SCALAR &&
1844 "Trial space must be H(Curl) and test space must be H_1");
1845
1846#ifdef MFEM_THREAD_SAFE
1847 DenseMatrix dshape(test_nd, dim);
1848 DenseMatrix dshapedxt(test_nd, dim);
1849 DenseMatrix vshape(trial_nd, dim);
1850 DenseMatrix invdfdx(dim);
1851#else
1852 dshape.SetSize(test_nd, dim);
1853 dshapedxt.SetSize(test_nd, dim);
1854 vshape.SetSize(trial_nd, dim);
1855 invdfdx.SetSize(dim);
1856#endif
1857
1858 elmat.SetSize(test_nd, trial_nd);
1859
1860 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
1861 if (ir == NULL)
1862 {
1863 // The integrand on the reference element is:
1864 // -( Q/det(J) ) u_hat^T adj(J) adj(J)^T grad_hat(v_hat).
1865 //
1866 // For Trans in (P_k)^d, v_hat in P_l, u_hat in ND_m, and dim=sdim=d>=1
1867 // - J_{ij} is in P_{k-1}, so adj(J)_{ij} is in P_{(d-1)*(k-1)}
1868 // - so adj(J)^T grad_hat(v_hat) is in (P_{(d-1)*(k-1)+(l-1)})^d
1869 // - u_hat is in (P_m)^d
1870 // - adj(J)^T u_hat is in (P_{(d-1)*(k-1)+m})^d
1871 // - and u_hat^T adj(J) adj(J)^T grad_hat(v_hat) is in P_n with
1872 // n = 2*(d-1)*(k-1)+(l-1)+m
1873 //
1874 // For Trans in (Q_k)^d, v_hat in Q_l, u_hat in ND_m, and dim=sdim=d>1
1875 // - J_{i*}, J's i-th row, is in ( Q_{k-1,k,k}, Q_{k,k-1,k}, Q_{k,k,k-1} )
1876 // - adj(J)_{*j} is in ( Q_{s,s-1,s-1}, Q_{s-1,s,s-1}, Q_{s-1,s-1,s} )
1877 // with s = (d-1)*k
1878 // - adj(J)^T grad_hat(v_hat) is in Q_{(d-1)*k+(l-1)}
1879 // - u_hat is in ( Q_{m-1,m,m}, Q_{m,m-1,m}, Q_{m,m,m-1} )
1880 // - adj(J)^T u_hat is in Q_{(d-1)*k+(m-1)}
1881 // - and u_hat^T adj(J) adj(J)^T grad_hat(v_hat) is in Q_n with
1882 // n = 2*(d-1)*k+(l-1)+(m-1)
1883 //
1884 // In the next formula we use the expressions for n with k=1, which means
1885 // that the term Q/det(J) is disregarded:
1886 int ir_order = (trial_fe.Space() == FunctionSpace::Pk) ?
1887 (trial_fe.GetOrder() + test_fe.GetOrder() - 1) :
1888 (trial_fe.GetOrder() + test_fe.GetOrder() + 2*(dim-2));
1889 ir = &IntRules.Get(trial_fe.GetGeomType(), ir_order);
1890 }
1891
1892 elmat = 0.0;
1893 for (i = 0; i < ir->GetNPoints(); i++)
1894 {
1895 const IntegrationPoint &ip = ir->IntPoint(i);
1896 test_fe.CalcDShape(ip, dshape);
1897
1898 Trans.SetIntPoint(&ip);
1899 CalcAdjugate(Trans.Jacobian(), invdfdx);
1900 Mult(dshape, invdfdx, dshapedxt);
1901
1902 trial_fe.CalcVShape(Trans, vshape);
1903
1904 real_t w = ip.weight;
1905
1906 if (Q)
1907 {
1908 w *= Q->Eval(Trans, ip);
1909 }
1910 dshapedxt *= -w;
1911
1912 AddMultABt(dshapedxt, vshape, elmat);
1913 }
1914}
1915
1917 const FiniteElement &trial_fe, const FiniteElement &test_fe,
1918 ElementTransformation &Trans, DenseMatrix &elmat)
1919{
1920 int trial_nd = trial_fe.GetDof(), test_nd = test_fe.GetDof(), i;
1921 int dim = trial_fe.GetDim();
1922 int dimc = (dim == 3) ? 3 : 1;
1923
1924 MFEM_ASSERT(trial_fe.GetMapType() == mfem::FiniteElement::H_CURL ||
1926 "At least one of the finite elements must be in H(Curl)");
1927
1928 int curl_nd, vec_nd;
1929 if ( trial_fe.GetMapType() == mfem::FiniteElement::H_CURL )
1930 {
1931 curl_nd = trial_nd;
1932 vec_nd = test_nd;
1933 }
1934 else
1935 {
1936 curl_nd = test_nd;
1937 vec_nd = trial_nd;
1938 }
1939
1940#ifdef MFEM_THREAD_SAFE
1941 DenseMatrix curlshapeTrial(curl_nd, dimc);
1942 DenseMatrix curlshapeTrial_dFT(curl_nd, dimc);
1943 DenseMatrix vshapeTest(vec_nd, dimc);
1944#else
1945 curlshapeTrial.SetSize(curl_nd, dimc);
1946 curlshapeTrial_dFT.SetSize(curl_nd, dimc);
1947 vshapeTest.SetSize(vec_nd, dimc);
1948#endif
1949 Vector shapeTest(vshapeTest.GetData(), vec_nd);
1950
1951 elmat.SetSize(test_nd, trial_nd);
1952
1953 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
1954 if (ir == NULL)
1955 {
1956 int order = trial_fe.GetOrder() + test_fe.GetOrder() - 1; // <--
1957 ir = &IntRules.Get(trial_fe.GetGeomType(), order);
1958 }
1959
1960 elmat = 0.0;
1961 for (i = 0; i < ir->GetNPoints(); i++)
1962 {
1963 const IntegrationPoint &ip = ir->IntPoint(i);
1964
1965 Trans.SetIntPoint(&ip);
1966 if (dim == 3)
1967 {
1968 if ( trial_fe.GetMapType() == mfem::FiniteElement::H_CURL )
1969 {
1970 trial_fe.CalcCurlShape(ip, curlshapeTrial);
1971 test_fe.CalcVShape(Trans, vshapeTest);
1972 }
1973 else
1974 {
1975 test_fe.CalcCurlShape(ip, curlshapeTrial);
1976 trial_fe.CalcVShape(Trans, vshapeTest);
1977 }
1978 MultABt(curlshapeTrial, Trans.Jacobian(), curlshapeTrial_dFT);
1979 }
1980 else
1981 {
1982 if ( trial_fe.GetMapType() == mfem::FiniteElement::H_CURL )
1983 {
1984 trial_fe.CalcCurlShape(ip, curlshapeTrial_dFT);
1985 test_fe.CalcPhysShape(Trans, shapeTest);
1986 }
1987 else
1988 {
1989 test_fe.CalcCurlShape(ip, curlshapeTrial_dFT);
1990 trial_fe.CalcPhysShape(Trans, shapeTest);
1991 }
1992 }
1993
1994 real_t w = ip.weight;
1995
1996 if (Q)
1997 {
1998 w *= Q->Eval(Trans, ip);
1999 }
2000 // Note: shapeTest points to the same data as vshapeTest
2001 vshapeTest *= w;
2002 if ( trial_fe.GetMapType() == mfem::FiniteElement::H_CURL )
2003 {
2004 AddMultABt(vshapeTest, curlshapeTrial_dFT, elmat);
2005 }
2006 else
2007 {
2008 AddMultABt(curlshapeTrial_dFT, vshapeTest, elmat);
2009 }
2010 }
2011}
2012
2014 const FiniteElement &el, ElementTransformation &Tr,
2015 DenseMatrix &elmat)
2016{
2017 int nd = el.GetDof();
2018 real_t w;
2019
2020#ifdef MFEM_THREAD_SAFE
2021 Vector shape;
2022#endif
2023 elmat.SetSize(nd);
2024 shape.SetSize(nd);
2025
2026 const IntegrationRule *ir = IntRule;
2027 if (ir == NULL)
2028 {
2029 int intorder = 2*el.GetOrder() + Tr.OrderW(); // <----------
2030 ir = &IntRules.Get(el.GetGeomType(), intorder);
2031 }
2032
2033 elmat = 0.0;
2034 for (int i = 0; i < ir->GetNPoints(); i++)
2035 {
2036 const IntegrationPoint &ip = ir->IntPoint(i);
2037 el.CalcShape(ip, shape);
2038
2039 Tr.SetIntPoint (&ip);
2040 w = ip.weight / Tr.Weight();
2041
2042 if (Q)
2043 {
2044 w *= Q->Eval(Tr, ip);
2045 }
2046
2047 AddMult_a_VVt(w, shape, elmat);
2048 }
2049}
2050
2052 const FiniteElement &trial_fe,
2053 const FiniteElement &test_fe,
2055 DenseMatrix &elmat)
2056{
2057 int tr_nd = trial_fe.GetDof();
2058 int te_nd = test_fe.GetDof();
2059 real_t w;
2060
2061#ifdef MFEM_THREAD_SAFE
2062 Vector shape, te_shape;
2063#endif
2064 elmat.SetSize(te_nd, tr_nd);
2065 shape.SetSize(tr_nd);
2066 te_shape.SetSize(te_nd);
2067
2068 const IntegrationRule *ir = IntRule;
2069 if (ir == NULL)
2070 {
2071 int order = trial_fe.GetOrder() + test_fe.GetOrder() + Tr.OrderW();
2072
2073 ir = &IntRules.Get(trial_fe.GetGeomType(), order);
2074 }
2075
2076 elmat = 0.0;
2077 for (int i = 0; i < ir->GetNPoints(); i++)
2078 {
2079 const IntegrationPoint &ip = ir->IntPoint(i);
2080 trial_fe.CalcShape(ip, shape);
2081 test_fe.CalcShape(ip, te_shape);
2082
2083 Tr.SetIntPoint (&ip);
2084 w = ip.weight / Tr.Weight();
2085
2086 if (Q)
2087 {
2088 w *= Q->Eval(Tr, ip);
2089 }
2090
2091 te_shape *= w;
2092 AddMultVWt(te_shape, shape, elmat);
2093 }
2094}
2095
2097 const FiniteElement &trial_fe,
2098 const FiniteElement &test_fe,
2099 ElementTransformation &Trans,
2100 DenseMatrix &elmat)
2101{
2102 int dim = trial_fe.GetDim();
2103 int trial_nd = trial_fe.GetDof();
2104 int test_nd = test_fe.GetDof();
2105 int spaceDim = Trans.GetSpaceDim();
2106
2107 int i, l;
2108 real_t det;
2109
2110 elmat.SetSize (test_nd,trial_nd);
2111 dshape.SetSize (trial_nd,dim);
2112 dshapedxt.SetSize(trial_nd, spaceDim);
2113 dshapedxi.SetSize(trial_nd);
2114 invdfdx.SetSize(dim, spaceDim);
2115 shape.SetSize (test_nd);
2116
2117 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
2118 if (ir == NULL)
2119 {
2120 int order;
2121 if (trial_fe.Space() == FunctionSpace::Pk)
2122 {
2123 order = trial_fe.GetOrder() + test_fe.GetOrder() - 1;
2124 }
2125 else
2126 {
2127 order = trial_fe.GetOrder() + test_fe.GetOrder() + dim;
2128 }
2129
2130 if (trial_fe.Space() == FunctionSpace::rQk)
2131 {
2132 ir = &RefinedIntRules.Get(trial_fe.GetGeomType(), order);
2133 }
2134 else
2135 {
2136 ir = &IntRules.Get(trial_fe.GetGeomType(), order);
2137 }
2138 }
2139
2140 elmat = 0.0;
2141 for (i = 0; i < ir->GetNPoints(); i++)
2142 {
2143 const IntegrationPoint &ip = ir->IntPoint(i);
2144
2145 trial_fe.CalcDShape(ip, dshape);
2146
2147 Trans.SetIntPoint (&ip);
2148 CalcInverse (Trans.Jacobian(), invdfdx);
2149 det = Trans.Weight();
2150 Mult (dshape, invdfdx, dshapedxt);
2151
2152 test_fe.CalcPhysShape(Trans, shape);
2153
2154 for (l = 0; l < trial_nd; l++)
2155 {
2156 dshapedxi(l) = dshapedxt(l,xi);
2157 }
2158
2159 shape *= Q->Eval(Trans,ip) * det * ip.weight;
2160 AddMultVWt (shape, dshapedxi, elmat);
2161 }
2162}
2163
2165( const FiniteElement &el, ElementTransformation &Trans,
2166 DenseMatrix &elmat )
2167{
2168 int nd = el.GetDof();
2169 dim = el.GetDim();
2170 int dimc = el.GetCurlDim();
2171 real_t w;
2172
2173#ifdef MFEM_THREAD_SAFE
2174 Vector D;
2175 DenseMatrix curlshape(nd,dimc), curlshape_dFt(nd,dimc), M;
2176#else
2177 curlshape.SetSize(nd,dimc);
2178 curlshape_dFt.SetSize(nd,dimc);
2179#endif
2180 elmat.SetSize(nd);
2181 if (MQ) { M.SetSize(dimc); }
2182 if (DQ) { D.SetSize(dimc); }
2183
2184 const IntegrationRule *ir = GetIntegrationRule(el, Trans);
2185 if (ir == NULL)
2186 {
2187 int order;
2188 if (el.Space() == FunctionSpace::Pk)
2189 {
2190 order = 2*el.GetOrder() - 2;
2191 }
2192 else
2193 {
2194 order = 2*el.GetOrder();
2195 }
2196
2197 ir = &IntRules.Get(el.GetGeomType(), order);
2198 }
2199
2200 elmat = 0.0;
2201 for (int i = 0; i < ir->GetNPoints(); i++)
2202 {
2203 const IntegrationPoint &ip = ir->IntPoint(i);
2204
2205 Trans.SetIntPoint (&ip);
2206
2207 w = ip.weight * Trans.Weight();
2208 el.CalcPhysCurlShape(Trans, curlshape_dFt);
2209
2210 if (MQ)
2211 {
2212 MQ->Eval(M, Trans, ip);
2213 M *= w;
2214 Mult(curlshape_dFt, M, curlshape);
2215 AddMultABt(curlshape, curlshape_dFt, elmat);
2216 }
2217 else if (DQ)
2218 {
2219 DQ->Eval(D, Trans, ip);
2220 D *= w;
2221 AddMultADAt(curlshape_dFt, D, elmat);
2222 }
2223 else if (Q)
2224 {
2225 w *= Q->Eval(Trans, ip);
2226 AddMult_a_AAt(w, curlshape_dFt, elmat);
2227 }
2228 else
2229 {
2230 AddMult_a_AAt(w, curlshape_dFt, elmat);
2231 }
2232 }
2233}
2234
2236 const FiniteElement &test_fe,
2237 ElementTransformation &Trans,
2238 DenseMatrix &elmat)
2239{
2240 int tr_nd = trial_fe.GetDof();
2241 int te_nd = test_fe.GetDof();
2242 dim = trial_fe.GetDim();
2243 int dimc = trial_fe.GetCurlDim();
2244 real_t w;
2245
2246#ifdef MFEM_THREAD_SAFE
2247 Vector D;
2248 DenseMatrix curlshape(tr_nd,dimc), curlshape_dFt(tr_nd,dimc), M;
2249 DenseMatrix te_curlshape(te_nd,dimc), te_curlshape_dFt(te_nd,dimc);
2250#else
2251 curlshape.SetSize(tr_nd,dimc);
2252 curlshape_dFt.SetSize(tr_nd,dimc);
2253 te_curlshape.SetSize(te_nd,dimc);
2254 te_curlshape_dFt.SetSize(te_nd,dimc);
2255#endif
2256 elmat.SetSize(te_nd, tr_nd);
2257
2258 if (MQ) { M.SetSize(dimc); }
2259 if (DQ) { D.SetSize(dimc); }
2260
2261
2262 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
2263 if (ir == NULL)
2264 {
2265 int order;
2266 if (trial_fe.Space() == FunctionSpace::Pk)
2267 {
2268 order = test_fe.GetOrder() + trial_fe.GetOrder() - 2;
2269 }
2270 else
2271 {
2272 order = test_fe.GetOrder() + trial_fe.GetOrder() + trial_fe.GetDim() - 1;
2273 }
2274 ir = &IntRules.Get(trial_fe.GetGeomType(), order);
2275 }
2276
2277 elmat = 0.0;
2278 for (int i = 0; i < ir->GetNPoints(); i++)
2279 {
2280 const IntegrationPoint &ip = ir->IntPoint(i);
2281
2282 Trans.SetIntPoint(&ip);
2283
2284 w = ip.weight * Trans.Weight();
2285 trial_fe.CalcPhysCurlShape(Trans, curlshape_dFt);
2286 test_fe.CalcPhysCurlShape(Trans, te_curlshape_dFt);
2287
2288 if (MQ)
2289 {
2290 MQ->Eval(M, Trans, ip);
2291 M *= w;
2292 Mult(te_curlshape_dFt, M, te_curlshape);
2293 AddMultABt(te_curlshape, curlshape_dFt, elmat);
2294 }
2295 else if (DQ)
2296 {
2297 DQ->Eval(D, Trans, ip);
2298 D *= w;
2299 AddMultADBt(te_curlshape_dFt,D,curlshape_dFt,elmat);
2300 }
2301 else
2302 {
2303 if (Q)
2304 {
2305 w *= Q->Eval(Trans, ip);
2306 }
2307 curlshape_dFt *= w;
2308 AddMultABt(te_curlshape_dFt, curlshape_dFt, elmat);
2309 }
2310 }
2311}
2312
2313void CurlCurlIntegrator
2314::ComputeElementFlux(const FiniteElement &el, ElementTransformation &Trans,
2315 Vector &u, const FiniteElement &fluxelem, Vector &flux,
2316 bool with_coef, const IntegrationRule *ir)
2317{
2318#ifdef MFEM_THREAD_SAFE
2319 DenseMatrix projcurl;
2320#endif
2321
2322 MFEM_VERIFY(ir == NULL, "Integration rule (ir) must be NULL")
2323
2324 fluxelem.ProjectCurl(el, Trans, projcurl);
2325
2326 flux.SetSize(projcurl.Height());
2327 projcurl.Mult(u, flux);
2328
2329 // TODO: Q, wcoef?
2330}
2331
2333 ElementTransformation &Trans,
2334 Vector &flux, Vector *d_energy)
2335{
2336 int nd = fluxelem.GetDof();
2337 dim = fluxelem.GetDim();
2338
2339#ifdef MFEM_THREAD_SAFE
2340 DenseMatrix vshape;
2341#endif
2342 vshape.SetSize(nd, dim);
2343 pointflux.SetSize(dim);
2344 if (d_energy) { vec.SetSize(dim); }
2345
2346 int order = 2 * fluxelem.GetOrder(); // <--
2347 const IntegrationRule &ir = IntRules.Get(fluxelem.GetGeomType(), order);
2348
2349 real_t energy = 0.0;
2350 if (d_energy) { *d_energy = 0.0; }
2351
2352 Vector* pfluxes = NULL;
2353 if (d_energy)
2354 {
2355 pfluxes = new Vector[ir.GetNPoints()];
2356 }
2357
2358 for (int i = 0; i < ir.GetNPoints(); i++)
2359 {
2360 const IntegrationPoint &ip = ir.IntPoint(i);
2361 Trans.SetIntPoint(&ip);
2362
2363 fluxelem.CalcVShape(Trans, vshape);
2364 // fluxelem.CalcVShape(ip, vshape);
2365 vshape.MultTranspose(flux, pointflux);
2366
2367 real_t w = Trans.Weight() * ip.weight;
2368
2369 real_t e = w * (pointflux * pointflux);
2370
2371 if (Q)
2372 {
2373 // TODO
2374 }
2375
2376 energy += e;
2377
2378#if ANISO_EXPERIMENTAL
2379 if (d_energy)
2380 {
2381 pfluxes[i].SetSize(dim);
2382 Trans.Jacobian().MultTranspose(pointflux, pfluxes[i]);
2383
2384 /*
2385 DenseMatrix Jadj(dim, dim);
2386 CalcAdjugate(Trans.Jacobian(), Jadj);
2387 pfluxes[i].SetSize(dim);
2388 Jadj.Mult(pointflux, pfluxes[i]);
2389 */
2390
2391 // pfluxes[i] = pointflux;
2392 }
2393#endif
2394 }
2395
2396 if (d_energy)
2397 {
2398#if ANISO_EXPERIMENTAL
2399 *d_energy = 0.0;
2400 Vector tmp;
2401
2402 int n = (int) round(pow(ir.GetNPoints(), 1.0/3.0));
2403 MFEM_ASSERT(n*n*n == ir.GetNPoints(), "");
2404
2405 // hack: get total variation of 'pointflux' in the x,y,z directions
2406 for (int k = 0; k < n; k++)
2407 for (int l = 0; l < n; l++)
2408 for (int m = 0; m < n; m++)
2409 {
2410 Vector &vec = pfluxes[(k*n + l)*n + m];
2411 if (m > 0)
2412 {
2413 tmp = vec; tmp -= pfluxes[(k*n + l)*n + (m-1)];
2414 (*d_energy)[0] += (tmp * tmp);
2415 }
2416 if (l > 0)
2417 {
2418 tmp = vec; tmp -= pfluxes[(k*n + (l-1))*n + m];
2419 (*d_energy)[1] += (tmp * tmp);
2420 }
2421 if (k > 0)
2422 {
2423 tmp = vec; tmp -= pfluxes[((k-1)*n + l)*n + m];
2424 (*d_energy)[2] += (tmp * tmp);
2425 }
2426 }
2427#else
2428 *d_energy = 1.0;
2429#endif
2430
2431 delete [] pfluxes;
2432 }
2433
2434 return energy;
2435}
2436
2438 const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat)
2439{
2440 int dim = el.GetDim();
2441 int dof = el.GetDof();
2442 int cld = (dim*(dim-1))/2;
2443
2444#ifdef MFEM_THREAD_SAFE
2445 DenseMatrix dshape_hat(dof, dim), dshape(dof, dim);
2446 DenseMatrix curlshape(dim*dof, cld), Jadj(dim);
2447#else
2448 dshape_hat.SetSize(dof, dim);
2449 dshape.SetSize(dof, dim);
2450 curlshape.SetSize(dim*dof, cld);
2451 Jadj.SetSize(dim);
2452#endif
2453
2454
2455 const IntegrationRule *ir = GetIntegrationRule(el, Trans);
2456 if (ir == NULL)
2457 {
2458 // use the same integration rule as diffusion
2459 int order = 2 * Trans.OrderGrad(&el);
2460 ir = &IntRules.Get(el.GetGeomType(), order);
2461 }
2462
2463 elmat.SetSize(dof*dim);
2464 elmat = 0.0;
2465 for (int i = 0; i < ir->GetNPoints(); i++)
2466 {
2467 const IntegrationPoint &ip = ir->IntPoint(i);
2468 el.CalcDShape(ip, dshape_hat);
2469
2470 Trans.SetIntPoint(&ip);
2471 CalcAdjugate(Trans.Jacobian(), Jadj);
2472 real_t w = ip.weight / Trans.Weight();
2473
2474 Mult(dshape_hat, Jadj, dshape);
2475 dshape.GradToCurl(curlshape);
2476
2477 if (Q)
2478 {
2479 w *= Q->Eval(Trans, ip);
2480 }
2481
2482 AddMult_a_AAt(w, curlshape, elmat);
2483 }
2484}
2485
2487 const FiniteElement &el, ElementTransformation &Tr, const Vector &elfun)
2488{
2489 int dim = el.GetDim();
2490 int dof = el.GetDof();
2491
2492#ifdef MFEM_THREAD_SAFE
2493 DenseMatrix dshape_hat(dof, dim), Jadj(dim), grad_hat(dim), grad(dim);
2494#else
2495 dshape_hat.SetSize(dof, dim);
2496
2497 Jadj.SetSize(dim);
2498 grad_hat.SetSize(dim);
2499 grad.SetSize(dim);
2500#endif
2501 DenseMatrix elfun_mat(elfun.GetData(), dof, dim);
2502
2503
2504 const IntegrationRule *ir = GetIntegrationRule(el, Tr);
2505 if (ir == NULL)
2506 {
2507 // use the same integration rule as diffusion
2508 int order = 2 * Tr.OrderGrad(&el);
2509 ir = &IntRules.Get(el.GetGeomType(), order);
2510 }
2511
2512 real_t energy = 0.;
2513 for (int i = 0; i < ir->GetNPoints(); i++)
2514 {
2515 const IntegrationPoint &ip = ir->IntPoint(i);
2516 el.CalcDShape(ip, dshape_hat);
2517
2518 MultAtB(elfun_mat, dshape_hat, grad_hat);
2519
2520 Tr.SetIntPoint(&ip);
2521 CalcAdjugate(Tr.Jacobian(), Jadj);
2522 real_t w = ip.weight / Tr.Weight();
2523
2524 Mult(grad_hat, Jadj, grad);
2525
2526 if (dim == 2)
2527 {
2528 real_t curl = grad(0,1) - grad(1,0);
2529 w *= curl * curl;
2530 }
2531 else
2532 {
2533 real_t curl_x = grad(2,1) - grad(1,2);
2534 real_t curl_y = grad(0,2) - grad(2,0);
2535 real_t curl_z = grad(1,0) - grad(0,1);
2536 w *= curl_x * curl_x + curl_y * curl_y + curl_z * curl_z;
2537 }
2538
2539 if (Q)
2540 {
2541 w *= Q->Eval(Tr, ip);
2542 }
2543
2544 energy += w;
2545 }
2546
2547 elfun_mat.ClearExternalData();
2548
2549 return 0.5 * energy;
2550}
2551
2553 const FiniteElement &trial_fe, const FiniteElement &test_fe,
2554 ElementTransformation &Trans, DenseMatrix &elmat)
2555{
2556 int dim = trial_fe.GetDim();
2557 int trial_dof = trial_fe.GetDof();
2558 int test_dof = test_fe.GetDof();
2559 int dimc = (dim == 3) ? 3 : 1;
2560
2561 MFEM_VERIFY(trial_fe.GetMapType() == mfem::FiniteElement::H_CURL ||
2562 (dim == 2 && trial_fe.GetMapType() == mfem::FiniteElement::VALUE),
2563 "Trial finite element must be either 2D/3D H(Curl) or 2D H1");
2564 MFEM_VERIFY(test_fe.GetMapType() == mfem::FiniteElement::VALUE ||
2566 "Test finite element must be in H1/L2");
2567
2568 bool spaceH1 = (trial_fe.GetMapType() == mfem::FiniteElement::VALUE);
2569
2570 if (spaceH1)
2571 {
2572 dshape.SetSize(trial_dof,dim);
2573 curlshape.SetSize(trial_dof,dim);
2574 dimc = dim;
2575 }
2576 else
2577 {
2578 curlshape.SetSize(trial_dof,dimc);
2579 elmat_comp.SetSize(test_dof, trial_dof);
2580 }
2581 elmat.SetSize(dimc * test_dof, trial_dof);
2582 shape.SetSize(test_dof);
2583 elmat = 0.0;
2584
2585 real_t c;
2586 Vector d_col;
2587
2588 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
2589 if (ir == NULL)
2590 {
2591 int order = trial_fe.GetOrder() + test_fe.GetOrder() + Trans.OrderJ();
2592 ir = &IntRules.Get(trial_fe.GetGeomType(), order);
2593 }
2594
2595 for (int i = 0; i < ir->GetNPoints(); i++)
2596 {
2597 const IntegrationPoint &ip = ir->IntPoint(i);
2598 Trans.SetIntPoint(&ip);
2599 if (spaceH1)
2600 {
2601 trial_fe.CalcPhysDShape(Trans, dshape);
2602 dshape.GradToVectorCurl2D(curlshape);
2603 }
2604 else
2605 {
2606 trial_fe.CalcPhysCurlShape(Trans, curlshape);
2607 }
2608 test_fe.CalcPhysShape(Trans, shape);
2609 c = ip.weight*Trans.Weight();
2610 if (Q)
2611 {
2612 c *= Q->Eval(Trans, ip);
2613 }
2614 shape *= c;
2615
2616 for (int d = 0; d < dimc; ++d)
2617 {
2618 real_t * curldata = &(curlshape.GetData())[d*trial_dof];
2619 for (int jj = 0; jj < trial_dof; ++jj)
2620 {
2621 for (int ii = 0; ii < test_dof; ++ii)
2622 {
2623 elmat(d * test_dof + ii, jj) += shape(ii) * curldata[jj];
2624 }
2625 }
2626 }
2627 }
2628}
2629
2630
2632 const FiniteElement &el,
2633 ElementTransformation &Trans,
2634 DenseMatrix &elmat)
2635{
2636 int dof = el.GetDof();
2637 int spaceDim = Trans.GetSpaceDim();
2638 int vdim = std::max(spaceDim, el.GetRangeDim());
2639
2640 real_t w;
2641
2642#ifdef MFEM_THREAD_SAFE
2643 Vector D(DQ ? DQ->GetVDim() : 0);
2644 DenseMatrix trial_vshape(dof, vdim);
2645 DenseMatrix K(MQ ? MQ->GetVDim() : 0, MQ ? MQ->GetVDim() : 0);
2646#else
2647 trial_vshape.SetSize(dof, vdim);
2648 D.SetSize(DQ ? DQ->GetVDim() : 0);
2649 K.SetSize(MQ ? MQ->GetVDim() : 0, MQ ? MQ->GetVDim() : 0);
2650#endif
2651 DenseMatrix tmp(trial_vshape.Height(), K.Width());
2652
2653 elmat.SetSize(dof);
2654 elmat = 0.0;
2655
2656 const IntegrationRule *ir = GetIntegrationRule(el, Trans);
2657 if (ir == NULL)
2658 {
2659 // int order = 2 * el.GetOrder();
2660 int order = Trans.OrderW() + 2 * el.GetOrder();
2661 ir = &IntRules.Get(el.GetGeomType(), order);
2662 }
2663
2664 for (int i = 0; i < ir->GetNPoints(); i++)
2665 {
2666 const IntegrationPoint &ip = ir->IntPoint(i);
2667
2668 Trans.SetIntPoint (&ip);
2669
2670 el.CalcVShape(Trans, trial_vshape);
2671
2672 w = ip.weight * Trans.Weight();
2673 if (MQ)
2674 {
2675 MQ->Eval(K, Trans, ip);
2676 K *= w;
2677 Mult(trial_vshape,K,tmp);
2678 AddMultABt(tmp,trial_vshape,elmat);
2679 }
2680 else if (DQ)
2681 {
2682 DQ->Eval(D, Trans, ip);
2683 D *= w;
2684 AddMultADAt(trial_vshape, D, elmat);
2685 }
2686 else
2687 {
2688 if (Q)
2689 {
2690 w *= Q -> Eval (Trans, ip);
2691 }
2692 AddMult_a_AAt (w, trial_vshape, elmat);
2693 }
2694 }
2695}
2696
2698 const FiniteElement &trial_fe, const FiniteElement &test_fe,
2699 ElementTransformation &Trans, DenseMatrix &elmat)
2700{
2701 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
2702
2703 if (test_fe.GetRangeType() == FiniteElement::SCALAR
2704 && trial_fe.GetRangeType() == FiniteElement::VECTOR)
2705 {
2706 // assume test_fe is scalar FE and trial_fe is vector FE
2707 int spaceDim = Trans.GetSpaceDim();
2708 int vdim = std::max(spaceDim, trial_fe.GetRangeDim());
2709 int trial_dof = trial_fe.GetDof();
2710 int test_dof = test_fe.GetDof();
2711 real_t w;
2712
2713#ifdef MFEM_THREAD_SAFE
2714 DenseMatrix trial_vshape(trial_dof, spaceDim);
2715 Vector shape(test_dof);
2716 Vector D(DQ ? DQ->GetVDim() : 0);
2717 DenseMatrix K(MQ ? MQ->GetVDim() : 0, MQ ? MQ->GetVDim() : 0);
2718#else
2719 trial_vshape.SetSize(trial_dof, spaceDim);
2720 shape.SetSize(test_dof);
2721 D.SetSize(DQ ? DQ->GetVDim() : 0);
2722 K.SetSize(MQ ? MQ->GetVDim() : 0, MQ ? MQ->GetVDim() : 0);
2723#endif
2724
2725 elmat.SetSize(vdim*test_dof, trial_dof);
2726 if (ir == NULL)
2727 {
2728 int order = (Trans.OrderW() + test_fe.GetOrder() + trial_fe.GetOrder());
2729 ir = &IntRules.Get(test_fe.GetGeomType(), order);
2730 }
2731
2732 elmat = 0.0;
2733 for (int i = 0; i < ir->GetNPoints(); i++)
2734 {
2735 const IntegrationPoint &ip = ir->IntPoint(i);
2736
2737 Trans.SetIntPoint (&ip);
2738
2739 trial_fe.CalcVShape(Trans, trial_vshape);
2740 test_fe.CalcPhysShape(Trans, shape);
2741
2742 w = ip.weight * Trans.Weight();
2743 if (DQ)
2744 {
2745 DQ->Eval(D, Trans, ip);
2746 D *= w;
2747 for (int d = 0; d < vdim; d++)
2748 {
2749 for (int j = 0; j < test_dof; j++)
2750 {
2751 for (int k = 0; k < trial_dof; k++)
2752 {
2753 elmat(d * test_dof + j, k) +=
2754 shape(j) * D(d) * trial_vshape(k, d);
2755 }
2756 }
2757 }
2758 }
2759 else if (MQ)
2760 {
2761 MQ->Eval(K, Trans, ip);
2762 K *= w;
2763 for (int d = 0; d < vdim; d++)
2764 {
2765 for (int j = 0; j < test_dof; j++)
2766 {
2767 for (int k = 0; k < trial_dof; k++)
2768 {
2769 real_t Kv = 0.0;
2770 for (int vd = 0; vd < spaceDim; vd++)
2771 {
2772 Kv += K(d, vd) * trial_vshape(k, vd);
2773 }
2774 elmat(d * test_dof + j, k) += shape(j) * Kv;
2775 }
2776 }
2777 }
2778 }
2779 else
2780 {
2781 if (Q)
2782 {
2783 w *= Q->Eval(Trans, ip);
2784 }
2785 for (int d = 0; d < vdim; d++)
2786 {
2787 for (int j = 0; j < test_dof; j++)
2788 {
2789 for (int k = 0; k < trial_dof; k++)
2790 {
2791 elmat(d * test_dof + j, k) +=
2792 w * shape(j) * trial_vshape(k, d);
2793 }
2794 }
2795 }
2796 }
2797 }
2798 }
2799 else if (test_fe.GetRangeType() == FiniteElement::VECTOR
2800 && trial_fe.GetRangeType() == FiniteElement::VECTOR)
2801 {
2802 // assume both test_fe and trial_fe are vector FE
2803 int spaceDim = Trans.GetSpaceDim();
2804 int trial_vdim = std::max(spaceDim, trial_fe.GetRangeDim());
2805 int test_vdim = std::max(spaceDim, test_fe.GetRangeDim());
2806 int trial_dof = trial_fe.GetDof();
2807 int test_dof = test_fe.GetDof();
2808 real_t w;
2809
2810#ifdef MFEM_THREAD_SAFE
2811 DenseMatrix trial_vshape(trial_dof,trial_vdim);
2812 DenseMatrix test_vshape(test_dof,test_vdim);
2813 Vector D(DQ ? DQ->GetVDim() : 0);
2814 DenseMatrix K(MQ ? MQ->GetVDim() : 0, MQ ? MQ->GetVDim() : 0);
2815#else
2816 trial_vshape.SetSize(trial_dof,trial_vdim);
2817 test_vshape.SetSize(test_dof,test_vdim);
2818 D.SetSize(DQ ? DQ->GetVDim() : 0);
2819 K.SetSize(MQ ? MQ->GetVDim() : 0, MQ ? MQ->GetVDim() : 0);
2820#endif
2821 DenseMatrix tmp(test_vshape.Height(), K.Width());
2822
2823 elmat.SetSize (test_dof, trial_dof);
2824
2825 if (ir == NULL)
2826 {
2827 int order = (Trans.OrderW() + test_fe.GetOrder() + trial_fe.GetOrder());
2828 ir = &IntRules.Get(test_fe.GetGeomType(), order);
2829 }
2830
2831 elmat = 0.0;
2832 for (int i = 0; i < ir->GetNPoints(); i++)
2833 {
2834 const IntegrationPoint &ip = ir->IntPoint(i);
2835
2836 Trans.SetIntPoint (&ip);
2837
2838 trial_fe.CalcVShape(Trans, trial_vshape);
2839 test_fe.CalcVShape(Trans, test_vshape);
2840
2841 w = ip.weight * Trans.Weight();
2842 if (MQ)
2843 {
2844 MQ->Eval(K, Trans, ip);
2845 K *= w;
2846 Mult(test_vshape,K,tmp);
2847 AddMultABt(tmp,trial_vshape,elmat);
2848 }
2849 else if (DQ)
2850 {
2851 DQ->Eval(D, Trans, ip);
2852 D *= w;
2853 AddMultADBt(test_vshape,D,trial_vshape,elmat);
2854 }
2855 else
2856 {
2857 if (Q)
2858 {
2859 w *= Q -> Eval (Trans, ip);
2860 }
2861 AddMult_a_ABt(w,test_vshape,trial_vshape,elmat);
2862 }
2863 }
2864 }
2865 else
2866 {
2867 MFEM_ABORT("VectorFEMassIntegrator::AssembleElementMatrix2(...)\n"
2868 " is not implemented for given trial and test bases.");
2869 }
2870}
2871
2873 const FiniteElement &trial_fe,
2874 const FiniteElement &test_fe,
2875 ElementTransformation &Trans,
2876 DenseMatrix &elmat)
2877{
2878 dim = trial_fe.GetDim();
2879 sdim = Trans.GetSpaceDim();
2880 int trial_dof = trial_fe.GetDof();
2881 int test_dof = test_fe.GetDof();
2882 real_t c;
2883
2884 dshape.SetSize (trial_dof, dim);
2885 gshape.SetSize (trial_dof, sdim);
2886 Jadj.SetSize (dim, sdim);
2887 divshape.SetSize (sdim*trial_dof);
2888 shape.SetSize (test_dof);
2889
2890 elmat.SetSize (test_dof, sdim*trial_dof);
2891
2892 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
2893
2894 elmat = 0.0;
2895
2896 for (int i = 0; i < ir -> GetNPoints(); i++)
2897 {
2898 const IntegrationPoint &ip = ir->IntPoint(i);
2899 Trans.SetIntPoint (&ip);
2900
2901 trial_fe.CalcDShape (ip, dshape);
2902 test_fe.CalcPhysShape (Trans, shape);
2903
2904 // AdjugateJacobian = / adj(J), if J is square
2905 // \ adj(J^t.J).J^t, otherwise
2906 CalcAdjugate(Trans.Jacobian(), Jadj);
2907 Mult (dshape, Jadj, gshape);
2908
2909 gshape.GradToDiv (divshape);
2910
2911 c = ip.weight;
2912 if (dim != sdim) { c /= Trans.Weight(); }
2913 if (Q)
2914 {
2915 c *= Q -> Eval (Trans, ip);
2916 }
2917
2918 // elmat += c * shape * divshape ^ t
2919 shape *= c;
2920 AddMultVWt (shape, divshape, elmat);
2921 }
2922}
2923
2925 const FiniteElement &trial_fe,
2926 const FiniteElement &test_fe,
2927 const ElementTransformation &Trans)
2928{
2929 int order = Trans.OrderGrad(&trial_fe) + test_fe.GetOrder() + Trans.OrderJ();
2930 return IntRules.Get(trial_fe.GetGeomType(), order);
2931}
2932
2933
2935 const FiniteElement &el,
2936 ElementTransformation &Trans,
2937 DenseMatrix &elmat)
2938{
2939 int dof = el.GetDof();
2940 real_t c;
2941
2942#ifdef MFEM_THREAD_SAFE
2943 Vector divshape(dof);
2944#else
2945 divshape.SetSize(dof);
2946#endif
2947 elmat.SetSize(dof);
2948
2949 const IntegrationRule *ir = GetIntegrationRule(el, Trans);
2950 if (ir == NULL)
2951 {
2952 int order = 2 * el.GetOrder() - 2; // <--- OK for RTk
2953 if (el.Space() == FunctionSpace::Uk)
2954 {
2955 order += 2;
2956 }
2957
2958 ir = &IntRules.Get(el.GetGeomType(), order);
2959 }
2960
2961 elmat = 0.0;
2962
2963 for (int i = 0; i < ir -> GetNPoints(); i++)
2964 {
2965 const IntegrationPoint &ip = ir->IntPoint(i);
2966
2967 el.CalcDivShape (ip, divshape);
2968
2969 Trans.SetIntPoint (&ip);
2970 c = ip.weight / Trans.Weight();
2971
2972 if (Q)
2973 {
2974 c *= Q -> Eval (Trans, ip);
2975 }
2976
2977 // elmat += c * divshape * divshape ^ t
2978 AddMult_a_VVt (c, divshape, elmat);
2979 }
2980}
2981
2983 const FiniteElement &trial_fe,
2984 const FiniteElement &test_fe,
2985 ElementTransformation &Trans,
2986 DenseMatrix &elmat)
2987{
2988 int tr_nd = trial_fe.GetDof();
2989 int te_nd = test_fe.GetDof();
2990 real_t c;
2991
2992#ifdef MFEM_THREAD_SAFE
2993 Vector divshape(tr_nd);
2994 Vector te_divshape(te_nd);
2995#else
2996 divshape.SetSize(tr_nd);
2997 te_divshape.SetSize(te_nd);
2998#endif
2999 elmat.SetSize(te_nd,tr_nd);
3000
3001 const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
3002 if (ir == NULL)
3003 {
3004 int order = 2 * max(test_fe.GetOrder(),
3005 trial_fe.GetOrder()) - 2; // <--- OK for RTk
3006 ir = &IntRules.Get(test_fe.GetGeomType(), order);
3007 }
3008
3009 elmat = 0.0;
3010
3011 for (int i = 0; i < ir -> GetNPoints(); i++)
3012 {
3013 const IntegrationPoint &ip = ir->IntPoint(i);
3014
3015 trial_fe.CalcDivShape(ip,divshape);
3016 test_fe.CalcDivShape(ip,te_divshape);
3017
3018 Trans.SetIntPoint (&ip);
3019 c = ip.weight / Trans.Weight();
3020
3021 if (Q)
3022 {
3023 c *= Q -> Eval (Trans, ip);
3024 }
3025
3026 te_divshape *= c;
3027 AddMultVWt(te_divshape, divshape, elmat);
3028 }
3029}
3030
3032 const FiniteElement &el,
3033 ElementTransformation &Trans,
3034 DenseMatrix &elmat)
3035{
3036 const int dof = el.GetDof();
3037 dim = el.GetDim();
3038 sdim = Trans.GetSpaceDim();
3039
3040 // If vdim is not set, set it to the space dimension;
3041 vdim = (vdim <= 0) ? sdim : vdim;
3042 const bool square = (dim == sdim);
3043
3044 if (VQ)
3045 {
3046 vcoeff.SetSize(vdim);
3047 }
3048 else if (MQ)
3049 {
3050 mcoeff.SetSize(vdim);
3051 }
3052
3053 dshape.SetSize(dof, dim);
3054 dshapedxt.SetSize(dof, sdim);
3055
3056 elmat.SetSize(vdim * dof);
3057 pelmat.SetSize(dof);
3058
3059 const IntegrationRule *ir = GetIntegrationRule(el, Trans);
3060 if (ir == NULL)
3061 {
3062 ir = &DiffusionIntegrator::GetRule(el,el);
3063 }
3064
3065 elmat = 0.0;
3066
3067 for (int i = 0; i < ir -> GetNPoints(); i++)
3068 {
3069 const IntegrationPoint &ip = ir->IntPoint(i);
3070 el.CalcDShape(ip, dshape);
3071
3072 Trans.SetIntPoint(&ip);
3073 real_t w = Trans.Weight();
3074 w = ip.weight / (square ? w : w*w*w);
3075 // AdjugateJacobian = / adj(J), if J is square
3076 // \ adj(J^t.J).J^t, otherwise
3077 Mult(dshape, Trans.AdjugateJacobian(), dshapedxt);
3078
3079 if (VQ)
3080 {
3081 VQ->Eval(vcoeff, Trans, ip);
3082 for (int k = 0; k < vdim; ++k)
3083 {
3084 Mult_a_AAt(w*vcoeff(k), dshapedxt, pelmat);
3085 elmat.AddMatrix(pelmat, dof*k, dof*k);
3086 }
3087 }
3088 else if (MQ)
3089 {
3090 MQ->Eval(mcoeff, Trans, ip);
3091 for (int ii = 0; ii < vdim; ++ii)
3092 {
3093 for (int jj = 0; jj < vdim; ++jj)
3094 {
3095 Mult_a_AAt(w*mcoeff(ii,jj), dshapedxt, pelmat);
3096 elmat.AddMatrix(pelmat, dof*ii, dof*jj);
3097 }
3098 }
3099 }
3100 else
3101 {
3102 if (Q) { w *= Q->Eval(Trans, ip); }
3103 Mult_a_AAt(w, dshapedxt, pelmat);
3104 for (int k = 0; k < vdim; ++k)
3105 {
3106 elmat.AddMatrix(pelmat, dof*k, dof*k);
3107 }
3108 }
3109 }
3110}
3111
3113 const FiniteElement &el, ElementTransformation &Tr,
3114 const Vector &elfun, Vector &elvect)
3115{
3116 const int dof = el.GetDof();
3117 dim = el.GetDim();
3118 sdim = Tr.GetSpaceDim();
3119
3120 // If vdim is not set, set it to the space dimension;
3121 vdim = (vdim <= 0) ? sdim : vdim;
3122 const bool square = (dim == sdim);
3123
3124 if (VQ)
3125 {
3126 vcoeff.SetSize(vdim);
3127 }
3128 else if (MQ)
3129 {
3130 mcoeff.SetSize(vdim);
3131 }
3132
3133 dshape.SetSize(dof, dim);
3134 dshapedxt.SetSize(dof, sdim);
3135 pelmat.SetSize(dof);
3136
3137 elvect.SetSize(vdim*dof);
3138
3139 // NOTE: DenseMatrix is in column-major order. This is consistent with
3140 // vectors ordered byNODES. In the resulting DenseMatrix, each column
3141 // corresponds to a particular vdim.
3142 DenseMatrix mat_in(elfun.GetData(), dof, vdim);
3143 DenseMatrix mat_out(elvect.GetData(), dof, vdim);
3144
3145
3146 const IntegrationRule *ir = GetIntegrationRule(el, Tr);
3147 if (ir == NULL)
3148 {
3149 ir = &DiffusionIntegrator::GetRule(el,el);
3150 }
3151
3152 elvect = 0.0;
3153 for (int i = 0; i < ir->GetNPoints(); i++)
3154 {
3155 const IntegrationPoint &ip = ir->IntPoint(i);
3156 el.CalcDShape(ip, dshape);
3157
3158 Tr.SetIntPoint(&ip);
3159 real_t w = Tr.Weight();
3160 w = ip.weight / (square ? w : w*w*w);
3161 Mult(dshape, Tr.AdjugateJacobian(), dshapedxt);
3162 MultAAt(dshapedxt, pelmat);
3163
3164 if (VQ)
3165 {
3166 VQ->Eval(vcoeff, Tr, ip);
3167 for (int k = 0; k < vdim; ++k)
3168 {
3169 const Vector vec_in(mat_in.GetColumn(k), dof);
3170 Vector vec_out(mat_out.GetColumn(k), dof);
3171 pelmat.AddMult_a(w*vcoeff(k), vec_in, vec_out);
3172 }
3173 }
3174 else if (MQ)
3175 {
3176 MQ->Eval(mcoeff, Tr, ip);
3177 for (int ii = 0; ii < vdim; ++ii)
3178 {
3179 Vector vec_out(mat_out.GetColumn(ii), dof);
3180 for (int jj = 0; jj < vdim; ++jj)
3181 {
3182 const Vector vec_in(mat_in.GetColumn(jj), dof);
3183 pelmat.AddMult_a(w*mcoeff(ii,jj), vec_in, vec_out);
3184 }
3185 }
3186 }
3187 else
3188 {
3189 if (Q) { w *= Q->Eval(Tr, ip); }
3190 pelmat *= w;
3191 for (int k = 0; k < vdim; ++k)
3192 {
3193 const Vector vec_in(mat_in.GetColumn(k), dof);
3194 Vector vec_out(mat_out.GetColumn(k), dof);
3195 pelmat.AddMult(vec_in, vec_out);
3196 }
3197 }
3198 }
3199}
3200
3202 ElasticityIntegrator &parent_, int i_, int j_)
3203 : parent(parent_),
3204 i_block(i_),
3205 j_block(j_)
3206{ }
3207
3209 const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat)
3210{
3211 int dof = el.GetDof();
3212 int dim = el.GetDim();
3213 real_t w, L, M;
3214
3215 MFEM_ASSERT(dim == Trans.GetSpaceDim(), "");
3216
3217#ifdef MFEM_THREAD_SAFE
3218 DenseMatrix dshape(dof, dim), gshape(dof, dim), pelmat(dof);
3219 Vector divshape(dim*dof);
3220#else
3221 dshape.SetSize(dof, dim);
3222 gshape.SetSize(dof, dim);
3223 pelmat.SetSize(dof);
3224 divshape.SetSize(dim*dof);
3225#endif
3226
3227 elmat.SetSize(dof * dim);
3228
3229 const IntegrationRule *ir = GetIntegrationRule(el, Trans);
3230 if (ir == NULL)
3231 {
3232 int order = 2 * Trans.OrderGrad(&el); // correct order?
3233 ir = &IntRules.Get(el.GetGeomType(), order);
3234 }
3235
3236 elmat = 0.0;
3237
3238 for (int i = 0; i < ir->GetNPoints(); i++)
3239 {
3240 const IntegrationPoint &ip = ir->IntPoint(i);
3241
3242 el.CalcDShape(ip, dshape);
3243
3244 Trans.SetIntPoint(&ip);
3245 w = ip.weight * Trans.Weight();
3246 Mult(dshape, Trans.InverseJacobian(), gshape);
3247 MultAAt(gshape, pelmat);
3248 gshape.GradToDiv (divshape);
3249
3250 M = mu->Eval(Trans, ip);
3251 if (lambda)
3252 {
3253 L = lambda->Eval(Trans, ip);
3254 }
3255 else
3256 {
3257 L = q_lambda * M;
3258 M = q_mu * M;
3259 }
3260
3261 if (L != 0.0)
3262 {
3263 AddMult_a_VVt(L * w, divshape, elmat);
3264 }
3265
3266 if (M != 0.0)
3267 {
3268 for (int d = 0; d < dim; d++)
3269 {
3270 for (int k = 0; k < dof; k++)
3271 for (int l = 0; l < dof; l++)
3272 {
3273 elmat (dof*d+k, dof*d+l) += (M * w) * pelmat(k, l);
3274 }
3275 }
3276 for (int ii = 0; ii < dim; ii++)
3277 for (int jj = 0; jj < dim; jj++)
3278 {
3279 for (int kk = 0; kk < dof; kk++)
3280 for (int ll = 0; ll < dof; ll++)
3281 {
3282 elmat(dof*ii+kk, dof*jj+ll) +=
3283 (M * w) * gshape(kk, jj) * gshape(ll, ii);
3284 }
3285 }
3286 }
3287 }
3288}
3289
3292 Vector &u, const mfem::FiniteElement &fluxelem, Vector &flux,
3293 bool with_coef, const IntegrationRule *ir)
3294{
3295 const int dof = el.GetDof();
3296 const int dim = el.GetDim();
3297 const int tdim = dim*(dim+1)/2; // num. entries in a symmetric tensor
3298 real_t L, M;
3299
3300 MFEM_ASSERT(dim == 2 || dim == 3,
3301 "dimension is not supported: dim = " << dim);
3302 MFEM_ASSERT(dim == Trans.GetSpaceDim(), "");
3303 MFEM_ASSERT(fluxelem.GetMapType() == FiniteElement::VALUE, "");
3304 MFEM_ASSERT(dynamic_cast<const NodalFiniteElement*>(&fluxelem), "");
3305
3306#ifdef MFEM_THREAD_SAFE
3307 DenseMatrix dshape(dof, dim);
3308#else
3309 dshape.SetSize(dof, dim);
3310#endif
3311
3312 real_t gh_data[9], grad_data[9];
3313 DenseMatrix gh(gh_data, dim, dim);
3314 DenseMatrix grad(grad_data, dim, dim);
3315
3316 if (!ir)
3317 {
3318 ir = &fluxelem.GetNodes();
3319 }
3320 const int fnd = ir->GetNPoints();
3321 flux.SetSize(fnd * tdim);
3322
3323 DenseMatrix loc_data_mat(u.GetData(), dof, dim);
3324 for (int i = 0; i < fnd; i++)
3325 {
3326 const IntegrationPoint &ip = ir->IntPoint(i);
3327 el.CalcDShape(ip, dshape);
3328 MultAtB(loc_data_mat, dshape, gh);
3329
3330 Trans.SetIntPoint(&ip);
3331 Mult(gh, Trans.InverseJacobian(), grad);
3332
3333 M = mu->Eval(Trans, ip);
3334 if (lambda)
3335 {
3336 L = lambda->Eval(Trans, ip);
3337 }
3338 else
3339 {
3340 L = q_lambda * M;
3341 M = q_mu * M;
3342 }
3343
3344 // stress = 2*M*e(u) + L*tr(e(u))*I, where
3345 // e(u) = (1/2)*(grad(u) + grad(u)^T)
3346 const real_t M2 = 2.0*M;
3347 if (dim == 2)
3348 {
3349 L *= (grad(0,0) + grad(1,1));
3350 // order of the stress entries: s_xx, s_yy, s_xy
3351 flux(i+fnd*0) = M2*grad(0,0) + L;
3352 flux(i+fnd*1) = M2*grad(1,1) + L;
3353 flux(i+fnd*2) = M*(grad(0,1) + grad(1,0));
3354 }
3355 else if (dim == 3)
3356 {
3357 L *= (grad(0,0) + grad(1,1) + grad(2,2));
3358 // order of the stress entries: s_xx, s_yy, s_zz, s_xy, s_xz, s_yz
3359 flux(i+fnd*0) = M2*grad(0,0) + L;
3360 flux(i+fnd*1) = M2*grad(1,1) + L;
3361 flux(i+fnd*2) = M2*grad(2,2) + L;
3362 flux(i+fnd*3) = M*(grad(0,1) + grad(1,0));
3363 flux(i+fnd*4) = M*(grad(0,2) + grad(2,0));
3364 flux(i+fnd*5) = M*(grad(1,2) + grad(2,1));
3365 }
3366 }
3367}
3368
3370 ElementTransformation &Trans,
3371 Vector &flux, Vector *d_energy)
3372{
3373 const int dof = fluxelem.GetDof();
3374 const int dim = fluxelem.GetDim();
3375 const int tdim = dim*(dim+1)/2; // num. entries in a symmetric tensor
3376 real_t L, M;
3377
3378 // The MFEM_ASSERT constraints in ElasticityIntegrator::ComputeElementFlux
3379 // are assumed here too.
3380 MFEM_ASSERT(d_energy == NULL, "anisotropic estimates are not supported");
3381 MFEM_ASSERT(flux.Size() == dof*tdim, "invalid 'flux' vector");
3382
3383#ifndef MFEM_THREAD_SAFE
3384 shape.SetSize(dof);
3385#else
3386 Vector shape(dof);
3387#endif
3388 real_t pointstress_data[6];
3389 Vector pointstress(pointstress_data, tdim);
3390
3391 // View of the 'flux' vector as a (dof x tdim) matrix
3392 DenseMatrix flux_mat(flux.GetData(), dof, tdim);
3393
3394 // Use the same integration rule as in AssembleElementMatrix, replacing 'el'
3395 // with 'fluxelem' when 'IntRule' is not set.
3396 // Should we be using a different (more accurate) rule here?
3397
3398 const IntegrationRule *ir = GetIntegrationRule(fluxelem, Trans);
3399 if (ir == NULL)
3400 {
3401 int order = 2 * Trans.OrderGrad(&fluxelem);
3402 ir = &IntRules.Get(fluxelem.GetGeomType(), order);
3403 }
3404
3405 real_t energy = 0.0;
3406
3407 for (int i = 0; i < ir->GetNPoints(); i++)
3408 {
3409 const IntegrationPoint &ip = ir->IntPoint(i);
3410 Trans.SetIntPoint(&ip);
3411 fluxelem.CalcPhysShape(Trans, shape);
3412
3413 flux_mat.MultTranspose(shape, pointstress);
3414
3415 real_t w = Trans.Weight() * ip.weight;
3416
3417 M = mu->Eval(Trans, ip);
3418 if (lambda)
3419 {
3420 L = lambda->Eval(Trans, ip);
3421 }
3422 else
3423 {
3424 L = q_lambda * M;
3425 M = q_mu * M;
3426 }
3427
3428 // The strain energy density at a point is given by (1/2)*(s : e) where s
3429 // and e are the stress and strain tensors, respectively. Since we only
3430 // have the stress, we need to compute the strain from the stress:
3431 // s = 2*mu*e + lambda*tr(e)*I
3432 // Taking trace on both sides we find:
3433 // tr(s) = 2*mu*tr(e) + lambda*tr(e)*dim = (2*mu + dim*lambda)*tr(e)
3434 // which gives:
3435 // tr(e) = tr(s)/(2*mu + dim*lambda)
3436 // Then from the first identity above we can find the strain:
3437 // e = (1/(2*mu))*(s - lambda*tr(e)*I)
3438
3439 real_t pt_e; // point strain energy density
3440 const real_t *s = pointstress_data;
3441 if (dim == 2)
3442 {
3443 // s entries: s_xx, s_yy, s_xy
3444 const real_t tr_e = (s[0] + s[1])/(2*(M + L));
3445 L *= tr_e;
3446 pt_e = (0.25/M)*(s[0]*(s[0] - L) + s[1]*(s[1] - L) + 2*s[2]*s[2]);
3447 }
3448 else // (dim == 3)
3449 {
3450 // s entries: s_xx, s_yy, s_zz, s_xy, s_xz, s_yz
3451 const real_t tr_e = (s[0] + s[1] + s[2])/(2*M + 3*L);
3452 L *= tr_e;
3453 pt_e = (0.25/M)*(s[0]*(s[0] - L) + s[1]*(s[1] - L) + s[2]*(s[2] - L) +
3454 2*(s[3]*s[3] + s[4]*s[4] + s[5]*s[5]));
3455 }
3456
3457 energy += w * pt_e;
3458 }
3459 return energy;
3460}
3461
3463 const FiniteElement &el2,
3465 DenseMatrix &elmat)
3466{
3467 int ndof1, ndof2;
3468
3469 real_t un, a, b, w;
3470
3471 dim = el1.GetDim();
3472 ndof1 = el1.GetDof();
3473 Vector vu(dim), nor(dim);
3474
3475 if (Trans.Elem2No >= 0)
3476 {
3477 ndof2 = el2.GetDof();
3478 }
3479 else
3480 {
3481 ndof2 = 0;
3482 }
3483
3484 shape1.SetSize(ndof1);
3485 shape2.SetSize(ndof2);
3486 elmat.SetSize(ndof1 + ndof2);
3487 elmat = 0.0;
3488
3489 const IntegrationRule *ir = IntRule;
3490 if (ir == NULL)
3491 {
3492 int order;
3493 // Assuming order(u)==order(mesh)
3494 if (Trans.Elem2No >= 0)
3495 order = (min(Trans.Elem1->OrderW(), Trans.Elem2->OrderW()) +
3496 2*max(el1.GetOrder(), el2.GetOrder()));
3497 else
3498 {
3499 order = Trans.Elem1->OrderW() + 2*el1.GetOrder();
3500 }
3501 if (el1.Space() == FunctionSpace::Pk)
3502 {
3503 order++;
3504 }
3505 ir = &IntRules.Get(Trans.GetGeometryType(), order);
3506 }
3507
3508 for (int p = 0; p < ir->GetNPoints(); p++)
3509 {
3510 const IntegrationPoint &ip = ir->IntPoint(p);
3511
3512 // Set the integration point in the face and the neighboring elements
3513 Trans.SetAllIntPoints(&ip);
3514
3515 // Access the neighboring elements' integration points
3516 // Note: eip2 will only contain valid data if Elem2 exists
3517 const IntegrationPoint &eip1 = Trans.GetElement1IntPoint();
3518 const IntegrationPoint &eip2 = Trans.GetElement2IntPoint();
3519
3520 el1.CalcPhysShape(*Trans.Elem1, shape1);
3521
3522 u->Eval(vu, *Trans.Elem1, eip1);
3523
3524 if (dim == 1)
3525 {
3526 nor(0) = 2*eip1.x - 1.0;
3527 }
3528 else
3529 {
3530 CalcOrtho(Trans.Jacobian(), nor);
3531 }
3532
3533 un = vu * nor;
3534 a = 0.5 * alpha * un;
3535 b = beta * fabs(un);
3536 // note: if |alpha/2|==|beta| then |a|==|b|, i.e. (a==b) or (a==-b)
3537 // and therefore two blocks in the element matrix contribution
3538 // (from the current quadrature point) are 0
3539
3540 if (rho)
3541 {
3542 real_t rho_p;
3543 if (un >= 0.0 && ndof2)
3544 {
3545 rho_p = rho->Eval(*Trans.Elem2, eip2);
3546 }
3547 else
3548 {
3549 rho_p = rho->Eval(*Trans.Elem1, eip1);
3550 }
3551 a *= rho_p;
3552 b *= rho_p;
3553 }
3554
3555 w = ip.weight * (a+b);
3556 if (w != 0.0)
3557 {
3558 for (int i = 0; i < ndof1; i++)
3559 for (int j = 0; j < ndof1; j++)
3560 {
3561 elmat(i, j) += w * shape1(i) * shape1(j);
3562 }
3563 }
3564
3565 if (ndof2)
3566 {
3567 el2.CalcPhysShape(*Trans.Elem2, shape2);
3568
3569 if (w != 0.0)
3570 for (int i = 0; i < ndof2; i++)
3571 for (int j = 0; j < ndof1; j++)
3572 {
3573 elmat(ndof1+i, j) -= w * shape2(i) * shape1(j);
3574 }
3575
3576 w = ip.weight * (b-a);
3577 if (w != 0.0)
3578 {
3579 for (int i = 0; i < ndof2; i++)
3580 for (int j = 0; j < ndof2; j++)
3581 {
3582 elmat(ndof1+i, ndof1+j) += w * shape2(i) * shape2(j);
3583 }
3584
3585 for (int i = 0; i < ndof1; i++)
3586 for (int j = 0; j < ndof2; j++)
3587 {
3588 elmat(i, ndof1+j) -= w * shape1(i) * shape2(j);
3589 }
3590 }
3591 }
3592 }
3593}
3594
3596 const FiniteElement &test_fe1,
3597 const FiniteElement &trial_fe2,
3598 const FiniteElement &test_fe2,
3600 DenseMatrix &elmat)
3601{
3602 int tr_ndof1, te_ndof1, tr_ndof2, te_ndof2;
3603
3604 real_t un, a, b, w;
3605
3606 dim = test_fe1.GetDim();
3607 tr_ndof1 = trial_fe1.GetDof();
3608 te_ndof1 = test_fe1.GetDof();
3609 Vector vu(dim), nor(dim);
3610
3611 if (Trans.Elem2No >= 0)
3612 {
3613 tr_ndof2 = trial_fe2.GetDof();
3614 te_ndof2 = test_fe2.GetDof();
3615 }
3616 else
3617 {
3618 tr_ndof2 = 0;
3619 te_ndof2 = 0;
3620 }
3621
3622 tr_shape1.SetSize(tr_ndof1);
3623 te_shape1.SetSize(te_ndof1);
3624 tr_shape2.SetSize(tr_ndof2);
3625 te_shape2.SetSize(te_ndof2);
3626 elmat.SetSize(te_ndof1 + te_ndof2, tr_ndof1 + tr_ndof2);
3627 elmat = 0.0;
3628
3629 const IntegrationRule *ir = IntRule;
3630 if (ir == NULL)
3631 {
3632 int order;
3633 // Assuming order(u)==order(mesh)
3634 if (Trans.Elem2No >= 0)
3635 order = (min(Trans.Elem1->OrderW(), Trans.Elem2->OrderW()) +
3636 max(trial_fe1.GetOrder(), trial_fe2.GetOrder()) +
3637 max(test_fe1.GetOrder(), test_fe2.GetOrder()));
3638 else
3639 {
3640 order = Trans.Elem1->OrderW() + trial_fe1.GetOrder() + test_fe1.GetOrder();
3641 }
3642 if (trial_fe1.Space() == FunctionSpace::Pk)
3643 {
3644 order++;
3645 }
3646 ir = &IntRules.Get(Trans.FaceGeom, order);
3647 }
3648
3649 for (int p = 0; p < ir->GetNPoints(); p++)
3650 {
3651 const IntegrationPoint &ip = ir->IntPoint(p);
3652 IntegrationPoint eip1, eip2;
3653 Trans.Loc1.Transform(ip, eip1);
3654 Trans.Elem1->SetIntPoint(&eip1);
3655 if (tr_ndof2 && te_ndof2)
3656 {
3657 Trans.Loc2.Transform(ip, eip2);
3658 Trans.Elem2->SetIntPoint(&eip2);
3659 }
3660 trial_fe1.CalcPhysShape(*Trans.Elem1, tr_shape1);
3661 test_fe1.CalcPhysShape(*Trans.Elem1, te_shape1);
3662
3663 Trans.Face->SetIntPoint(&ip);
3664
3665 u->Eval(vu, *Trans.Elem1, eip1);
3666
3667 if (dim == 1)
3668 {
3669 nor(0) = 2*eip1.x - 1.0;
3670 }
3671 else
3672 {
3673 CalcOrtho(Trans.Face->Jacobian(), nor);
3674 }
3675
3676 un = vu * nor;
3677 a = 0.5 * alpha * un;
3678 b = beta * fabs(un);
3679 // note: if |alpha/2|==|beta| then |a|==|b|, i.e. (a==b) or (a==-b)
3680 // and therefore two blocks in the element matrix contribution
3681 // (from the current quadrature point) are 0
3682
3683 if (rho)
3684 {
3685 real_t rho_p;
3686 if (un >= 0.0 && tr_ndof2 && te_ndof2)
3687 {
3688 Trans.Elem2->SetIntPoint(&eip2);
3689 rho_p = rho->Eval(*Trans.Elem2, eip2);
3690 }
3691 else
3692 {
3693 rho_p = rho->Eval(*Trans.Elem1, eip1);
3694 }
3695 a *= rho_p;
3696 b *= rho_p;
3697 }
3698
3699 w = ip.weight * (a+b);
3700 if (w != 0.0)
3701 {
3702 for (int i = 0; i < te_ndof1; i++)
3703 for (int j = 0; j < tr_ndof1; j++)
3704 {
3705 elmat(i, j) += w * te_shape1(i) * tr_shape1(j);
3706 }
3707 }
3708
3709 if (tr_ndof2 && te_ndof2)
3710 {
3711 trial_fe2.CalcPhysShape(*Trans.Elem2, tr_shape2);
3712 test_fe2.CalcPhysShape(*Trans.Elem2, te_shape2);
3713
3714 if (w != 0.0)
3715 for (int i = 0; i < te_ndof2; i++)
3716 for (int j = 0; j < tr_ndof1; j++)
3717 {
3718 elmat(te_ndof1+i, j) -= w * te_shape2(i) * tr_shape1(j);
3719 }
3720
3721 w = ip.weight * (b-a);
3722 if (w != 0.0)
3723 {
3724 for (int i = 0; i < te_ndof2; i++)
3725 for (int j = 0; j < tr_ndof2; j++)
3726 {
3727 elmat(te_ndof1+i, tr_ndof1+j) += w * te_shape2(i) * tr_shape2(j);
3728 }
3729
3730 for (int i = 0; i < te_ndof1; i++)
3731 for (int j = 0; j < tr_ndof2; j++)
3732 {
3733 elmat(i, tr_ndof1+j) -= w * te_shape1(i) * tr_shape2(j);
3734 }
3735 }
3736 }
3737 }
3738}
3739
3741 Geometry::Type geom, int order, const ElementTransformation &T)
3742{
3743 return IntRules.Get(geom, T.OrderW() + 2*order);
3744}
3745
3747 Geometry::Type geom, int order, const FaceElementTransformations &T)
3748{
3749 return GetRule(geom, order, *T.Elem1);
3750}
3751
3753 const FiniteElement &el1, const FiniteElement &el2,
3755{
3756 int ndof1, ndof2, ndofs;
3757 bool kappa_is_nonzero = (kappa != 0.);
3758 real_t w, wq = 0.0;
3759
3760 dim = el1.GetDim();
3761 ndof1 = el1.GetDof();
3762
3763 nor.SetSize(dim);
3764 nh.SetSize(dim);
3765 ni.SetSize(dim);
3766 adjJ.SetSize(dim);
3767 if (MQ)
3768 {
3769 mq.SetSize(dim);
3770 }
3771
3772 shape1.SetSize(ndof1);
3773 dshape1.SetSize(ndof1, dim);
3774 dshape1dn.SetSize(ndof1);
3775 if (Trans.Elem2No >= 0)
3776 {
3777 ndof2 = el2.GetDof();
3778 shape2.SetSize(ndof2);
3779 dshape2.SetSize(ndof2, dim);
3780 dshape2dn.SetSize(ndof2);
3781 }
3782 else
3783 {
3784 ndof2 = 0;
3785 }
3786
3787 ndofs = ndof1 + ndof2;
3788 elmat.SetSize(ndofs);
3789 elmat = 0.0;
3790 if (kappa_is_nonzero)
3791 {
3792 jmat.SetSize(ndofs);
3793 jmat = 0.;
3794 }
3795
3796 const IntegrationRule *ir = IntRule;
3797 if (ir == NULL)
3798 {
3799 const int order = (ndof2) ? max(el1.GetOrder(),
3800 el2.GetOrder()) : el1.GetOrder();
3801 ir = &GetRule(order, Trans.GetGeometryType());
3802 }
3803
3804 // assemble: < {(Q \nabla u).n},[v] > --> elmat
3805 // kappa < {h^{-1} Q} [u],[v] > --> jmat
3806 for (int p = 0; p < ir->GetNPoints(); p++)
3807 {
3808 const IntegrationPoint &ip = ir->IntPoint(p);
3809
3810 // Set the integration point in the face and the neighboring elements
3811 Trans.SetAllIntPoints(&ip);
3812
3813 // Access the neighboring elements' integration points
3814 // Note: eip2 will only contain valid data if Elem2 exists
3815 const IntegrationPoint &eip1 = Trans.GetElement1IntPoint();
3816 const IntegrationPoint &eip2 = Trans.GetElement2IntPoint();
3817
3818 if (dim == 1)
3819 {
3820 nor(0) = 2*eip1.x - 1.0;
3821 }
3822 else
3823 {
3824 CalcOrtho(Trans.Jacobian(), nor);
3825 }
3826
3827 el1.CalcShape(eip1, shape1);
3828 el1.CalcDShape(eip1, dshape1);
3829 w = ip.weight/Trans.Elem1->Weight();
3830 if (ndof2)
3831 {
3832 w /= 2;
3833 }
3834 if (!MQ)
3835 {
3836 if (Q)
3837 {
3838 w *= Q->Eval(*Trans.Elem1, eip1);
3839 }
3840 ni.Set(w, nor);
3841 }
3842 else
3843 {
3844 nh.Set(w, nor);
3845 MQ->Eval(mq, *Trans.Elem1, eip1);
3847 }
3848 CalcAdjugate(Trans.Elem1->Jacobian(), adjJ);
3849 adjJ.Mult(ni, nh);
3850 if (kappa_is_nonzero)
3851 {
3852 wq = ni * nor;
3853 }
3854 // Note: in the jump term, we use 1/h1 = |nor|/det(J1) which is
3855 // independent of Loc1 and always gives the size of element 1 in
3856 // direction perpendicular to the face. Indeed, for linear transformation
3857 // |nor|=measure(face)/measure(ref. face),
3858 // det(J1)=measure(element)/measure(ref. element),
3859 // and the ratios measure(ref. element)/measure(ref. face) are
3860 // compatible for all element/face pairs.
3861 // For example: meas(ref. tetrahedron)/meas(ref. triangle) = 1/3, and
3862 // for any tetrahedron vol(tet)=(1/3)*height*area(base).
3863 // For interior faces: q_e/h_e=(q1/h1+q2/h2)/2.
3864
3866 for (int i = 0; i < ndof1; i++)
3867 for (int j = 0; j < ndof1; j++)
3868 {
3869 elmat(i, j) += shape1(i) * dshape1dn(j);
3870 }
3871
3872 if (ndof2)
3873 {
3874 el2.CalcShape(eip2, shape2);
3875 el2.CalcDShape(eip2, dshape2);
3876 w = ip.weight/2/Trans.Elem2->Weight();
3877 if (!MQ)
3878 {
3879 if (Q)
3880 {
3881 w *= Q->Eval(*Trans.Elem2, eip2);
3882 }
3883 ni.Set(w, nor);
3884 }
3885 else
3886 {
3887 nh.Set(w, nor);
3888 MQ->Eval(mq, *Trans.Elem2, eip2);
3890 }
3891 CalcAdjugate(Trans.Elem2->Jacobian(), adjJ);
3892 adjJ.Mult(ni, nh);
3893 if (kappa_is_nonzero)
3894 {
3895 wq += ni * nor;
3896 }
3897
3899
3900 for (int i = 0; i < ndof1; i++)
3901 for (int j = 0; j < ndof2; j++)
3902 {
3903 elmat(i, ndof1 + j) += shape1(i) * dshape2dn(j);
3904 }
3905
3906 for (int i = 0; i < ndof2; i++)
3907 for (int j = 0; j < ndof1; j++)
3908 {
3909 elmat(ndof1 + i, j) -= shape2(i) * dshape1dn(j);
3910 }
3911
3912 for (int i = 0; i < ndof2; i++)
3913 for (int j = 0; j < ndof2; j++)
3914 {
3915 elmat(ndof1 + i, ndof1 + j) -= shape2(i) * dshape2dn(j);
3916 }
3917 }
3918
3919 if (kappa_is_nonzero)
3920 {
3921 // only assemble the lower triangular part of jmat
3922 wq *= kappa;
3923 for (int i = 0; i < ndof1; i++)
3924 {
3925 const real_t wsi = wq*shape1(i);
3926 for (int j = 0; j <= i; j++)
3927 {
3928 jmat(i, j) += wsi * shape1(j);
3929 }
3930 }
3931 if (ndof2)
3932 {
3933 for (int i = 0; i < ndof2; i++)
3934 {
3935 const int i2 = ndof1 + i;
3936 const real_t wsi = wq*shape2(i);
3937 for (int j = 0; j < ndof1; j++)
3938 {
3939 jmat(i2, j) -= wsi * shape1(j);
3940 }
3941 for (int j = 0; j <= i; j++)
3942 {
3943 jmat(i2, ndof1 + j) += wsi * shape2(j);
3944 }
3945 }
3946 }
3947 }
3948 }
3949
3950 // elmat := -elmat + sigma*elmat^t + jmat
3951 if (kappa_is_nonzero)
3952 {
3953 for (int i = 0; i < ndofs; i++)
3954 {
3955 for (int j = 0; j < i; j++)
3956 {
3957 real_t aij = elmat(i,j), aji = elmat(j,i), mij = jmat(i,j);
3958 elmat(i,j) = sigma*aji - aij + mij;
3959 elmat(j,i) = sigma*aij - aji + mij;
3960 }
3961 elmat(i,i) = (sigma - 1.)*elmat(i,i) + jmat(i,i);
3962 }
3963 }
3964 else
3965 {
3966 for (int i = 0; i < ndofs; i++)
3967 {
3968 for (int j = 0; j < i; j++)
3969 {
3970 real_t aij = elmat(i,j), aji = elmat(j,i);
3971 elmat(i,j) = sigma*aji - aij;
3972 elmat(j,i) = sigma*aij - aji;
3973 }
3974 elmat(i,i) *= (sigma - 1.);
3975 }
3976 }
3977}
3978
3980 int order, Geometry::Type geom)
3981{
3982 // order is typically the maximum of the order of the left and right elements
3983 // neighboring the given face.
3984 return IntRules.Get(geom, 2*order);
3985}
3986
3988 int order, FaceElementTransformations &T)
3989{
3990 return GetRule(order, T.GetGeometryType());
3991}
3992
3993// static method
3995 const int dim, const int row_ndofs, const int col_ndofs,
3996 const int row_offset, const int col_offset,
3997 const real_t jmatcoef, const Vector &col_nL, const Vector &col_nM,
3998 const Vector &row_shape, const Vector &col_shape,
3999 const Vector &col_dshape_dnM, const DenseMatrix &col_dshape,
4000 DenseMatrix &elmat, DenseMatrix &jmat)
4001{
4002 for (int jm = 0, j = col_offset; jm < dim; ++jm)
4003 {
4004 for (int jdof = 0; jdof < col_ndofs; ++jdof, ++j)
4005 {
4006 const real_t t2 = col_dshape_dnM(jdof);
4007 for (int im = 0, i = row_offset; im < dim; ++im)
4008 {
4009 const real_t t1 = col_dshape(jdof, jm) * col_nL(im);
4010 const real_t t3 = col_dshape(jdof, im) * col_nM(jm);
4011 const real_t tt = t1 + ((im == jm) ? t2 : 0.0) + t3;
4012 for (int idof = 0; idof < row_ndofs; ++idof, ++i)
4013 {
4014 elmat(i, j) += row_shape(idof) * tt;
4015 }
4016 }
4017 }
4018 }
4019
4020 if (jmatcoef == 0.0) { return; }
4021
4022 for (int d = 0; d < dim; ++d)
4023 {
4024 const int jo = col_offset + d*col_ndofs;
4025 const int io = row_offset + d*row_ndofs;
4026 for (int jdof = 0, j = jo; jdof < col_ndofs; ++jdof, ++j)
4027 {
4028 const real_t sj = jmatcoef * col_shape(jdof);
4029 for (int i = max(io,j), idof = i - io; idof < row_ndofs; ++idof, ++i)
4030 {
4031 jmat(i, j) += row_shape(idof) * sj;
4032 }
4033 }
4034 }
4035}
4036
4038 const FiniteElement &el1, const FiniteElement &el2,
4040{
4041#ifdef MFEM_THREAD_SAFE
4042 // For descriptions of these variables, see the class declaration.
4047 Vector nor;
4048 Vector nL1, nL2;
4049 Vector nM1, nM2;
4052#endif
4053
4054 const int dim = el1.GetDim();
4055 const int ndofs1 = el1.GetDof();
4056 const int ndofs2 = (Trans.Elem2No >= 0) ? el2.GetDof() : 0;
4057 const int nvdofs = dim*(ndofs1 + ndofs2);
4058
4059 // Initially 'elmat' corresponds to the term:
4060 // < { sigma(u) . n }, [v] > =
4061 // < { (lambda div(u) I + mu (grad(u) + grad(u)^T)) . n }, [v] >
4062 // But eventually, it's going to be replaced by:
4063 // elmat := -elmat + alpha*elmat^T + jmat
4064 elmat.SetSize(nvdofs);
4065 elmat = 0.;
4066
4067 const bool kappa_is_nonzero = (kappa != 0.0);
4068 if (kappa_is_nonzero)
4069 {
4070 jmat.SetSize(nvdofs);
4071 jmat = 0.;
4072 }
4073
4074 adjJ.SetSize(dim);
4075 shape1.SetSize(ndofs1);
4076 dshape1.SetSize(ndofs1, dim);
4077 dshape1_ps.SetSize(ndofs1, dim);
4078 nor.SetSize(dim);
4079 nL1.SetSize(dim);
4080 nM1.SetSize(dim);
4081 dshape1_dnM.SetSize(ndofs1);
4082
4083 if (ndofs2)
4084 {
4085 shape2.SetSize(ndofs2);
4086 dshape2.SetSize(ndofs2, dim);
4087 dshape2_ps.SetSize(ndofs2, dim);
4088 nL2.SetSize(dim);
4089 nM2.SetSize(dim);
4090 dshape2_dnM.SetSize(ndofs2);
4091 }
4092
4093 const IntegrationRule *ir = IntRule;
4094 if (ir == NULL)
4095 {
4096 // a simple choice for the integration order; is this OK?
4097 const int order = 2 * max(el1.GetOrder(), ndofs2 ? el2.GetOrder() : 0);
4098 ir = &IntRules.Get(Trans.GetGeometryType(), order);
4099 }
4100
4101 for (int pind = 0; pind < ir->GetNPoints(); ++pind)
4102 {
4103 const IntegrationPoint &ip = ir->IntPoint(pind);
4104
4105 // Set the integration point in the face and the neighboring elements
4106 Trans.SetAllIntPoints(&ip);
4107
4108 // Access the neighboring elements' integration points
4109 // Note: eip2 will only contain valid data if Elem2 exists
4110 const IntegrationPoint &eip1 = Trans.GetElement1IntPoint();
4111 const IntegrationPoint &eip2 = Trans.GetElement2IntPoint();
4112
4113 el1.CalcShape(eip1, shape1);
4114 el1.CalcDShape(eip1, dshape1);
4115
4116 CalcAdjugate(Trans.Elem1->Jacobian(), adjJ);
4118
4119 if (dim == 1)
4120 {
4121 nor(0) = 2*eip1.x - 1.0;
4122 }
4123 else
4124 {
4125 CalcOrtho(Trans.Jacobian(), nor);
4126 }
4127
4128 real_t w, wLM;
4129 if (ndofs2)
4130 {
4131 el2.CalcShape(eip2, shape2);
4132 el2.CalcDShape(eip2, dshape2);
4133 CalcAdjugate(Trans.Elem2->Jacobian(), adjJ);
4135
4136 w = ip.weight/2;
4137 const real_t w2 = w / Trans.Elem2->Weight();
4138 const real_t wL2 = w2 * lambda->Eval(*Trans.Elem2, eip2);
4139 const real_t wM2 = w2 * mu->Eval(*Trans.Elem2, eip2);
4140 nL2.Set(wL2, nor);
4141 nM2.Set(wM2, nor);
4142 wLM = (wL2 + 2.0*wM2);
4144 }
4145 else
4146 {
4147 w = ip.weight;
4148 wLM = 0.0;
4149 }
4150
4151 {
4152 const real_t w1 = w / Trans.Elem1->Weight();
4153 const real_t wL1 = w1 * lambda->Eval(*Trans.Elem1, eip1);
4154 const real_t wM1 = w1 * mu->Eval(*Trans.Elem1, eip1);
4155 nL1.Set(wL1, nor);
4156 nM1.Set(wM1, nor);
4157 wLM += (wL1 + 2.0*wM1);
4159 }
4160
4161 const real_t jmatcoef = kappa * (nor*nor) * wLM;
4162
4163 // (1,1) block
4165 dim, ndofs1, ndofs1, 0, 0, jmatcoef, nL1, nM1,
4167
4168 if (ndofs2 == 0) { continue; }
4169
4170 // In both elmat and jmat, shape2 appears only with a minus sign.
4171 shape2.Neg();
4172
4173 // (1,2) block
4175 dim, ndofs1, ndofs2, 0, dim*ndofs1, jmatcoef, nL2, nM2,
4177 // (2,1) block
4179 dim, ndofs2, ndofs1, dim*ndofs1, 0, jmatcoef, nL1, nM1,
4181 // (2,2) block
4183 dim, ndofs2, ndofs2, dim*ndofs1, dim*ndofs1, jmatcoef, nL2, nM2,
4185 }
4186
4187 // elmat := -elmat + alpha*elmat^t + jmat
4188 if (kappa_is_nonzero)
4189 {
4190 for (int i = 0; i < nvdofs; ++i)
4191 {
4192 for (int j = 0; j < i; ++j)
4193 {
4194 real_t aij = elmat(i,j), aji = elmat(j,i), mij = jmat(i,j);
4195 elmat(i,j) = alpha*aji - aij + mij;
4196 elmat(j,i) = alpha*aij - aji + mij;
4197 }
4198 elmat(i,i) = (alpha - 1.)*elmat(i,i) + jmat(i,i);
4199 }
4200 }
4201 else
4202 {
4203 for (int i = 0; i < nvdofs; ++i)
4204 {
4205 for (int j = 0; j < i; ++j)
4206 {
4207 real_t aij = elmat(i,j), aji = elmat(j,i);
4208 elmat(i,j) = alpha*aji - aij;
4209 elmat(j,i) = alpha*aij - aji;
4210 }
4211 elmat(i,i) *= (alpha - 1.);
4212 }
4213 }
4214}
4215
4216
4218 const FiniteElement &trial_face_fe, const FiniteElement &test_fe1,
4219 const FiniteElement &test_fe2, FaceElementTransformations &Trans,
4220 DenseMatrix &elmat)
4221{
4222 int i, j, face_ndof, ndof1, ndof2;
4223 int order;
4224
4225 real_t w;
4226
4227 face_ndof = trial_face_fe.GetDof();
4228 ndof1 = test_fe1.GetDof();
4229
4230 face_shape.SetSize(face_ndof);
4231 shape1.SetSize(ndof1);
4232
4233 if (Trans.Elem2No >= 0)
4234 {
4235 ndof2 = test_fe2.GetDof();
4236 shape2.SetSize(ndof2);
4237 }
4238 else
4239 {
4240 ndof2 = 0;
4241 }
4242
4243 elmat.SetSize(ndof1 + ndof2, face_ndof);
4244 elmat = 0.0;
4245
4246 const IntegrationRule *ir = IntRule;
4247 if (ir == NULL)
4248 {
4249 if (Trans.Elem2No >= 0)
4250 {
4251 order = max(test_fe1.GetOrder(), test_fe2.GetOrder());
4252 }
4253 else
4254 {
4255 order = test_fe1.GetOrder();
4256 }
4257 order += trial_face_fe.GetOrder();
4258 if (trial_face_fe.GetMapType() == FiniteElement::VALUE)
4259 {
4260 order += Trans.OrderW();
4261 }
4262 ir = &IntRules.Get(Trans.GetGeometryType(), order);
4263 }
4264
4265 for (int p = 0; p < ir->GetNPoints(); p++)
4266 {
4267 const IntegrationPoint &ip = ir->IntPoint(p);
4268
4269 // Set the integration point in the face and the neighboring elements
4270 Trans.SetAllIntPoints(&ip);
4271
4272 // Trace finite element shape function
4273 trial_face_fe.CalcShape(ip, face_shape);
4274 // Side 1 finite element shape function
4275 test_fe1.CalcPhysShape(*Trans.Elem1, shape1);
4276 if (ndof2)
4277 {
4278 // Side 2 finite element shape function
4279 test_fe2.CalcPhysShape(*Trans.Elem2, shape2);
4280 }
4281 w = ip.weight;
4282 if (trial_face_fe.GetMapType() == FiniteElement::VALUE)
4283 {
4284 w *= Trans.Weight();
4285 }
4286 face_shape *= w;
4287 for (i = 0; i < ndof1; i++)
4288 for (j = 0; j < face_ndof; j++)
4289 {
4290 elmat(i, j) += shape1(i) * face_shape(j);
4291 }
4292 if (ndof2)
4293 {
4294 // Subtract contribution from side 2
4295 for (i = 0; i < ndof2; i++)
4296 for (j = 0; j < face_ndof; j++)
4297 {
4298 elmat(ndof1+i, j) -= shape2(i) * face_shape(j);
4299 }
4300 }
4301 }
4302}
4303
4305 const FiniteElement &trial_face_fe, const FiniteElement &test_fe1,
4306 const FiniteElement &test_fe2, FaceElementTransformations &Trans,
4307 DenseMatrix &elmat)
4308{
4309 int i, j, face_ndof, ndof1, ndof2, dim;
4310 int order;
4311
4312 MFEM_VERIFY(trial_face_fe.GetMapType() == FiniteElement::VALUE, "");
4313
4314 face_ndof = trial_face_fe.GetDof();
4315 ndof1 = test_fe1.GetDof();
4316 dim = test_fe1.GetDim();
4317
4318 face_shape.SetSize(face_ndof);
4319 normal.SetSize(dim);
4320 shape1.SetSize(ndof1,dim);
4321 shape1_n.SetSize(ndof1);
4322
4323 if (Trans.Elem2No >= 0)
4324 {
4325 ndof2 = test_fe2.GetDof();
4326 shape2.SetSize(ndof2,dim);
4327 shape2_n.SetSize(ndof2);
4328 }
4329 else
4330 {
4331 ndof2 = 0;
4332 }
4333
4334 elmat.SetSize(ndof1 + ndof2, face_ndof);
4335 elmat = 0.0;
4336
4337 const IntegrationRule *ir = IntRule;
4338 if (ir == NULL)
4339 {
4340 if (Trans.Elem2No >= 0)
4341 {
4342 order = max(test_fe1.GetOrder(), test_fe2.GetOrder()) - 1;
4343 }
4344 else
4345 {
4346 order = test_fe1.GetOrder() - 1;
4347 }
4348 order += trial_face_fe.GetOrder();
4349 ir = &IntRules.Get(Trans.GetGeometryType(), order);
4350 }
4351
4352 for (int p = 0; p < ir->GetNPoints(); p++)
4353 {
4354 const IntegrationPoint &ip = ir->IntPoint(p);
4355 IntegrationPoint eip1, eip2;
4356 // Trace finite element shape function
4357 trial_face_fe.CalcShape(ip, face_shape);
4358 Trans.Loc1.Transf.SetIntPoint(&ip);
4359 CalcOrtho(Trans.Loc1.Transf.Jacobian(), normal);
4360 // Side 1 finite element shape function
4361 Trans.Loc1.Transform(ip, eip1);
4362 test_fe1.CalcVShape(eip1, shape1);
4363 shape1.Mult(normal, shape1_n);
4364 if (ndof2)
4365 {
4366 // Side 2 finite element shape function
4367 Trans.Loc2.Transform(ip, eip2);
4368 test_fe2.CalcVShape(eip2, shape2);
4369 Trans.Loc2.Transf.SetIntPoint(&ip);
4370 CalcOrtho(Trans.Loc2.Transf.Jacobian(), normal);
4371 shape2.Mult(normal, shape2_n);
4372 }
4373 face_shape *= ip.weight;
4374 for (i = 0; i < ndof1; i++)
4375 for (j = 0; j < face_ndof; j++)
4376 {
4377 elmat(i, j) += shape1_n(i) * face_shape(j);
4378 }
4379 if (ndof2)
4380 {
4381 // Subtract contribution from side 2
4382 for (i = 0; i < ndof2; i++)
4383 for (j = 0; j < face_ndof; j++)
4384 {
4385 elmat(ndof1+i, j) -= shape2_n(i) * face_shape(j);
4386 }
4387 }
4388 }
4389}
4390
4392 const FiniteElement &trial_face_fe,
4393 const FiniteElement &test_fe,
4395 DenseMatrix &elmat)
4396{
4397 MFEM_VERIFY(test_fe.GetMapType() == FiniteElement::VALUE,
4398 "TraceIntegrator::AssembleTraceFaceMatrix: Test space should be H1");
4399 MFEM_VERIFY(trial_face_fe.GetMapType() == FiniteElement::INTEGRAL,
4400 "TraceIntegrator::AssembleTraceFaceMatrix: Trial space should be RT trace");
4401
4402 int i, j, face_ndof, ndof;
4403 int order;
4404
4405 face_ndof = trial_face_fe.GetDof();
4406 ndof = test_fe.GetDof();
4407
4408 face_shape.SetSize(face_ndof);
4409 shape.SetSize(ndof);
4410
4411 elmat.SetSize(ndof, face_ndof);
4412 elmat = 0.0;
4413
4414 const IntegrationRule *ir = IntRule;
4415 if (ir == NULL)
4416 {
4417 order = test_fe.GetOrder();
4418 order += trial_face_fe.GetOrder();
4419 ir = &IntRules.Get(Trans.GetGeometryType(), order);
4420 }
4421
4422 int iel = Trans.Elem1->ElementNo;
4423 if (iel != elem)
4424 {
4425 MFEM_VERIFY(elem == Trans.Elem2->ElementNo, "Elem != Trans.Elem2->ElementNo");
4426 }
4427
4428 real_t scale = 1.0;
4429 if (iel != elem) { scale = -1.; }
4430 for (int p = 0; p < ir->GetNPoints(); p++)
4431 {
4432 const IntegrationPoint &ip = ir->IntPoint(p);
4433
4434 // Set the integration point in the face and the neighboring elements
4435 Trans.SetAllIntPoints(&ip);
4436 // Trace finite element shape function
4437 trial_face_fe.CalcPhysShape(Trans,face_shape);
4438
4439 // Finite element shape function
4440 ElementTransformation * eltrans = (iel == elem) ? Trans.Elem1 : Trans.Elem2;
4441 test_fe.CalcPhysShape(*eltrans, shape);
4442
4443 face_shape *= Trans.Weight()*ip.weight*scale;
4444 for (i = 0; i < ndof; i++)
4445 {
4446 for (j = 0; j < face_ndof; j++)
4447 {
4448 elmat(i, j) += shape(i) * face_shape(j);
4449 }
4450 }
4451 }
4452}
4453
4455 const FiniteElement &trial_face_fe,
4456 const FiniteElement &test_fe,
4458 DenseMatrix &elmat)
4459{
4460 int i, j, face_ndof, ndof, dim;
4461 int order;
4462
4463 MFEM_VERIFY(test_fe.GetMapType() == FiniteElement::H_DIV,
4464 "NormalTraceIntegrator::AssembleTraceFaceMatrix: Test space should be RT");
4465 MFEM_VERIFY(trial_face_fe.GetMapType() == FiniteElement::VALUE,
4466 "NormalTraceIntegrator::AssembleTraceFaceMatrix: Trial space should be H1 (trace)");
4467
4468 face_ndof = trial_face_fe.GetDof();
4469 ndof = test_fe.GetDof();
4470 dim = test_fe.GetDim();
4471
4472 face_shape.SetSize(face_ndof);
4473 normal.SetSize(dim);
4474 shape.SetSize(ndof,dim);
4475 shape_n.SetSize(ndof);
4476
4477 elmat.SetSize(ndof, face_ndof);
4478 elmat = 0.0;
4479
4480 const IntegrationRule *ir = IntRule;
4481 if (ir == NULL)
4482 {
4483 order = test_fe.GetOrder();
4484 order += trial_face_fe.GetOrder();
4485 ir = &IntRules.Get(Trans.GetGeometryType(), order);
4486 }
4487
4488 int iel = Trans.Elem1->ElementNo;
4489 if (iel != elem)
4490 {
4491 MFEM_VERIFY(elem == Trans.Elem2->ElementNo, "Elem != Trans.Elem2->ElementNo");
4492 }
4493
4494 real_t scale = 1.0;
4495 if (iel != elem) { scale = -1.; }
4496
4497 for (int p = 0; p < ir->GetNPoints(); p++)
4498 {
4499 const IntegrationPoint &ip = ir->IntPoint(p);
4500 Trans.SetAllIntPoints(&ip);
4501 trial_face_fe.CalcPhysShape(Trans, face_shape);
4502 CalcOrtho(Trans.Jacobian(),normal);
4503 ElementTransformation * etrans = (iel == elem) ? Trans.Elem1 : Trans.Elem2;
4504 test_fe.CalcVShape(*etrans, shape);
4505 shape.Mult(normal, shape_n);
4506 face_shape *= ip.weight*scale;
4507
4508 for (i = 0; i < ndof; i++)
4509 {
4510 for (j = 0; j < face_ndof; j++)
4511 {
4512 elmat(i, j) += shape_n(i) * face_shape(j);
4513 }
4514 }
4515 }
4516}
4517
4519 const FiniteElement &trial_face_fe,
4520 const FiniteElement &test_fe,
4522 DenseMatrix &elmat)
4523{
4524
4525 MFEM_VERIFY(test_fe.GetMapType() == FiniteElement::H_CURL,
4526 "TangentTraceIntegrator::AssembleTraceFaceMatrix: Test space should be ND");
4527
4528 int face_ndof, ndof, dim;
4529 int order;
4530 dim = test_fe.GetDim();
4531 if (dim == 3)
4532 {
4533 std::string msg =
4534 "Trial space should be ND face trace and test space should be a ND vector field in 3D ";
4535 MFEM_VERIFY(trial_face_fe.GetMapType() == FiniteElement::H_CURL &&
4536 trial_face_fe.GetDim() == 2 && test_fe.GetDim() == 3, msg);
4537 }
4538 else
4539 {
4540 std::string msg =
4541 "Trial space should be H1 edge trace and test space should be a ND vector field in 2D";
4542 MFEM_VERIFY(trial_face_fe.GetMapType() == FiniteElement::VALUE &&
4543 trial_face_fe.GetDim() == 1 && test_fe.GetDim() == 2, msg);
4544 }
4545 face_ndof = trial_face_fe.GetDof();
4546 ndof = test_fe.GetDof();
4547
4548 int dimc = (dim == 3) ? 3 : 1;
4549
4550 face_shape.SetSize(face_ndof,dimc);
4551 shape_n.SetSize(ndof,dimc);
4552 shape.SetSize(ndof,dim);
4553 normal.SetSize(dim);
4554 DenseMatrix face_shape_n(face_ndof,dimc);
4555
4556 elmat.SetSize(ndof, face_ndof);
4557 elmat = 0.0;
4558
4559 const IntegrationRule *ir = IntRule;
4560 if (ir == NULL)
4561 {
4562 order = test_fe.GetOrder();
4563 order += trial_face_fe.GetOrder();
4564 ir = &IntRules.Get(Trans.GetGeometryType(), order);
4565 }
4566
4567 int iel = Trans.Elem1->ElementNo;
4568 if (iel != elem)
4569 {
4570 MFEM_VERIFY(elem == Trans.Elem2->ElementNo, "Elem != Trans.Elem2->ElementNo");
4571 }
4572
4573 real_t scale = 1.0;
4574 if (iel != elem) { scale = -1.; }
4575 for (int p = 0; p < ir->GetNPoints(); p++)
4576 {
4577 const IntegrationPoint &ip = ir->IntPoint(p);
4578 // Set the integration point in the face and the neighboring elements
4579 Trans.SetAllIntPoints(&ip);
4580 // Trace finite element shape function
4581 if (dim == 3)
4582 {
4583 trial_face_fe.CalcVShape(Trans,face_shape);
4584 }
4585 else
4586 {
4587 face_shape.GetColumnReference(0,temp);
4588 trial_face_fe.CalcPhysShape(Trans,temp);
4589 }
4590 CalcOrtho(Trans.Jacobian(),normal);
4591 ElementTransformation * eltrans = (iel == elem) ? Trans.Elem1 : Trans.Elem2;
4592 test_fe.CalcVShape(*eltrans, shape);
4593
4594 // rotate
4595 cross_product(normal, shape, shape_n);
4596
4597 const real_t w = scale*ip.weight;
4598 AddMult_a_ABt(w,shape_n, face_shape, elmat);
4599 }
4600}
4601
4603 const FiniteElement &dom_fe, const FiniteElement &ran_fe,
4604 ElementTransformation &Trans, DenseMatrix &elmat)
4605{
4606 int spaceDim = Trans.GetSpaceDim();
4607 elmat.SetSize(ran_fe.GetDof(), spaceDim*dom_fe.GetDof());
4608 Vector n(spaceDim), shape(dom_fe.GetDof());
4609
4610 const IntegrationRule &ran_nodes = ran_fe.GetNodes();
4611 for (int i = 0; i < ran_nodes.Size(); i++)
4612 {
4613 const IntegrationPoint &ip = ran_nodes.IntPoint(i);
4614 Trans.SetIntPoint(&ip);
4615 CalcOrtho(Trans.Jacobian(), n);
4616 dom_fe.CalcShape(ip, shape);
4617 for (int j = 0; j < shape.Size(); j++)
4618 {
4619 for (int d = 0; d < spaceDim; d++)
4620 {
4621 elmat(i, j+d*shape.Size()) = shape(j)*n(d);
4622 }
4623 }
4624 }
4625}
4626
4627
4628namespace internal
4629{
4630
4631// Scalar shape functions scaled by scalar coefficient.
4632// Used in the implementation of class ScalarProductInterpolator below.
4633struct ShapeCoefficient : public VectorCoefficient
4634{
4635 Coefficient &Q;
4636 const FiniteElement &fe;
4637
4638 ShapeCoefficient(Coefficient &q, const FiniteElement &fe_)
4639 : VectorCoefficient(fe_.GetDof()), Q(q), fe(fe_) { }
4640
4642 void Eval(Vector &V, ElementTransformation &T,
4643 const IntegrationPoint &ip) override
4644 {
4645 V.SetSize(vdim);
4646 fe.CalcPhysShape(T, V);
4647 V *= Q.Eval(T, ip);
4648 }
4649};
4650
4651}
4652
4653void
4655 const FiniteElement &ran_fe,
4656 ElementTransformation &Trans,
4657 DenseMatrix &elmat)
4658{
4659 internal::ShapeCoefficient dom_shape_coeff(*Q, dom_fe);
4660
4661 elmat.SetSize(ran_fe.GetDof(),dom_fe.GetDof());
4662
4663 Vector elmat_as_vec(elmat.Data(), ran_fe.GetDof()*dom_fe.GetDof());
4664
4665 ran_fe.Project(dom_shape_coeff, Trans, elmat_as_vec);
4666}
4667
4668
4669void
4671 const FiniteElement &dom_fe,
4672 const FiniteElement &ran_fe,
4673 ElementTransformation &Trans,
4674 DenseMatrix &elmat)
4675{
4676 // Vector shape functions scaled by scalar coefficient
4677 struct VShapeCoefficient : public MatrixCoefficient
4678 {
4679 Coefficient &Q;
4680 const FiniteElement &fe;
4681
4682 VShapeCoefficient(Coefficient &q, const FiniteElement &fe_, int sdim)
4683 : MatrixCoefficient(fe_.GetDof(), sdim), Q(q), fe(fe_) { }
4684
4685 void Eval(DenseMatrix &M, ElementTransformation &T,
4686 const IntegrationPoint &ip) override
4687 {
4688 M.SetSize(height, width);
4689 fe.CalcPhysVShape(T, M);
4690 M *= Q.Eval(T, ip);
4691 }
4692 };
4693
4694 VShapeCoefficient dom_shape_coeff(*Q, dom_fe, Trans.GetSpaceDim());
4695
4696 elmat.SetSize(ran_fe.GetDof(),dom_fe.GetDof());
4697
4698 Vector elmat_as_vec(elmat.Data(), ran_fe.GetDof()*dom_fe.GetDof());
4699
4700 ran_fe.ProjectMatrixCoefficient(dom_shape_coeff, Trans, elmat_as_vec);
4701}
4702
4703
4704void
4706 const FiniteElement &dom_fe,
4707 const FiniteElement &ran_fe,
4708 ElementTransformation &Trans,
4709 DenseMatrix &elmat)
4710{
4711 // Scalar shape functions scaled by vector coefficient
4712 struct VecShapeCoefficient : public MatrixCoefficient
4713 {
4715 const FiniteElement &fe;
4716 Vector vc, shape;
4717
4718 VecShapeCoefficient(VectorCoefficient &vq, const FiniteElement &fe_)
4719 : MatrixCoefficient(fe_.GetDof(), vq.GetVDim()), VQ(vq), fe(fe_),
4720 vc(width), shape(height) { }
4721
4722 void Eval(DenseMatrix &M, ElementTransformation &T,
4723 const IntegrationPoint &ip) override
4724 {
4725 M.SetSize(height, width);
4726 VQ.Eval(vc, T, ip);
4727 fe.CalcPhysShape(T, shape);
4728 MultVWt(shape, vc, M);
4729 }
4730 };
4731
4732 VecShapeCoefficient dom_shape_coeff(*VQ, dom_fe);
4733
4734 elmat.SetSize(ran_fe.GetDof(),dom_fe.GetDof());
4735
4736 Vector elmat_as_vec(elmat.Data(), ran_fe.GetDof()*dom_fe.GetDof());
4737
4738 ran_fe.ProjectMatrixCoefficient(dom_shape_coeff, Trans, elmat_as_vec);
4739}
4740
4741
4742void
4744 const FiniteElement &dom_fe,
4745 const FiniteElement &ran_fe,
4746 ElementTransformation &Trans,
4747 DenseMatrix &elmat)
4748{
4749 // Vector coefficient product with vector shape functions
4750 struct VCrossVShapeCoefficient : public VectorCoefficient
4751 {
4753 const FiniteElement &fe;
4754 DenseMatrix vshape;
4755 Vector vc;
4756
4757 VCrossVShapeCoefficient(VectorCoefficient &vq, const FiniteElement &fe_)
4758 : VectorCoefficient(fe_.GetDof()), VQ(vq), fe(fe_),
4759 vshape(vdim, vq.GetVDim()), vc(vq.GetVDim()) { }
4760
4761 using VectorCoefficient::Eval;
4762 void Eval(Vector &V, ElementTransformation &T,
4763 const IntegrationPoint &ip) override
4764 {
4765 V.SetSize(vdim);
4766 VQ.Eval(vc, T, ip);
4767 fe.CalcPhysVShape(T, vshape);
4768 for (int k = 0; k < vdim; k++)
4769 {
4770 V(k) = vc(0) * vshape(k,1) - vc(1) * vshape(k,0);
4771 }
4772 }
4773 };
4774
4775 VCrossVShapeCoefficient dom_shape_coeff(*VQ, dom_fe);
4776
4777 elmat.SetSize(ran_fe.GetDof(),dom_fe.GetDof());
4778
4779 Vector elmat_as_vec(elmat.Data(), elmat.Height()*elmat.Width());
4780
4781 ran_fe.Project(dom_shape_coeff, Trans, elmat_as_vec);
4782}
4783
4784void
4786 const FiniteElement &dom_fe,
4787 const FiniteElement &ran_fe,
4788 ElementTransformation &Trans,
4789 DenseMatrix &elmat)
4790{
4791 // Vector coefficient product with vector shape functions
4792 struct VCrossVShapeCoefficient : public MatrixCoefficient
4793 {
4795 const FiniteElement &fe;
4796 DenseMatrix vshape;
4797 Vector vc;
4798
4799 VCrossVShapeCoefficient(VectorCoefficient &vq, const FiniteElement &fe_)
4800 : MatrixCoefficient(fe_.GetDof(), vq.GetVDim()), VQ(vq), fe(fe_),
4801 vshape(height, width), vc(width)
4802 {
4803 MFEM_ASSERT(width == 3, "");
4804 }
4805
4806 void Eval(DenseMatrix &M, ElementTransformation &T,
4807 const IntegrationPoint &ip) override
4808 {
4809 M.SetSize(height, width);
4810 VQ.Eval(vc, T, ip);
4811 fe.CalcPhysVShape(T, vshape);
4812 for (int k = 0; k < height; k++)
4813 {
4814 M(k,0) = vc(1) * vshape(k,2) - vc(2) * vshape(k,1);
4815 M(k,1) = vc(2) * vshape(k,0) - vc(0) * vshape(k,2);
4816 M(k,2) = vc(0) * vshape(k,1) - vc(1) * vshape(k,0);
4817 }
4818 }
4819 };
4820
4821 VCrossVShapeCoefficient dom_shape_coeff(*VQ, dom_fe);
4822
4823 if (ran_fe.GetRangeType() == FiniteElement::SCALAR)
4824 {
4825 elmat.SetSize(ran_fe.GetDof()*VQ->GetVDim(),dom_fe.GetDof());
4826 }
4827 else
4828 {
4829 elmat.SetSize(ran_fe.GetDof(),dom_fe.GetDof());
4830 }
4831
4832 Vector elmat_as_vec(elmat.Data(), elmat.Height()*elmat.Width());
4833
4834 ran_fe.ProjectMatrixCoefficient(dom_shape_coeff, Trans, elmat_as_vec);
4835}
4836
4837
4838namespace internal
4839{
4840
4841// Vector shape functions dot product with a vector coefficient.
4842// Used in the implementation of class VectorInnerProductInterpolator below.
4843struct VDotVShapeCoefficient : public VectorCoefficient
4844{
4846 const FiniteElement &fe;
4847 DenseMatrix vshape;
4848 Vector vc;
4849
4850 VDotVShapeCoefficient(VectorCoefficient &vq, const FiniteElement &fe_)
4851 : VectorCoefficient(fe_.GetDof()), VQ(vq), fe(fe_),
4852 vshape(vdim, vq.GetVDim()), vc(vq.GetVDim()) { }
4853
4855 void Eval(Vector &V, ElementTransformation &T,
4856 const IntegrationPoint &ip) override
4857 {
4858 V.SetSize(vdim);
4859 VQ.Eval(vc, T, ip);
4860 fe.CalcPhysVShape(T, vshape);
4861 vshape.Mult(vc, V);
4862 }
4863};
4864
4865}
4866
4867void
4869 const FiniteElement &dom_fe,
4870 const FiniteElement &ran_fe,
4871 ElementTransformation &Trans,
4872 DenseMatrix &elmat)
4873{
4874 internal::VDotVShapeCoefficient dom_shape_coeff(*VQ, dom_fe);
4875
4876 elmat.SetSize(ran_fe.GetDof(),dom_fe.GetDof());
4877
4878 Vector elmat_as_vec(elmat.Data(), elmat.Height()*elmat.Width());
4879
4880 ran_fe.Project(dom_shape_coeff, Trans, elmat_as_vec);
4881}
4882
4883}
int Size() const
Return the logical size of the array.
Definition array.hpp:166
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:331
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:122
real_t * GetData() const
Returns the matrix data array. Warning: this method casts away constness.
Definition densemat.hpp:126
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:116
void Reset(real_t *d, int h, int w)
Change the data array and the size of the DenseMatrix.
Definition densemat.hpp:98
void ClearExternalData()
Definition densemat.hpp:103
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
static const IntegrationRule & GetRule(const FiniteElement &trial_fe, const FiniteElement &test_fe)
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.
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:208
Abstract class for all finite elements.
Definition fe_base.hpp:247
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:328
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...
Definition fe_base.hpp:341
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:324
int GetMapType() const
Returns the FiniteElement::MapType of the element describing how reference functions are mapped to ph...
Definition fe_base.hpp:363
int GetRangeType() const
Returns the FiniteElement::RangeType of the element, one of {SCALAR, VECTOR}.
Definition fe_base.hpp:354
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
Definition fe_base.hpp:403
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:334
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:351
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:450
int GetCurlDim() const
Returns the dimension of the curl for vector-valued finite elements.
Definition fe_base.hpp:331
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:337
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:233
@ Uk
Rational polynomials of order k.
Definition fe_base.hpp:236
@ rQk
Refined tensor products of polynomials of order k.
Definition fe_base.hpp:235
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:100
int GetNPoints() const
Returns the number of the points in the integration rule.
Definition intrules.hpp:256
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
Definition intrules.hpp:259
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.
static const IntegrationRule & GetRule(const FiniteElement &trial_fe, const FiniteElement &test_fe, const ElementTransformation &Trans)
void AssembleElementMatrix(const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat) override
MassIntegrator(const IntegrationRule *ir=nullptr)
void AssembleElementMatrix2(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans, DenseMatrix &elmat) override
Base class for Matrix Coefficients that optionally depend on time and space.
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:724
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:66
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
Definition operator.hpp:72
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
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:584
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
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:495
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:492
real_t p(const Vector &x, real_t t)
MFEM_HOST_DEVICE real_t norm(const Complex &z)