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