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