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