MFEM  v4.5.2
Finite element discretization library
gridfunc.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 GridFunction
13 
14 #include "gridfunc.hpp"
15 #include "quadinterpolator.hpp"
16 #include "../mesh/nurbs.hpp"
17 #include "../general/text.hpp"
18 
19 #ifdef MFEM_USE_MPI
20 #include "pfespace.hpp"
21 #endif
22 
23 #include <limits>
24 #include <cstring>
25 #include <string>
26 #include <cmath>
27 #include <iostream>
28 #include <algorithm>
29 
30 
31 namespace mfem
32 {
33 
34 using namespace std;
35 
36 GridFunction::GridFunction(Mesh *m, std::istream &input)
37  : Vector()
38 {
39  // Grid functions are stored on the device
40  UseDevice(true);
41 
42  fes = new FiniteElementSpace;
43  fec = fes->Load(m, input);
44 
45  skip_comment_lines(input, '#');
46  istream::int_type next_char = input.peek();
47  if (next_char == 'N') // First letter of "NURBS_patches"
48  {
49  string buff;
50  getline(input, buff);
51  filter_dos(buff);
52  if (buff == "NURBS_patches")
53  {
54  MFEM_VERIFY(fes->GetNURBSext(),
55  "NURBS_patches requires NURBS FE space");
56  fes->GetNURBSext()->LoadSolution(input, *this);
57  }
58  else
59  {
60  MFEM_ABORT("unknown section: " << buff);
61  }
62  }
63  else
64  {
65  Vector::Load(input, fes->GetVSize());
66 
67  // if the mesh is a legacy (v1.1) NC mesh, it has old vertex ordering
68  if (fes->Nonconforming() &&
70  {
72  }
73  }
75 }
76 
77 GridFunction::GridFunction(Mesh *m, GridFunction *gf_array[], int num_pieces)
78 {
79  UseDevice(true);
80 
81  // all GridFunctions must have the same FE collection, vdim, ordering
82  int vdim, ordering;
83 
84  fes = gf_array[0]->FESpace();
86  vdim = fes->GetVDim();
87  ordering = fes->GetOrdering();
88  fes = new FiniteElementSpace(m, fec, vdim, ordering);
89  SetSize(fes->GetVSize());
90 
91  if (m->NURBSext)
92  {
93  m->NURBSext->MergeGridFunctions(gf_array, num_pieces, *this);
94  return;
95  }
96 
97  int g_ndofs = fes->GetNDofs();
98  int g_nvdofs = fes->GetNVDofs();
99  int g_nedofs = fes->GetNEDofs();
100  int g_nfdofs = fes->GetNFDofs();
101  int g_nddofs = g_ndofs - (g_nvdofs + g_nedofs + g_nfdofs);
102  int vi, ei, fi, di;
103  vi = ei = fi = di = 0;
104  for (int i = 0; i < num_pieces; i++)
105  {
106  FiniteElementSpace *l_fes = gf_array[i]->FESpace();
107  int l_ndofs = l_fes->GetNDofs();
108  int l_nvdofs = l_fes->GetNVDofs();
109  int l_nedofs = l_fes->GetNEDofs();
110  int l_nfdofs = l_fes->GetNFDofs();
111  int l_nddofs = l_ndofs - (l_nvdofs + l_nedofs + l_nfdofs);
112  const double *l_data = gf_array[i]->GetData();
113  double *g_data = data;
114  if (ordering == Ordering::byNODES)
115  {
116  for (int d = 0; d < vdim; d++)
117  {
118  memcpy(g_data+vi, l_data, l_nvdofs*sizeof(double));
119  l_data += l_nvdofs;
120  g_data += g_nvdofs;
121  memcpy(g_data+ei, l_data, l_nedofs*sizeof(double));
122  l_data += l_nedofs;
123  g_data += g_nedofs;
124  memcpy(g_data+fi, l_data, l_nfdofs*sizeof(double));
125  l_data += l_nfdofs;
126  g_data += g_nfdofs;
127  memcpy(g_data+di, l_data, l_nddofs*sizeof(double));
128  l_data += l_nddofs;
129  g_data += g_nddofs;
130  }
131  }
132  else
133  {
134  memcpy(g_data+vdim*vi, l_data, l_nvdofs*sizeof(double)*vdim);
135  l_data += vdim*l_nvdofs;
136  g_data += vdim*g_nvdofs;
137  memcpy(g_data+vdim*ei, l_data, l_nedofs*sizeof(double)*vdim);
138  l_data += vdim*l_nedofs;
139  g_data += vdim*g_nedofs;
140  memcpy(g_data+vdim*fi, l_data, l_nfdofs*sizeof(double)*vdim);
141  l_data += vdim*l_nfdofs;
142  g_data += vdim*g_nfdofs;
143  memcpy(g_data+vdim*di, l_data, l_nddofs*sizeof(double)*vdim);
144  l_data += vdim*l_nddofs;
145  g_data += vdim*g_nddofs;
146  }
147  vi += l_nvdofs;
148  ei += l_nedofs;
149  fi += l_nfdofs;
150  di += l_nddofs;
151  }
153 }
154 
156 {
157  if (fec)
158  {
159  delete fes;
160  delete fec;
161  fec = NULL;
162  }
163 }
164 
166 {
167  if (fes->GetSequence() == fes_sequence)
168  {
169  return; // space and grid function are in sync, no-op
170  }
171  // it seems we cannot use the following, due to FESpace::Update(false)
172  /*if (fes->GetSequence() != fes_sequence + 1)
173  {
174  MFEM_ABORT("Error in update sequence. GridFunction needs to be updated "
175  "right after the space is updated.");
176  }*/
178 
179  const Operator *T = fes->GetUpdateOperator();
180  if (T)
181  {
182  Vector old_data;
183  old_data.Swap(*this);
184  SetSize(T->Height());
185  UseDevice(true);
186  T->Mult(old_data, *this);
187  }
188  else
189  {
190  SetSize(fes->GetVSize());
191  }
192 
193  if (t_vec.Size() > 0) { SetTrueVector(); }
194 }
195 
197 {
198  if (f != fes) { Destroy(); }
199  fes = f;
200  SetSize(fes->GetVSize());
202 }
203 
205 {
206  if (f != fes) { Destroy(); }
207  fes = f;
208  NewDataAndSize(v, fes->GetVSize());
210 }
211 
213 {
214  MFEM_ASSERT(v.Size() >= v_offset + f->GetVSize(), "");
215  if (f != fes) { Destroy(); }
216  fes = f;
217  v.UseDevice(true);
218  this->Vector::MakeRef(v, v_offset, fes->GetVSize());
220 }
221 
223 {
224  if (IsIdentityProlongation(f->GetProlongationMatrix()))
225  {
226  MakeRef(f, tv);
228  }
229  else
230  {
231  SetSpace(f); // works in parallel
232  t_vec.NewDataAndSize(tv, f->GetTrueVSize());
233  }
234 }
235 
237 {
238  tv.UseDevice(true);
239  if (IsIdentityProlongation(f->GetProlongationMatrix()))
240  {
241  MakeRef(f, tv, tv_offset);
242  t_vec.NewMemoryAndSize(data, size, false);
243  }
244  else
245  {
246  MFEM_ASSERT(tv.Size() >= tv_offset + f->GetTrueVSize(), "");
247  SetSpace(f); // works in parallel
248  t_vec.MakeRef(tv, tv_offset, f->GetTrueVSize());
249  }
250 }
251 
253  GridFunction &flux,
254  Array<int>& count,
255  bool wcoef,
256  int subdomain)
257 {
258  GridFunction &u = *this;
259 
260  ElementTransformation *Transf;
261  DofTransformation *udoftrans;
262  DofTransformation *fdoftrans;
263 
264  FiniteElementSpace *ufes = u.FESpace();
265  FiniteElementSpace *ffes = flux.FESpace();
266 
267  int nfe = ufes->GetNE();
268  Array<int> udofs;
269  Array<int> fdofs;
270  Vector ul, fl;
271 
272  flux = 0.0;
273  count = 0;
274 
275  for (int i = 0; i < nfe; i++)
276  {
277  if (subdomain >= 0 && ufes->GetAttribute(i) != subdomain)
278  {
279  continue;
280  }
281 
282  udoftrans = ufes->GetElementVDofs(i, udofs);
283  fdoftrans = ffes->GetElementVDofs(i, fdofs);
284 
285  u.GetSubVector(udofs, ul);
286  if (udoftrans)
287  {
288  udoftrans->InvTransformPrimal(ul);
289  }
290 
291  Transf = ufes->GetElementTransformation(i);
292  blfi.ComputeElementFlux(*ufes->GetFE(i), *Transf, ul,
293  *ffes->GetFE(i), fl, wcoef);
294 
295  if (fdoftrans)
296  {
297  fdoftrans->TransformPrimal(fl);
298  }
299  flux.AddElementVector(fdofs, fl);
300 
302  for (int j = 0; j < fdofs.Size(); j++)
303  {
304  count[fdofs[j]]++;
305  }
306  }
307 }
308 
310  GridFunction &flux, bool wcoef,
311  int subdomain)
312 {
313  Array<int> count(flux.Size());
314 
315  SumFluxAndCount(blfi, flux, count, wcoef, subdomain);
316 
317  // complete averaging
318  for (int i = 0; i < count.Size(); i++)
319  {
320  if (count[i] != 0) { flux(i) /= count[i]; }
321  }
322 }
323 
325 {
326  const FiniteElement *fe;
327  if (!fes->GetNE())
328  {
329  const FiniteElementCollection *fe_coll = fes->FEColl();
330  static const Geometry::Type geoms[3] =
332  fe = fe_coll->
333  FiniteElementForGeometry(geoms[fes->GetMesh()->Dimension()-1]);
334  }
335  else
336  {
337  fe = fes->GetFE(0);
338  }
339  if (!fe || fe->GetRangeType() == FiniteElement::SCALAR)
340  {
341  return fes->GetVDim();
342  }
343  return fes->GetVDim()*std::max(fes->GetMesh()->SpaceDimension(),
344  fe->GetVDim());
345 }
346 
348 {
349  const FiniteElement *fe;
350  if (!fes->GetNE())
351  {
352  static const Geometry::Type geoms[3] =
354  fe = fec->FiniteElementForGeometry(geoms[fes->GetMesh()->Dimension()-1]);
355  }
356  else
357  {
358  fe = fes->GetFE(0);
359  }
360  if (!fe || fe->GetRangeType() == FiniteElement::SCALAR)
361  {
362  return 2 * fes->GetMesh()->SpaceDimension() - 3;
363  }
364  return fes->GetVDim()*fe->GetCurlDim();
365 }
366 
368 {
369  const SparseMatrix *R = fes->GetRestrictionMatrix();
371  {
372  // R is identity
373  tv = *this; // no real copy if 'tv' and '*this' use the same data
374  }
375  else
376  {
377  tv.SetSize(R->Height());
378  R->Mult(*this, tv);
379  }
380 }
381 
383 {
384  MFEM_ASSERT(tv.Size() == fes->GetTrueVSize(), "invalid input");
386  if (!cP)
387  {
388  *this = tv; // no real copy if 'tv' and '*this' use the same data
389  }
390  else
391  {
392  cP->Mult(tv, *this);
393  }
394 }
395 
396 void GridFunction::GetNodalValues(int i, Array<double> &nval, int vdim) const
397 {
398  Array<int> vdofs;
399 
400  int k;
401 
402  DofTransformation * doftrans = fes->GetElementVDofs(i, vdofs);
403  const FiniteElement *FElem = fes->GetFE(i);
404  const IntegrationRule *ElemVert =
406  int dof = FElem->GetDof();
407  int n = ElemVert->GetNPoints();
408  nval.SetSize(n);
409  vdim--;
410  Vector loc_data;
411  GetSubVector(vdofs, loc_data);
412  if (doftrans)
413  {
414  doftrans->InvTransformPrimal(loc_data);
415  }
416 
417  if (FElem->GetRangeType() == FiniteElement::SCALAR)
418  {
419  Vector shape(dof);
420  if (FElem->GetMapType() == FiniteElement::VALUE)
421  {
422  for (k = 0; k < n; k++)
423  {
424  FElem->CalcShape(ElemVert->IntPoint(k), shape);
425  nval[k] = shape * (&loc_data[dof * vdim]);
426  }
427  }
428  else
429  {
431  for (k = 0; k < n; k++)
432  {
433  Tr->SetIntPoint(&ElemVert->IntPoint(k));
434  FElem->CalcPhysShape(*Tr, shape);
435  nval[k] = shape * (&loc_data[dof * vdim]);
436  }
437  }
438  }
439  else
440  {
442  DenseMatrix vshape(dof, FElem->GetDim());
443  for (k = 0; k < n; k++)
444  {
445  Tr->SetIntPoint(&ElemVert->IntPoint(k));
446  FElem->CalcVShape(*Tr, vshape);
447  nval[k] = loc_data * (&vshape(0,vdim));
448  }
449  }
450 }
451 
452 double GridFunction::GetValue(int i, const IntegrationPoint &ip, int vdim)
453 const
454 {
455  Array<int> dofs;
456  DofTransformation * doftrans = fes->GetElementDofs(i, dofs);
457  fes->DofsToVDofs(vdim-1, dofs);
458  Vector DofVal(dofs.Size()), LocVec;
459  const FiniteElement *fe = fes->GetFE(i);
460  if (fe->GetMapType() == FiniteElement::VALUE)
461  {
462  fe->CalcShape(ip, DofVal);
463  }
464  else
465  {
467  Tr->SetIntPoint(&ip);
468  fe->CalcPhysShape(*Tr, DofVal);
469  }
470  GetSubVector(dofs, LocVec);
471  if (doftrans)
472  {
473  doftrans->InvTransformPrimal(LocVec);
474  }
475 
476  return (DofVal * LocVec);
477 }
478 
480  Vector &val) const
481 {
482  const FiniteElement *FElem = fes->GetFE(i);
483  int dof = FElem->GetDof();
484  Array<int> vdofs;
485  DofTransformation * doftrans = fes->GetElementVDofs(i, vdofs);
486  Vector loc_data;
487  GetSubVector(vdofs, loc_data);
488  if (doftrans)
489  {
490  doftrans->InvTransformPrimal(loc_data);
491  }
492  if (FElem->GetRangeType() == FiniteElement::SCALAR)
493  {
494  Vector shape(dof);
495  if (FElem->GetMapType() == FiniteElement::VALUE)
496  {
497  FElem->CalcShape(ip, shape);
498  }
499  else
500  {
502  Tr->SetIntPoint(&ip);
503  FElem->CalcPhysShape(*Tr, shape);
504  }
505  int vdim = fes->GetVDim();
506  val.SetSize(vdim);
507  for (int k = 0; k < vdim; k++)
508  {
509  val(k) = shape * (&loc_data[dof * k]);
510  }
511  }
512  else
513  {
514  int vdim = VectorDim();
515  DenseMatrix vshape(dof, vdim);
517  Tr->SetIntPoint(&ip);
518  FElem->CalcVShape(*Tr, vshape);
519  val.SetSize(vdim);
520  vshape.MultTranspose(loc_data, val);
521  }
522 }
523 
524 void GridFunction::GetValues(int i, const IntegrationRule &ir, Vector &vals,
525  int vdim)
526 const
527 {
528  Array<int> dofs;
529  int n = ir.GetNPoints();
530  vals.SetSize(n);
531  DofTransformation * doftrans = fes->GetElementDofs(i, dofs);
532  fes->DofsToVDofs(vdim-1, dofs);
533  const FiniteElement *FElem = fes->GetFE(i);
534  int dof = FElem->GetDof();
535  Vector DofVal(dof), loc_data(dof);
536  GetSubVector(dofs, loc_data);
537  if (doftrans)
538  {
539  doftrans->InvTransformPrimal(loc_data);
540  }
541  if (FElem->GetMapType() == FiniteElement::VALUE)
542  {
543  for (int k = 0; k < n; k++)
544  {
545  FElem->CalcShape(ir.IntPoint(k), DofVal);
546  vals(k) = DofVal * loc_data;
547  }
548  }
549  else
550  {
552  for (int k = 0; k < n; k++)
553  {
554  Tr->SetIntPoint(&ir.IntPoint(k));
555  FElem->CalcPhysShape(*Tr, DofVal);
556  vals(k) = DofVal * loc_data;
557  }
558  }
559 }
560 
561 void GridFunction::GetValues(int i, const IntegrationRule &ir, Vector &vals,
562  DenseMatrix &tr, int vdim)
563 const
564 {
566  ET = fes->GetElementTransformation(i);
567  ET->Transform(ir, tr);
568 
569  GetValues(i, ir, vals, vdim);
570 }
571 
573  int vdim)
574 const
575 {
576  Array<int> dofs;
577  int n = ir.GetNPoints();
578  laps.SetSize(n);
579  fes->GetElementDofs(i, dofs);
580  fes->DofsToVDofs(vdim-1, dofs);
581  const FiniteElement *FElem = fes->GetFE(i);
583  ET = fes->GetElementTransformation(i);
584  MFEM_ASSERT(FElem->GetMapType() == FiniteElement::VALUE,
585  "invalid FE map type");
586 
587  int dof = FElem->GetDof();
588  Vector DofLap(dof), loc_data(dof);
589  GetSubVector(dofs, loc_data);
590  for (int k = 0; k < n; k++)
591  {
592  const IntegrationPoint &ip = ir.IntPoint(k);
593  ET->SetIntPoint(&ip);
594  FElem->CalcPhysLaplacian(*ET, DofLap);
595  laps(k) = DofLap * loc_data;
596  }
597 }
598 
600  DenseMatrix &tr, int vdim)
601 const
602 {
604  ET = fes->GetElementTransformation(i);
605  ET->Transform(ir, tr);
606 
607  GetLaplacians(i, ir, laps, vdim);
608 }
609 
610 
612  DenseMatrix &hess,
613  int vdim)
614 const
615 {
616 
617  Array<int> dofs;
618  int n = ir.GetNPoints();
619  fes->GetElementDofs(i, dofs);
620  fes->DofsToVDofs(vdim-1, dofs);
621  const FiniteElement *FElem = fes->GetFE(i);
623  ET = fes->GetElementTransformation(i);
624  int dim = FElem->GetDim();
625  int size = (dim*(dim+1))/2;
626 
627  MFEM_ASSERT(FElem->GetMapType() == FiniteElement::VALUE,
628  "invalid FE map type");
629 
630  int dof = FElem->GetDof();
631  DenseMatrix DofHes(dof, size);
632  hess.SetSize(n, size);
633 
634  Vector loc_data(dof);
635  GetSubVector(dofs, loc_data);
636 
637  hess = 0.0;
638  for (int k = 0; k < n; k++)
639  {
640  const IntegrationPoint &ip = ir.IntPoint(k);
641  ET->SetIntPoint(&ip);
642  FElem->CalcPhysHessian(*ET, DofHes);
643 
644  for (int j = 0; j < size; j++)
645  {
646  for (int d = 0; d < dof; d++)
647  {
648  hess(k,j) += DofHes(d,j) * loc_data[d];
649  }
650  }
651  }
652 }
653 
655  DenseMatrix &hess,
656  DenseMatrix &tr, int vdim)
657 const
658 {
660  ET = fes->GetElementTransformation(i);
661  ET->Transform(ir, tr);
662 
663  GetHessians(i, ir, hess, vdim);
664 }
665 
666 
667 int GridFunction::GetFaceValues(int i, int side, const IntegrationRule &ir,
668  Vector &vals, DenseMatrix &tr,
669  int vdim) const
670 {
671  int n, dir;
673 
674  n = ir.GetNPoints();
675  IntegrationRule eir(n); // ---
676  if (side == 2) // automatic choice of side
677  {
678  Transf = fes->GetMesh()->GetFaceElementTransformations(i, 0);
679  if (Transf->Elem2No < 0 ||
680  fes->GetAttribute(Transf->Elem1No) <=
681  fes->GetAttribute(Transf->Elem2No))
682  {
683  dir = 0;
684  }
685  else
686  {
687  dir = 1;
688  }
689  }
690  else
691  {
692  if (side == 1 && !fes->GetMesh()->FaceIsInterior(i))
693  {
694  dir = 0;
695  }
696  else
697  {
698  dir = side;
699  }
700  }
701  if (dir == 0)
702  {
703  Transf = fes->GetMesh()->GetFaceElementTransformations(i, 4);
704  Transf->Loc1.Transform(ir, eir);
705  GetValues(Transf->Elem1No, eir, vals, tr, vdim);
706  }
707  else
708  {
709  Transf = fes->GetMesh()->GetFaceElementTransformations(i, 8);
710  Transf->Loc2.Transform(ir, eir);
711  GetValues(Transf->Elem2No, eir, vals, tr, vdim);
712  }
713 
714  return dir;
715 }
716 
718  DenseMatrix &vals, DenseMatrix &tr) const
719 {
721  Tr->Transform(ir, tr);
722 
723  GetVectorValues(*Tr, ir, vals);
724 }
725 
726 void be_to_bfe(Geometry::Type geom, int o, const IntegrationPoint &ip,
727  IntegrationPoint &fip)
728 {
729  if (geom == Geometry::TRIANGLE)
730  {
731  if (o == 2)
732  {
733  fip.x = 1.0 - ip.x - ip.y;
734  fip.y = ip.x;
735  }
736  else if (o == 4)
737  {
738  fip.x = ip.y;
739  fip.y = 1.0 - ip.x - ip.y;
740  }
741  else
742  {
743  fip.x = ip.x;
744  fip.y = ip.y;
745  }
746  fip.z = ip.z;
747  }
748  else
749  {
750  if (o == 2)
751  {
752  fip.x = ip.y;
753  fip.y = 1.0 - ip.x;
754  }
755  else if (o == 4)
756  {
757  fip.x = 1.0 - ip.x;
758  fip.y = 1.0 - ip.y;
759  }
760  else if (o == 6)
761  {
762  fip.x = 1.0 - ip.y;
763  fip.y = ip.x;
764  }
765  else
766  {
767  fip.x = ip.x;
768  fip.y = ip.y;
769  }
770  fip.z = ip.z;
771  }
772  fip.weight = ip.weight;
773  fip.index = ip.index;
774 }
775 
777  const IntegrationPoint &ip,
778  int comp, Vector *tr) const
779 {
780  if (tr)
781  {
782  T.SetIntPoint(&ip);
783  T.Transform(ip, *tr);
784  }
785 
786  const FiniteElement * fe = NULL;
787  Array<int> dofs;
788 
789  switch (T.ElementType)
790  {
792  fe = fes->GetFE(T.ElementNo);
793  fes->GetElementDofs(T.ElementNo, dofs);
794  break;
796  if (fes->FEColl()->GetContType() ==
798  {
799  fe = fes->GetEdgeElement(T.ElementNo);
800  fes->GetEdgeDofs(T.ElementNo, dofs);
801  }
802  else
803  {
804  MFEM_ABORT("GridFunction::GetValue: Field continuity type \""
805  << fes->FEColl()->GetContType() << "\" not supported "
806  << "on mesh edges.");
807  return NAN;
808  }
809  break;
811  if (fes->FEColl()->GetContType() ==
813  {
814  fe = fes->GetFaceElement(T.ElementNo);
815  fes->GetFaceDofs(T.ElementNo, dofs);
816  }
817  else
818  {
819  MFEM_ABORT("GridFunction::GetValue: Field continuity type \""
820  << fes->FEColl()->GetContType() << "\" not supported "
821  << "on mesh faces.");
822  return NAN;
823  }
824  break;
826  {
827  if (fes->FEColl()->GetContType() ==
829  {
830  // This is a continuous field so we can evaluate it on the boundary.
831  fe = fes->GetBE(T.ElementNo);
832  fes->GetBdrElementDofs(T.ElementNo, dofs);
833  }
834  else
835  {
836  // This is a discontinuous field which cannot be evaluated on the
837  // boundary so we'll evaluate it in the neighboring element.
839  fes->GetMesh()->GetBdrFaceTransformations(T.ElementNo);
840 
841  // Boundary elements and Boundary Faces may have different
842  // orientations so adjust the integration point if necessary.
843  int o = 0;
844  if (fes->GetMesh()->Dimension() == 3)
845  {
846  int f;
847  fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
848  }
849 
850  IntegrationPoint fip;
851  be_to_bfe(FET->GetGeometryType(), o, ip, fip);
852 
853  // Compute and set the point in element 1 from fip
854  FET->SetAllIntPoints(&fip);
856  return GetValue(T1, T1.GetIntPoint(), comp);
857  }
858  }
859  break;
861  {
863  dynamic_cast<FaceElementTransformations *>(&T);
864 
865  // Evaluate in neighboring element for both continuous and
866  // discontinuous fields (the integration point in T1 should have
867  // already been set).
869  return GetValue(T1, T1.GetIntPoint(), comp);
870  }
871  default:
872  {
873  MFEM_ABORT("GridFunction::GetValue: Unsupported element type \""
874  << T.ElementType << "\"");
875  return NAN;
876  }
877  }
878 
879  fes->DofsToVDofs(comp-1, dofs);
880  Vector DofVal(dofs.Size()), LocVec;
881  if (fe->GetMapType() == FiniteElement::VALUE)
882  {
883  fe->CalcShape(ip, DofVal);
884  }
885  else
886  {
887  fe->CalcPhysShape(T, DofVal);
888  }
889  GetSubVector(dofs, LocVec);
890 
891  return (DofVal * LocVec);
892 }
893 
895  const IntegrationRule &ir,
896  Vector &vals, int comp,
897  DenseMatrix *tr) const
898 {
899  if (tr)
900  {
901  T.Transform(ir, *tr);
902  }
903 
904  int nip = ir.GetNPoints();
905  vals.SetSize(nip);
906  for (int j = 0; j < nip; j++)
907  {
908  const IntegrationPoint &ip = ir.IntPoint(j);
909  T.SetIntPoint(&ip);
910  vals[j] = GetValue(T, ip, comp);
911  }
912 }
913 
915  const IntegrationPoint &ip,
916  Vector &val, Vector *tr) const
917 {
918  if (tr)
919  {
920  T.SetIntPoint(&ip);
921  T.Transform(ip, *tr);
922  }
923 
924  Array<int> vdofs;
925  const FiniteElement *fe = NULL;
926  DofTransformation * doftrans = NULL;
927 
928  switch (T.ElementType)
929  {
931  doftrans = fes->GetElementVDofs(T.ElementNo, vdofs);
932  fe = fes->GetFE(T.ElementNo);
933  break;
935  if (fes->FEColl()->GetContType() ==
937  {
938  fe = fes->GetEdgeElement(T.ElementNo);
939  fes->GetEdgeVDofs(T.ElementNo, vdofs);
940  }
941  else
942  {
943  MFEM_ABORT("GridFunction::GetVectorValue: Field continuity type \""
944  << fes->FEColl()->GetContType() << "\" not supported "
945  << "on mesh edges.");
946  return;
947  }
948  break;
950  if (fes->FEColl()->GetContType() ==
952  {
953  fe = fes->GetFaceElement(T.ElementNo);
954  fes->GetFaceVDofs(T.ElementNo, vdofs);
955  }
956  else
957  {
958  MFEM_ABORT("GridFunction::GetVectorValue: Field continuity type \""
959  << fes->FEColl()->GetContType() << "\" not supported "
960  << "on mesh faces.");
961  return;
962  }
963  break;
965  {
966  if (fes->FEColl()->GetContType() ==
968  {
969  // This is a continuous field so we can evaluate it on the boundary.
970  fes->GetBdrElementVDofs(T.ElementNo, vdofs);
971  fe = fes->GetBE(T.ElementNo);
972  }
973  else
974  {
975  // This is a discontinuous vector field which cannot be evaluated on
976  // the boundary so we'll evaluate it in the neighboring element.
978  fes->GetMesh()->GetBdrFaceTransformations(T.ElementNo);
979 
980  // Boundary elements and Boundary Faces may have different
981  // orientations so adjust the integration point if necessary.
982  int o = 0;
983  if (fes->GetMesh()->Dimension() == 3)
984  {
985  int f;
986  fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
987  }
988 
989  IntegrationPoint fip;
990  be_to_bfe(FET->GetGeometryType(), o, ip, fip);
991 
992  // Compute and set the point in element 1 from fip
993  FET->SetAllIntPoints(&fip);
995  return GetVectorValue(T1, T1.GetIntPoint(), val);
996  }
997  }
998  break;
1000  {
1002  dynamic_cast<FaceElementTransformations *>(&T);
1003 
1004  // Evaluate in neighboring element for both continuous and
1005  // discontinuous fields (the integration point in T1 should have
1006  // already been set).
1008  return GetVectorValue(T1, T1.GetIntPoint(), val);
1009  }
1010  default:
1011  {
1012  MFEM_ABORT("GridFunction::GetVectorValue: Unsupported element type \""
1013  << T.ElementType << "\"");
1014  if (val.Size() > 0) { val = NAN; }
1015  return;
1016  }
1017  }
1018 
1019  int dof = fe->GetDof();
1020  Vector loc_data;
1021  GetSubVector(vdofs, loc_data);
1022  if (doftrans)
1023  {
1024  doftrans->InvTransformPrimal(loc_data);
1025  }
1026  if (fe->GetRangeType() == FiniteElement::SCALAR)
1027  {
1028  Vector shape(dof);
1029  if (fe->GetMapType() == FiniteElement::VALUE)
1030  {
1031  fe->CalcShape(ip, shape);
1032  }
1033  else
1034  {
1035  fe->CalcPhysShape(T, shape);
1036  }
1037  int vdim = fes->GetVDim();
1038  val.SetSize(vdim);
1039  for (int k = 0; k < vdim; k++)
1040  {
1041  val(k) = shape * (&loc_data[dof * k]);
1042  }
1043  }
1044  else
1045  {
1046  int spaceDim = fes->GetMesh()->SpaceDimension();
1047  int vdim = std::max(spaceDim, fe->GetVDim());
1048  DenseMatrix vshape(dof, vdim);
1049  fe->CalcVShape(T, vshape);
1050  val.SetSize(vdim);
1051  vshape.MultTranspose(loc_data, val);
1052  }
1053 }
1054 
1056  const IntegrationRule &ir,
1057  DenseMatrix &vals,
1058  DenseMatrix *tr) const
1059 {
1060  if (tr)
1061  {
1062  T.Transform(ir, *tr);
1063  }
1064 
1065  const FiniteElement *FElem = fes->GetFE(T.ElementNo);
1066  int dof = FElem->GetDof();
1067 
1068  Array<int> vdofs;
1069  DofTransformation * doftrans = fes->GetElementVDofs(T.ElementNo, vdofs);
1070  Vector loc_data;
1071  GetSubVector(vdofs, loc_data);
1072  if (doftrans)
1073  {
1074  doftrans->InvTransformPrimal(loc_data);
1075  }
1076 
1077  int nip = ir.GetNPoints();
1078 
1079  if (FElem->GetRangeType() == FiniteElement::SCALAR)
1080  {
1081  Vector shape(dof);
1082  int vdim = fes->GetVDim();
1083  vals.SetSize(vdim, nip);
1084  for (int j = 0; j < nip; j++)
1085  {
1086  const IntegrationPoint &ip = ir.IntPoint(j);
1087  T.SetIntPoint(&ip);
1088  FElem->CalcPhysShape(T, shape);
1089 
1090  for (int k = 0; k < vdim; k++)
1091  {
1092  vals(k,j) = shape * (&loc_data[dof * k]);
1093  }
1094  }
1095  }
1096  else
1097  {
1098  int spaceDim = fes->GetMesh()->SpaceDimension();
1099  int vdim = std::max(spaceDim, FElem->GetVDim());
1100  DenseMatrix vshape(dof, vdim);
1101 
1102  vals.SetSize(vdim, nip);
1103  Vector val_j;
1104 
1105  for (int j = 0; j < nip; j++)
1106  {
1107  const IntegrationPoint &ip = ir.IntPoint(j);
1108  T.SetIntPoint(&ip);
1109  FElem->CalcVShape(T, vshape);
1110 
1111  vals.GetColumnReference(j, val_j);
1112  vshape.MultTranspose(loc_data, val_j);
1113  }
1114  }
1115 }
1116 
1118  int i, int side, const IntegrationRule &ir,
1119  DenseMatrix &vals, DenseMatrix &tr) const
1120 {
1121  int n, di;
1123 
1124  n = ir.GetNPoints();
1125  IntegrationRule eir(n); // ---
1126  Transf = fes->GetMesh()->GetFaceElementTransformations(i, 0);
1127  if (side == 2)
1128  {
1129  if (Transf->Elem2No < 0 ||
1130  fes->GetAttribute(Transf->Elem1No) <=
1131  fes->GetAttribute(Transf->Elem2No))
1132  {
1133  di = 0;
1134  }
1135  else
1136  {
1137  di = 1;
1138  }
1139  }
1140  else
1141  {
1142  di = side;
1143  }
1144  if (di == 0)
1145  {
1146  Transf = fes->GetMesh()->GetFaceElementTransformations(i, 5);
1147  Transf->Loc1.Transform(ir, eir);
1148  GetVectorValues(*Transf->Elem1, eir, vals, &tr);
1149  }
1150  else
1151  {
1152  Transf = fes->GetMesh()->GetFaceElementTransformations(i, 10);
1153  Transf->Loc2.Transform(ir, eir);
1154  GetVectorValues(*Transf->Elem2, eir, vals, &tr);
1155  }
1156 
1157  return di;
1158 }
1159 
1161 {
1162  // Without averaging ...
1163 
1164  const FiniteElementSpace *orig_fes = orig_func.FESpace();
1165  DofTransformation * doftrans;
1166  DofTransformation * orig_doftrans;
1167  Array<int> vdofs, orig_vdofs;
1168  Vector shape, loc_values, orig_loc_values;
1169  int i, j, d, ne, dof, odof, vdim;
1170 
1171  ne = fes->GetNE();
1172  vdim = fes->GetVDim();
1173  for (i = 0; i < ne; i++)
1174  {
1175  doftrans = fes->GetElementVDofs(i, vdofs);
1176  orig_doftrans = orig_fes->GetElementVDofs(i, orig_vdofs);
1177  orig_func.GetSubVector(orig_vdofs, orig_loc_values);
1178  if (orig_doftrans)
1179  {
1180  orig_doftrans->InvTransformPrimal(orig_loc_values);
1181  }
1182  const FiniteElement *fe = fes->GetFE(i);
1183  const FiniteElement *orig_fe = orig_fes->GetFE(i);
1184  dof = fe->GetDof();
1185  odof = orig_fe->GetDof();
1186  loc_values.SetSize(dof * vdim);
1187  shape.SetSize(odof);
1188  const IntegrationRule &ir = fe->GetNodes();
1189  for (j = 0; j < dof; j++)
1190  {
1191  const IntegrationPoint &ip = ir.IntPoint(j);
1192  orig_fe->CalcShape(ip, shape);
1193  for (d = 0; d < vdim; d++)
1194  {
1195  loc_values(d*dof+j) = shape * (&orig_loc_values[d * odof]);
1196  }
1197  }
1198  if (doftrans)
1199  {
1200  doftrans->TransformPrimal(loc_values);
1201  }
1202  SetSubVector(vdofs, loc_values);
1203  }
1204 }
1205 
1207 {
1208  // Without averaging ...
1209 
1210  const FiniteElementSpace *orig_fes = orig_func.FESpace();
1211  // DofTransformation * doftrans;
1212  // DofTransformation * orig_doftrans;
1213  Array<int> vdofs, orig_vdofs;
1214  Vector shape, loc_values, loc_values_t, orig_loc_values, orig_loc_values_t;
1215  int i, j, d, nbe, dof, odof, vdim;
1216 
1217  nbe = fes->GetNBE();
1218  vdim = fes->GetVDim();
1219  for (i = 0; i < nbe; i++)
1220  {
1221  fes->GetBdrElementVDofs(i, vdofs);
1222  orig_fes->GetBdrElementVDofs(i, orig_vdofs);
1223  orig_func.GetSubVector(orig_vdofs, orig_loc_values);
1224  const FiniteElement *fe = fes->GetBE(i);
1225  const FiniteElement *orig_fe = orig_fes->GetBE(i);
1226  dof = fe->GetDof();
1227  odof = orig_fe->GetDof();
1228  loc_values.SetSize(dof * vdim);
1229  shape.SetSize(odof);
1230  const IntegrationRule &ir = fe->GetNodes();
1231  for (j = 0; j < dof; j++)
1232  {
1233  const IntegrationPoint &ip = ir.IntPoint(j);
1234  orig_fe->CalcShape(ip, shape);
1235  for (d = 0; d < vdim; d++)
1236  {
1237  loc_values(d*dof+j) = shape * (&orig_loc_values[d * odof]);
1238  }
1239  }
1240  SetSubVector(vdofs, loc_values);
1241  }
1242 }
1243 
1245  int i, const IntegrationRule &ir, DenseMatrix &vals,
1246  DenseMatrix &tr, int comp) const
1247 {
1248  Array<int> vdofs;
1249  ElementTransformation *transf;
1250 
1251  int d, k, n, sdim, dof;
1252 
1253  n = ir.GetNPoints();
1254  DofTransformation * doftrans = fes->GetElementVDofs(i, vdofs);
1255  const FiniteElement *fe = fes->GetFE(i);
1256  dof = fe->GetDof();
1257  sdim = fes->GetMesh()->SpaceDimension();
1258  // int *dofs = &vdofs[comp*dof];
1259  transf = fes->GetElementTransformation(i);
1260  transf->Transform(ir, tr);
1261  vals.SetSize(n, sdim);
1262  DenseMatrix vshape(dof, sdim);
1263  Vector loc_data, val(sdim);
1264  GetSubVector(vdofs, loc_data);
1265  if (doftrans)
1266  {
1267  doftrans->InvTransformPrimal(loc_data);
1268  }
1269  for (k = 0; k < n; k++)
1270  {
1271  const IntegrationPoint &ip = ir.IntPoint(k);
1272  transf->SetIntPoint(&ip);
1273  fe->CalcVShape(*transf, vshape);
1274  vshape.MultTranspose(loc_data, val);
1275  for (d = 0; d < sdim; d++)
1276  {
1277  vals(k,d) = val(d);
1278  }
1279  }
1280 }
1281 
1283 {
1284  if (fes->GetOrdering() == Ordering::byNODES)
1285  {
1286  return;
1287  }
1288 
1289  int i, j, k;
1290  int vdim = fes->GetVDim();
1291  int ndofs = fes->GetNDofs();
1292  double *temp = new double[size];
1293 
1294  k = 0;
1295  for (j = 0; j < ndofs; j++)
1296  for (i = 0; i < vdim; i++)
1297  {
1298  temp[j+i*ndofs] = data[k++];
1299  }
1300 
1301  for (i = 0; i < size; i++)
1302  {
1303  data[i] = temp[i];
1304  }
1305 
1306  delete [] temp;
1307 }
1308 
1310 {
1311  int i, k;
1312  Array<int> overlap(fes->GetNV());
1313  Array<int> vertices;
1314  DenseMatrix vals, tr;
1315 
1316  val.SetSize(overlap.Size());
1317  overlap = 0;
1318  val = 0.0;
1319 
1320  comp--;
1321  for (i = 0; i < fes->GetNE(); i++)
1322  {
1323  const IntegrationRule *ir =
1325  fes->GetElementVertices(i, vertices);
1326  GetVectorFieldValues(i, *ir, vals, tr);
1327  for (k = 0; k < ir->GetNPoints(); k++)
1328  {
1329  val(vertices[k]) += vals(k, comp);
1330  overlap[vertices[k]]++;
1331  }
1332  }
1333 
1334  for (i = 0; i < overlap.Size(); i++)
1335  {
1336  val(i) /= overlap[i];
1337  }
1338 }
1339 
1341 {
1342  FiniteElementSpace *new_fes = vec_field.FESpace();
1343 
1344  int d, i, k, ind, dof, sdim;
1345  Array<int> overlap(new_fes->GetVSize());
1346  Array<int> new_vdofs;
1347  DenseMatrix vals, tr;
1348 
1349  sdim = fes->GetMesh()->SpaceDimension();
1350  overlap = 0;
1351  vec_field = 0.0;
1352 
1353  for (i = 0; i < new_fes->GetNE(); i++)
1354  {
1355  const FiniteElement *fe = new_fes->GetFE(i);
1356  const IntegrationRule &ir = fe->GetNodes();
1357  GetVectorFieldValues(i, ir, vals, tr, comp);
1358  new_fes->GetElementVDofs(i, new_vdofs);
1359  dof = fe->GetDof();
1360  for (d = 0; d < sdim; d++)
1361  {
1362  for (k = 0; k < dof; k++)
1363  {
1364  if ( (ind=new_vdofs[dof*d+k]) < 0 )
1365  {
1366  ind = -1-ind, vals(k, d) = - vals(k, d);
1367  }
1368  vec_field(ind) += vals(k, d);
1369  overlap[ind]++;
1370  }
1371  }
1372  }
1373 
1374  for (i = 0; i < overlap.Size(); i++)
1375  {
1376  vec_field(i) /= overlap[i];
1377  }
1378 }
1379 
1381  GridFunction &der,
1382  Array<int> &zones_per_dof)
1383 {
1384  FiniteElementSpace * der_fes = der.FESpace();
1385  ElementTransformation * transf;
1386  zones_per_dof.SetSize(der_fes->GetVSize());
1387  Array<int> der_dofs, vdofs;
1388  DenseMatrix dshape, inv_jac;
1389  Vector pt_grad, loc_func;
1390  int i, j, k, dim, dof, der_dof, ind;
1391  double a;
1392 
1393  zones_per_dof = 0;
1394  der = 0.0;
1395 
1396  comp--;
1397  for (i = 0; i < der_fes->GetNE(); i++)
1398  {
1399  const FiniteElement *der_fe = der_fes->GetFE(i);
1400  const FiniteElement *fe = fes->GetFE(i);
1401  const IntegrationRule &ir = der_fe->GetNodes();
1402  der_fes->GetElementDofs(i, der_dofs);
1403  fes->GetElementVDofs(i, vdofs);
1404  dim = fe->GetDim();
1405  dof = fe->GetDof();
1406  der_dof = der_fe->GetDof();
1407  dshape.SetSize(dof, dim);
1408  inv_jac.SetSize(dim);
1409  pt_grad.SetSize(dim);
1410  loc_func.SetSize(dof);
1411  transf = fes->GetElementTransformation(i);
1412  for (j = 0; j < dof; j++)
1413  loc_func(j) = ( (ind=vdofs[comp*dof+j]) >= 0 ) ?
1414  (data[ind]) : (-data[-1-ind]);
1415  for (k = 0; k < der_dof; k++)
1416  {
1417  const IntegrationPoint &ip = ir.IntPoint(k);
1418  fe->CalcDShape(ip, dshape);
1419  dshape.MultTranspose(loc_func, pt_grad);
1420  transf->SetIntPoint(&ip);
1421  CalcInverse(transf->Jacobian(), inv_jac);
1422  a = 0.0;
1423  for (j = 0; j < dim; j++)
1424  {
1425  a += inv_jac(j, der_comp) * pt_grad(j);
1426  }
1427  der(der_dofs[k]) += a;
1428  zones_per_dof[der_dofs[k]]++;
1429  }
1430  }
1431 }
1432 
1433 void GridFunction::GetDerivative(int comp, int der_comp, GridFunction &der)
1434 {
1435  Array<int> overlap;
1436  AccumulateAndCountDerivativeValues(comp, der_comp, der, overlap);
1437 
1438  for (int i = 0; i < overlap.Size(); i++)
1439  {
1440  der(i) /= overlap[i];
1441  }
1442 }
1443 
1445  ElementTransformation &T, DenseMatrix &gh) const
1446 {
1447  const FiniteElement *FElem = fes->GetFE(T.ElementNo);
1448  int dim = FElem->GetDim(), dof = FElem->GetDof();
1449  Vector loc_data;
1450  GetElementDofValues(T.ElementNo, loc_data);
1451  // assuming scalar FE
1452  int vdim = fes->GetVDim();
1453  DenseMatrix dshape(dof, dim);
1454  FElem->CalcDShape(T.GetIntPoint(), dshape);
1455  gh.SetSize(vdim, dim);
1456  DenseMatrix loc_data_mat(loc_data.GetData(), dof, vdim);
1457  MultAtB(loc_data_mat, dshape, gh);
1458 }
1459 
1461 {
1462  switch (T.ElementType)
1463  {
1465  {
1466  int elNo = T.ElementNo;
1467  const FiniteElement *fe = fes->GetFE(elNo);
1468  if (fe->GetRangeType() == FiniteElement::SCALAR)
1469  {
1470  MFEM_ASSERT(fe->GetMapType() == FiniteElement::VALUE,
1471  "invalid FE map type");
1472  DenseMatrix grad_hat;
1473  GetVectorGradientHat(T, grad_hat);
1474  const DenseMatrix &Jinv = T.InverseJacobian();
1475  double div_v = 0.0;
1476  for (int i = 0; i < Jinv.Width(); i++)
1477  {
1478  for (int j = 0; j < Jinv.Height(); j++)
1479  {
1480  div_v += grad_hat(i, j) * Jinv(j, i);
1481  }
1482  }
1483  return div_v;
1484  }
1485  else
1486  {
1487  // Assuming RT-type space
1488  Array<int> dofs;
1489  DofTransformation * doftrans = fes->GetElementDofs(elNo, dofs);
1490  Vector loc_data, divshape(fe->GetDof());
1491  GetSubVector(dofs, loc_data);
1492  if (doftrans)
1493  {
1494  doftrans->InvTransformPrimal(loc_data);
1495  }
1496  fe->CalcDivShape(T.GetIntPoint(), divshape);
1497  return (loc_data * divshape) / T.Weight();
1498  }
1499  }
1500  break;
1502  {
1503  // In order to properly capture the derivative of the normal component
1504  // of the field (as well as the transverse divergence of the
1505  // tangential components) we must evaluate it in the neighboring
1506  // element.
1508  fes->GetMesh()->GetBdrFaceTransformations(T.ElementNo);
1509 
1510  // Boundary elements and Boundary Faces may have different
1511  // orientations so adjust the integration point if necessary.
1512  int o = 0;
1513  if (fes->GetMesh()->Dimension() == 3)
1514  {
1515  int f;
1516  fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
1517  }
1518 
1519  IntegrationPoint fip;
1520  be_to_bfe(FET->GetGeometryType(), o, T.GetIntPoint(), fip);
1521 
1522  // Compute and set the point in element 1 from fip
1523  FET->SetAllIntPoints(&fip);
1525 
1526  return GetDivergence(T1);
1527  }
1528  break;
1530  {
1531  // This must be a DG context so this dynamic cast must succeed.
1533  dynamic_cast<FaceElementTransformations *>(&T);
1534 
1535  // Evaluate in neighboring element (the integration point in T1 should
1536  // have already been set).
1538  return GetDivergence(T1);
1539  }
1540  break;
1541  default:
1542  {
1543  MFEM_ABORT("GridFunction::GetDivergence: Unsupported element type \""
1544  << T.ElementType << "\"");
1545  }
1546  }
1547  return 0.0; // never reached
1548 }
1549 
1551 {
1552  switch (T.ElementType)
1553  {
1555  {
1556  int elNo = T.ElementNo;
1557  const FiniteElement *fe = fes->GetFE(elNo);
1558  if (fe->GetRangeType() == FiniteElement::SCALAR)
1559  {
1560  MFEM_ASSERT(fe->GetMapType() == FiniteElement::VALUE,
1561  "invalid FE map type");
1562  DenseMatrix grad_hat;
1563  GetVectorGradientHat(T, grad_hat);
1564  const DenseMatrix &Jinv = T.InverseJacobian();
1565  // Dimensions of grad are vdim x FElem->Dim
1566  DenseMatrix grad(grad_hat.Height(), Jinv.Width());
1567  Mult(grad_hat, Jinv, grad);
1568  MFEM_ASSERT(grad.Height() == grad.Width(), "");
1569  if (grad.Height() == 3)
1570  {
1571  curl.SetSize(3);
1572  curl(0) = grad(2,1) - grad(1,2);
1573  curl(1) = grad(0,2) - grad(2,0);
1574  curl(2) = grad(1,0) - grad(0,1);
1575  }
1576  else if (grad.Height() == 2)
1577  {
1578  curl.SetSize(1);
1579  curl(0) = grad(1,0) - grad(0,1);
1580  }
1581  }
1582  else
1583  {
1584  // Assuming ND-type space
1585  Array<int> dofs;
1586  DofTransformation * doftrans = fes->GetElementDofs(elNo, dofs);
1587  Vector loc_data;
1588  GetSubVector(dofs, loc_data);
1589  if (doftrans)
1590  {
1591  doftrans->InvTransformPrimal(loc_data);
1592  }
1593  DenseMatrix curl_shape(fe->GetDof(), fe->GetCurlDim());
1594  curl.SetSize(curl_shape.Width());
1595  fe->CalcPhysCurlShape(T, curl_shape);
1596  curl_shape.MultTranspose(loc_data, curl);
1597  }
1598  }
1599  break;
1601  {
1602  // In order to capture the tangential components of the curl we
1603  // must evaluate it in the neighboring element.
1605  fes->GetMesh()->GetBdrFaceTransformations(T.ElementNo);
1606 
1607  // Boundary elements and Boundary Faces may have different
1608  // orientations so adjust the integration point if necessary.
1609  int o = 0;
1610  if (fes->GetMesh()->Dimension() == 3)
1611  {
1612  int f;
1613  fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
1614  }
1615 
1616  IntegrationPoint fip;
1617  be_to_bfe(FET->GetGeometryType(), o, T.GetIntPoint(), fip);
1618 
1619  // Compute and set the point in element 1 from fip
1620  FET->SetAllIntPoints(&fip);
1622 
1623  GetCurl(T1, curl);
1624  }
1625  break;
1627  {
1628  // This must be a DG context so this dynamic cast must succeed.
1630  dynamic_cast<FaceElementTransformations *>(&T);
1631 
1632  // Evaluate in neighboring element (the integration point in T1 should
1633  // have already been set).
1635  GetCurl(T1, curl);
1636  }
1637  break;
1638  default:
1639  {
1640  MFEM_ABORT("GridFunction::GetCurl: Unsupported element type \""
1641  << T.ElementType << "\"");
1642  }
1643  }
1644 }
1645 
1647 {
1648  switch (T.ElementType)
1649  {
1651  {
1652  const FiniteElement *fe = fes->GetFE(T.ElementNo);
1653  MFEM_ASSERT(fe->GetMapType() == FiniteElement::VALUE,
1654  "invalid FE map type");
1655  MFEM_ASSERT(fes->GetVDim() == 1, "Defined for scalar functions.");
1656  int spaceDim = fes->GetMesh()->SpaceDimension();
1657  int dim = fe->GetDim(), dof = fe->GetDof();
1658  DenseMatrix dshape(dof, dim);
1659  Vector lval, gh(dim);
1660 
1661  grad.SetSize(spaceDim);
1662  GetElementDofValues(T.ElementNo, lval);
1663  fe->CalcDShape(T.GetIntPoint(), dshape);
1664  dshape.MultTranspose(lval, gh);
1665  T.InverseJacobian().MultTranspose(gh, grad);
1666  }
1667  break;
1669  {
1670  // In order to properly capture the normal component of the gradient
1671  // as well as its tangential components we must evaluate it in the
1672  // neighboring element.
1674  fes->GetMesh()->GetBdrFaceTransformations(T.ElementNo);
1675 
1676  // Boundary elements and Boundary Faces may have different
1677  // orientations so adjust the integration point if necessary.
1678  int o = 0;
1679  if (fes->GetMesh()->Dimension() == 3)
1680  {
1681  int f;
1682  fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
1683  }
1684 
1685  IntegrationPoint fip;
1686  be_to_bfe(FET->GetGeometryType(), o, T.GetIntPoint(), fip);
1687 
1688  // Compute and set the point in element 1 from fip
1689  FET->SetAllIntPoints(&fip);
1691 
1692  GetGradient(T1, grad);
1693  }
1694  break;
1696  {
1697  // This must be a DG context so this dynamic cast must succeed.
1699  dynamic_cast<FaceElementTransformations *>(&T);
1700 
1701  // Evaluate in neighboring element (the integration point in T1 should
1702  // have already been set).
1704  GetGradient(T1, grad);
1705  }
1706  break;
1707  default:
1708  {
1709  MFEM_ABORT("GridFunction::GetGradient: Unsupported element type \""
1710  << T.ElementType << "\"");
1711  }
1712  }
1713 }
1714 
1716  const IntegrationRule &ir,
1717  DenseMatrix &grad) const
1718 {
1719  int elNo = tr.ElementNo;
1720  const FiniteElement *fe = fes->GetFE(elNo);
1721  MFEM_ASSERT(fe->GetMapType() == FiniteElement::VALUE, "invalid FE map type");
1722  DenseMatrix dshape(fe->GetDof(), fe->GetDim());
1723  Vector lval, gh(fe->GetDim()), gcol;
1724 
1725  GetElementDofValues(tr.ElementNo, lval);
1726  grad.SetSize(fe->GetDim(), ir.GetNPoints());
1727  for (int i = 0; i < ir.GetNPoints(); i++)
1728  {
1729  const IntegrationPoint &ip = ir.IntPoint(i);
1730  fe->CalcDShape(ip, dshape);
1731  dshape.MultTranspose(lval, gh);
1732  tr.SetIntPoint(&ip);
1733  grad.GetColumnReference(i, gcol);
1734  const DenseMatrix &Jinv = tr.InverseJacobian();
1735  Jinv.MultTranspose(gh, gcol);
1736  }
1737 }
1738 
1740  ElementTransformation &T, DenseMatrix &grad) const
1741 {
1742  switch (T.ElementType)
1743  {
1745  {
1746  MFEM_ASSERT(fes->GetFE(T.ElementNo)->GetMapType() ==
1747  FiniteElement::VALUE, "invalid FE map type");
1748  DenseMatrix grad_hat;
1749  GetVectorGradientHat(T, grad_hat);
1750  const DenseMatrix &Jinv = T.InverseJacobian();
1751  grad.SetSize(grad_hat.Height(), Jinv.Width());
1752  Mult(grad_hat, Jinv, grad);
1753  }
1754  break;
1756  {
1757  // In order to capture the normal component of the gradient we
1758  // must evaluate it in the neighboring element.
1760  fes->GetMesh()->GetBdrFaceTransformations(T.ElementNo);
1761 
1762  // Boundary elements and Boundary Faces may have different
1763  // orientations so adjust the integration point if necessary.
1764  int o = 0;
1765  if (fes->GetMesh()->Dimension() == 3)
1766  {
1767  int f;
1768  fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
1769  }
1770 
1771  IntegrationPoint fip;
1772  be_to_bfe(FET->GetGeometryType(), o, T.GetIntPoint(), fip);
1773 
1774  // Compute and set the point in element 1 from fip
1775  FET->SetAllIntPoints(&fip);
1777 
1778  GetVectorGradient(T1, grad);
1779  }
1780  break;
1782  {
1783  // This must be a DG context so this dynamic cast must succeed.
1785  dynamic_cast<FaceElementTransformations *>(&T);
1786 
1787  // Evaluate in neighboring element (the integration point in T1 should
1788  // have already been set).
1790  GetVectorGradient(T1, grad);
1791  }
1792  break;
1793  default:
1794  {
1795  MFEM_ABORT("GridFunction::GetVectorGradient: "
1796  "Unsupported element type \"" << T.ElementType << "\"");
1797  }
1798  }
1799 }
1800 
1802 {
1803  MassIntegrator Mi;
1804  DenseMatrix loc_mass;
1805  DofTransformation * te_doftrans;
1806  DofTransformation * tr_doftrans;
1807  Array<int> te_dofs, tr_dofs;
1808  Vector loc_avgs, loc_this;
1809  Vector int_psi(avgs.Size());
1810 
1811  avgs = 0.0;
1812  int_psi = 0.0;
1813  for (int i = 0; i < fes->GetNE(); i++)
1814  {
1815  Mi.AssembleElementMatrix2(*fes->GetFE(i), *avgs.FESpace()->GetFE(i),
1816  *fes->GetElementTransformation(i), loc_mass);
1817  tr_doftrans = fes->GetElementDofs(i, tr_dofs);
1818  te_doftrans = avgs.FESpace()->GetElementDofs(i, te_dofs);
1819  GetSubVector(tr_dofs, loc_this);
1820  if (tr_doftrans)
1821  {
1822  tr_doftrans->InvTransformPrimal(loc_this);
1823  }
1824  loc_avgs.SetSize(te_dofs.Size());
1825  loc_mass.Mult(loc_this, loc_avgs);
1826  if (te_doftrans)
1827  {
1828  te_doftrans->TransformPrimal(loc_avgs);
1829  }
1830  avgs.AddElementVector(te_dofs, loc_avgs);
1831  loc_this = 1.0; // assume the local basis for 'this' sums to 1
1832  loc_mass.Mult(loc_this, loc_avgs);
1833  int_psi.AddElementVector(te_dofs, loc_avgs);
1834  }
1835  for (int i = 0; i < avgs.Size(); i++)
1836  {
1837  avgs(i) /= int_psi(i);
1838  }
1839 }
1840 
1841 void GridFunction::GetElementDofValues(int el, Vector &dof_vals) const
1842 {
1843  Array<int> dof_idx;
1844  DofTransformation * doftrans = fes->GetElementVDofs(el, dof_idx);
1845  GetSubVector(dof_idx, dof_vals);
1846  if (doftrans)
1847  {
1848  doftrans->InvTransformPrimal(dof_vals);
1849  }
1850 }
1851 
1853 {
1854  Mesh *mesh = fes->GetMesh();
1855  bool sameP = false;
1856  DenseMatrix P;
1857 
1858  if (!mesh->GetNE()) { return; }
1859 
1860  Geometry::Type geom, cached_geom = Geometry::INVALID;
1861  if (mesh->GetNumGeometries(mesh->Dimension()) == 1)
1862  {
1863  // Assuming that the projection matrix is the same for all elements
1864  sameP = true;
1865  fes->GetFE(0)->Project(*src.fes->GetFE(0),
1866  *mesh->GetElementTransformation(0), P);
1867  }
1868  const int vdim = fes->GetVDim();
1869  MFEM_VERIFY(vdim == src.fes->GetVDim(), "incompatible vector dimensions!");
1870 
1871  Array<int> src_vdofs, dest_vdofs;
1872  Vector src_lvec, dest_lvec(vdim*P.Height());
1873 
1874  for (int i = 0; i < mesh->GetNE(); i++)
1875  {
1876  // Assuming the projection matrix P depends only on the element geometry
1877  if ( !sameP && (geom = mesh->GetElementBaseGeometry(i)) != cached_geom )
1878  {
1879  fes->GetFE(i)->Project(*src.fes->GetFE(i),
1880  *mesh->GetElementTransformation(i), P);
1881  dest_lvec.SetSize(vdim*P.Height());
1882  cached_geom = geom;
1883  }
1884 
1885  DofTransformation * src_doftrans = src.fes->GetElementVDofs(i, src_vdofs);
1886  src.GetSubVector(src_vdofs, src_lvec);
1887  if (src_doftrans)
1888  {
1889  src_doftrans->InvTransformPrimal(src_lvec);
1890  }
1891  for (int vd = 0; vd < vdim; vd++)
1892  {
1893  P.Mult(&src_lvec[vd*P.Width()], &dest_lvec[vd*P.Height()]);
1894  }
1895  DofTransformation * doftrans = fes->GetElementVDofs(i, dest_vdofs);
1896  if (doftrans)
1897  {
1898  doftrans->TransformPrimal(dest_lvec);
1899  }
1900  SetSubVector(dest_vdofs, dest_lvec);
1901  }
1902 }
1903 
1904 void GridFunction::ImposeBounds(int i, const Vector &weights,
1905  const Vector &lo_, const Vector &hi_)
1906 {
1907  Array<int> vdofs;
1908  DofTransformation * doftrans = fes->GetElementVDofs(i, vdofs);
1909  int size = vdofs.Size();
1910  Vector vals, new_vals(size);
1911 
1912  GetSubVector(vdofs, vals);
1913  if (doftrans)
1914  {
1915  doftrans->InvTransformPrimal(vals);
1916  }
1917 
1918  MFEM_ASSERT(weights.Size() == size, "Different # of weights and dofs.");
1919  MFEM_ASSERT(lo_.Size() == size, "Different # of lower bounds and dofs.");
1920  MFEM_ASSERT(hi_.Size() == size, "Different # of upper bounds and dofs.");
1921 
1922  int max_iter = 30;
1923  double tol = 1.e-12;
1924  SLBQPOptimizer slbqp;
1925  slbqp.SetMaxIter(max_iter);
1926  slbqp.SetAbsTol(1.0e-18);
1927  slbqp.SetRelTol(tol);
1928  slbqp.SetBounds(lo_, hi_);
1929  slbqp.SetLinearConstraint(weights, weights * vals);
1930  slbqp.SetPrintLevel(0); // print messages only if not converged
1931  slbqp.Mult(vals, new_vals);
1932 
1933  if (doftrans)
1934  {
1935  doftrans->TransformPrimal(new_vals);
1936  }
1937  SetSubVector(vdofs, new_vals);
1938 }
1939 
1940 void GridFunction::ImposeBounds(int i, const Vector &weights,
1941  double min_, double max_)
1942 {
1943  Array<int> vdofs;
1944  DofTransformation * doftrans = fes->GetElementVDofs(i, vdofs);
1945  int size = vdofs.Size();
1946  Vector vals, new_vals(size);
1947  GetSubVector(vdofs, vals);
1948  if (doftrans)
1949  {
1950  doftrans->InvTransformPrimal(vals);
1951  }
1952 
1953  double max_val = vals.Max();
1954  double min_val = vals.Min();
1955 
1956  if (max_val <= min_)
1957  {
1958  new_vals = min_;
1959  if (doftrans)
1960  {
1961  doftrans->TransformPrimal(new_vals);
1962  }
1963  SetSubVector(vdofs, new_vals);
1964  return;
1965  }
1966 
1967  if (min_ <= min_val && max_val <= max_)
1968  {
1969  return;
1970  }
1971 
1972  Vector minv(size), maxv(size);
1973  minv = (min_ > min_val) ? min_ : min_val;
1974  maxv = (max_ < max_val) ? max_ : max_val;
1975 
1976  ImposeBounds(i, weights, minv, maxv);
1977 }
1978 
1980 {
1981  const SparseMatrix *R = fes->GetRestrictionMatrix();
1982  const Operator *P = fes->GetProlongationMatrix();
1983 
1984  if (P && R)
1985  {
1986  Vector tmp(R->Height());
1987  R->Mult(*this, tmp);
1988  P->Mult(tmp, *this);
1989  }
1990 }
1991 
1992 void GridFunction::GetNodalValues(Vector &nval, int vdim) const
1993 {
1994  int i, j;
1995  Array<int> vertices;
1996  Array<double> values;
1997  Array<int> overlap(fes->GetNV());
1998  nval.SetSize(fes->GetNV());
1999 
2000  nval = 0.0;
2001  overlap = 0;
2002  for (i = 0; i < fes->GetNE(); i++)
2003  {
2004  fes->GetElementVertices(i, vertices);
2005  GetNodalValues(i, values, vdim);
2006  for (j = 0; j < vertices.Size(); j++)
2007  {
2008  nval(vertices[j]) += values[j];
2009  overlap[vertices[j]]++;
2010  }
2011  }
2012  for (i = 0; i < overlap.Size(); i++)
2013  {
2014  nval(i) /= overlap[i];
2015  }
2016 }
2017 
2019  AvgType type,
2020  Array<int> &zones_per_vdof)
2021 {
2022  zones_per_vdof.SetSize(fes->GetVSize());
2023  zones_per_vdof = 0;
2024 
2025  // Local interpolation
2026  Array<int> vdofs;
2027  Vector vals;
2028  *this = 0.0;
2029 
2030  HostReadWrite();
2031 
2032  for (int i = 0; i < fes->GetNE(); i++)
2033  {
2034  fes->GetElementVDofs(i, vdofs);
2035  // Local interpolation of coeff.
2036  vals.SetSize(vdofs.Size());
2037  fes->GetFE(i)->Project(coeff, *fes->GetElementTransformation(i), vals);
2038 
2039  // Accumulate values in all dofs, count the zones.
2040  for (int j = 0; j < vdofs.Size(); j++)
2041  {
2042  if (type == HARMONIC)
2043  {
2044  MFEM_VERIFY(vals[j] != 0.0,
2045  "Coefficient has zeros, harmonic avg is undefined!");
2046  (*this)(vdofs[j]) += 1.0 / vals[j];
2047  }
2048  else if (type == ARITHMETIC)
2049  {
2050  (*this)(vdofs[j]) += vals[j];
2051  }
2052  else { MFEM_ABORT("Not implemented"); }
2053 
2054  zones_per_vdof[vdofs[j]]++;
2055  }
2056  }
2057 }
2058 
2060  AvgType type,
2061  Array<int> &zones_per_vdof)
2062 {
2063  zones_per_vdof.SetSize(fes->GetVSize());
2064  zones_per_vdof = 0;
2065 
2066  // Local interpolation
2067  Array<int> vdofs;
2068  Vector vals;
2069  *this = 0.0;
2070 
2071  HostReadWrite();
2072 
2073  for (int i = 0; i < fes->GetNE(); i++)
2074  {
2075  fes->GetElementVDofs(i, vdofs);
2076  // Local interpolation of coeff.
2077  vals.SetSize(vdofs.Size());
2078  fes->GetFE(i)->Project(vcoeff, *fes->GetElementTransformation(i), vals);
2079 
2080  // Accumulate values in all dofs, count the zones.
2081  for (int j = 0; j < vdofs.Size(); j++)
2082  {
2083  int ldof;
2084  int isign;
2085  if (vdofs[j] < 0 )
2086  {
2087  ldof = -1-vdofs[j];
2088  isign = -1;
2089  }
2090  else
2091  {
2092  ldof = vdofs[j];
2093  isign = 1;
2094  }
2095 
2096  if (type == HARMONIC)
2097  {
2098  MFEM_VERIFY(vals[j] != 0.0,
2099  "Coefficient has zeros, harmonic avg is undefined!");
2100  (*this)(ldof) += isign / vals[j];
2101  }
2102  else if (type == ARITHMETIC)
2103  {
2104  (*this)(ldof) += isign*vals[j];
2105 
2106  }
2107  else { MFEM_ABORT("Not implemented"); }
2108 
2109  zones_per_vdof[ldof]++;
2110  }
2111  }
2112 }
2113 
2115  Coefficient *coeff[], VectorCoefficient *vcoeff, Array<int> &attr,
2116  Array<int> &values_counter)
2117 {
2118  int i, j, fdof, d, ind, vdim;
2119  double val;
2120  const FiniteElement *fe;
2121  ElementTransformation *transf;
2122  Array<int> vdofs;
2123  Vector vc;
2124 
2125  values_counter.SetSize(Size());
2126  values_counter = 0;
2127 
2128  vdim = fes->GetVDim();
2129 
2130  HostReadWrite();
2131 
2132  for (i = 0; i < fes->GetNBE(); i++)
2133  {
2134  if (attr[fes->GetBdrAttribute(i) - 1] == 0) { continue; }
2135 
2136  fe = fes->GetBE(i);
2137  fdof = fe->GetDof();
2138  transf = fes->GetBdrElementTransformation(i);
2139  const IntegrationRule &ir = fe->GetNodes();
2140  fes->GetBdrElementVDofs(i, vdofs);
2141 
2142  for (j = 0; j < fdof; j++)
2143  {
2144  const IntegrationPoint &ip = ir.IntPoint(j);
2145  transf->SetIntPoint(&ip);
2146  if (vcoeff) { vcoeff->Eval(vc, *transf, ip); }
2147  for (d = 0; d < vdim; d++)
2148  {
2149  if (!vcoeff && !coeff[d]) { continue; }
2150 
2151  val = vcoeff ? vc(d) : coeff[d]->Eval(*transf, ip);
2152  if ( (ind = vdofs[fdof*d+j]) < 0 )
2153  {
2154  val = -val, ind = -1-ind;
2155  }
2156  if (++values_counter[ind] == 1)
2157  {
2158  (*this)(ind) = val;
2159  }
2160  else
2161  {
2162  (*this)(ind) += val;
2163  }
2164  }
2165  }
2166  }
2167 
2168  // In the case of partially conforming space, i.e. (fes->cP != NULL), we need
2169  // to set the values of all dofs on which the dofs set above depend.
2170  // Dependency is defined from the matrix A = cP.cR: dof i depends on dof j
2171  // iff A_ij != 0. It is sufficient to resolve just the first level of
2172  // dependency, since A is a projection matrix: A^n = A due to cR.cP = I.
2173  // Cases like these arise in 3D when boundary edges are constrained by
2174  // (depend on) internal faces/elements. We use the virtual method
2175  // GetBoundaryClosure from NCMesh to resolve the dependencies.
2176 
2177  if (fes->Nonconforming() && fes->GetMesh()->Dimension() == 3)
2178  {
2179  Vector vals;
2180  Mesh *mesh = fes->GetMesh();
2181  NCMesh *ncmesh = mesh->ncmesh;
2182  Array<int> bdr_edges, bdr_vertices;
2183  ncmesh->GetBoundaryClosure(attr, bdr_vertices, bdr_edges);
2184 
2185  for (i = 0; i < bdr_edges.Size(); i++)
2186  {
2187  int edge = bdr_edges[i];
2188  fes->GetEdgeVDofs(edge, vdofs);
2189  if (vdofs.Size() == 0) { continue; }
2190 
2191  transf = mesh->GetEdgeTransformation(edge);
2192  transf->Attribute = -1; // TODO: set the boundary attribute
2193  fe = fes->GetEdgeElement(edge);
2194  if (!vcoeff)
2195  {
2196  vals.SetSize(fe->GetDof());
2197  for (d = 0; d < vdim; d++)
2198  {
2199  if (!coeff[d]) { continue; }
2200 
2201  fe->Project(*coeff[d], *transf, vals);
2202  for (int k = 0; k < vals.Size(); k++)
2203  {
2204  ind = vdofs[d*vals.Size()+k];
2205  if (++values_counter[ind] == 1)
2206  {
2207  (*this)(ind) = vals(k);
2208  }
2209  else
2210  {
2211  (*this)(ind) += vals(k);
2212  }
2213  }
2214  }
2215  }
2216  else // vcoeff != NULL
2217  {
2218  vals.SetSize(vdim*fe->GetDof());
2219  fe->Project(*vcoeff, *transf, vals);
2220  for (int k = 0; k < vals.Size(); k++)
2221  {
2222  ind = vdofs[k];
2223  if (++values_counter[ind] == 1)
2224  {
2225  (*this)(ind) = vals(k);
2226  }
2227  else
2228  {
2229  (*this)(ind) += vals(k);
2230  }
2231  }
2232  }
2233  }
2234  }
2235 }
2236 
2237 static void accumulate_dofs(const Array<int> &dofs, const Vector &vals,
2238  Vector &gf, Array<int> &values_counter)
2239 {
2240  for (int i = 0; i < dofs.Size(); i++)
2241  {
2242  int k = dofs[i];
2243  double val = vals(i);
2244  if (k < 0) { k = -1 - k; val = -val; }
2245  if (++values_counter[k] == 1)
2246  {
2247  gf(k) = val;
2248  }
2249  else
2250  {
2251  gf(k) += val;
2252  }
2253  }
2254 }
2255 
2257  VectorCoefficient &vcoeff, Array<int> &bdr_attr,
2258  Array<int> &values_counter)
2259 {
2260  const FiniteElement *fe;
2262  Array<int> dofs;
2263  Vector lvec;
2264 
2265  values_counter.SetSize(Size());
2266  values_counter = 0;
2267 
2268  HostReadWrite();
2269 
2270  for (int i = 0; i < fes->GetNBE(); i++)
2271  {
2272  if (bdr_attr[fes->GetBdrAttribute(i)-1] == 0)
2273  {
2274  continue;
2275  }
2276  fe = fes->GetBE(i);
2278  DofTransformation *dof_tr = fes->GetBdrElementDofs(i, dofs);
2279  lvec.SetSize(fe->GetDof());
2280  fe->Project(vcoeff, *T, lvec);
2281  if (dof_tr) { dof_tr->TransformPrimal(lvec); }
2282  accumulate_dofs(dofs, lvec, *this, values_counter);
2283  }
2284 
2285  if (fes->Nonconforming() && fes->GetMesh()->Dimension() == 3)
2286  {
2287  Mesh *mesh = fes->GetMesh();
2288  NCMesh *ncmesh = mesh->ncmesh;
2289  Array<int> bdr_edges, bdr_vertices;
2290  ncmesh->GetBoundaryClosure(bdr_attr, bdr_vertices, bdr_edges);
2291 
2292  for (int i = 0; i < bdr_edges.Size(); i++)
2293  {
2294  int edge = bdr_edges[i];
2295  fes->GetEdgeDofs(edge, dofs);
2296  if (dofs.Size() == 0) { continue; }
2297 
2298  T = mesh->GetEdgeTransformation(edge);
2299  T->Attribute = -1; // TODO: set the boundary attribute
2300  fe = fes->GetEdgeElement(edge);
2301  lvec.SetSize(fe->GetDof());
2302  fe->Project(vcoeff, *T, lvec);
2303  accumulate_dofs(dofs, lvec, *this, values_counter);
2304  }
2305  }
2306 }
2307 
2308 void GridFunction::ComputeMeans(AvgType type, Array<int> &zones_per_vdof)
2309 {
2310  switch (type)
2311  {
2312  case ARITHMETIC:
2313  for (int i = 0; i < size; i++)
2314  {
2315  const int nz = zones_per_vdof[i];
2316  if (nz) { (*this)(i) /= nz; }
2317  }
2318  break;
2319 
2320  case HARMONIC:
2321  for (int i = 0; i < size; i++)
2322  {
2323  const int nz = zones_per_vdof[i];
2324  if (nz) { (*this)(i) = nz/(*this)(i); }
2325  }
2326  break;
2327 
2328  default:
2329  MFEM_ABORT("invalid AvgType");
2330  }
2331 }
2332 
2334  double &integral)
2335 {
2336  if (!fes->GetNE())
2337  {
2338  integral = 0.0;
2339  return;
2340  }
2341 
2342  Mesh *mesh = fes->GetMesh();
2343  const int dim = mesh->Dimension();
2344  const double *center = delta_coeff.Center();
2345  const double *vert = mesh->GetVertex(0);
2346  double min_dist, dist;
2347  int v_idx = 0;
2348 
2349  // find the vertex closest to the center of the delta function
2350  min_dist = Distance(center, vert, dim);
2351  for (int i = 0; i < mesh->GetNV(); i++)
2352  {
2353  vert = mesh->GetVertex(i);
2354  dist = Distance(center, vert, dim);
2355  if (dist < min_dist)
2356  {
2357  min_dist = dist;
2358  v_idx = i;
2359  }
2360  }
2361 
2362  (*this) = 0.0;
2363  integral = 0.0;
2364 
2365  if (min_dist >= delta_coeff.Tol())
2366  {
2367  return;
2368  }
2369 
2370  // find the elements that have 'v_idx' as a vertex
2371  MassIntegrator Mi(*delta_coeff.Weight());
2372  DenseMatrix loc_mass;
2373  Array<int> vdofs, vertices;
2374  Vector vals, loc_mass_vals;
2375  for (int i = 0; i < mesh->GetNE(); i++)
2376  {
2377  mesh->GetElementVertices(i, vertices);
2378  for (int j = 0; j < vertices.Size(); j++)
2379  if (vertices[j] == v_idx)
2380  {
2381  const FiniteElement *fe = fes->GetFE(i);
2382  Mi.AssembleElementMatrix(*fe, *fes->GetElementTransformation(i),
2383  loc_mass);
2384  vals.SetSize(fe->GetDof());
2385  fe->ProjectDelta(j, vals);
2386  fes->GetElementVDofs(i, vdofs);
2387  SetSubVector(vdofs, vals);
2388  loc_mass_vals.SetSize(vals.Size());
2389  loc_mass.Mult(vals, loc_mass_vals);
2390  integral += loc_mass_vals.Sum(); // partition of unity basis
2391  break;
2392  }
2393  }
2394 }
2395 
2397 {
2398  DeltaCoefficient *delta_c = dynamic_cast<DeltaCoefficient *>(&coeff);
2399  DofTransformation * doftrans = NULL;
2400 
2401  if (delta_c == NULL)
2402  {
2403  Array<int> vdofs;
2404  Vector vals;
2405 
2406  for (int i = 0; i < fes->GetNE(); i++)
2407  {
2408  doftrans = fes->GetElementVDofs(i, vdofs);
2409  vals.SetSize(vdofs.Size());
2410  fes->GetFE(i)->Project(coeff, *fes->GetElementTransformation(i), vals);
2411  if (doftrans)
2412  {
2413  doftrans->TransformPrimal(vals);
2414  }
2415  SetSubVector(vdofs, vals);
2416  }
2417  }
2418  else
2419  {
2420  double integral;
2421 
2422  ProjectDeltaCoefficient(*delta_c, integral);
2423 
2424  (*this) *= (delta_c->Scale() / integral);
2425  }
2426 }
2427 
2429  Coefficient &coeff, Array<int> &dofs, int vd)
2430 {
2431  int el = -1;
2432  ElementTransformation *T = NULL;
2433  const FiniteElement *fe = NULL;
2434 
2435  fes->BuildDofToArrays(); // ensures GetElementForDof(), GetLocalDofForDof() initialized.
2436 
2437  for (int i = 0; i < dofs.Size(); i++)
2438  {
2439  int dof = dofs[i], j = fes->GetElementForDof(dof);
2440  if (el != j)
2441  {
2442  el = j;
2443  T = fes->GetElementTransformation(el);
2444  fe = fes->GetFE(el);
2445  }
2446  int vdof = fes->DofToVDof(dof, vd);
2447  int ld = fes->GetLocalDofForDof(dof);
2448  const IntegrationPoint &ip = fe->GetNodes().IntPoint(ld);
2449  T->SetIntPoint(&ip);
2450  (*this)(vdof) = coeff.Eval(*T, ip);
2451  }
2452 }
2453 
2455 {
2456  int i;
2457  Array<int> vdofs;
2458  Vector vals;
2459 
2460  DofTransformation * doftrans = NULL;
2461 
2462  for (i = 0; i < fes->GetNE(); i++)
2463  {
2464  doftrans = fes->GetElementVDofs(i, vdofs);
2465  vals.SetSize(vdofs.Size());
2466  fes->GetFE(i)->Project(vcoeff, *fes->GetElementTransformation(i), vals);
2467  if (doftrans)
2468  {
2469  doftrans->TransformPrimal(vals);
2470  }
2471  SetSubVector(vdofs, vals);
2472  }
2473 }
2474 
2476  VectorCoefficient &vcoeff, Array<int> &dofs)
2477 {
2478  int el = -1;
2479  ElementTransformation *T = NULL;
2480  const FiniteElement *fe = NULL;
2481 
2482  Vector val;
2483 
2484  fes->BuildDofToArrays(); // ensures GetElementForDof(), GetLocalDofForDof() initialized.
2485 
2486  for (int i = 0; i < dofs.Size(); i++)
2487  {
2488  int dof = dofs[i], j = fes->GetElementForDof(dof);
2489  if (el != j)
2490  {
2491  el = j;
2492  T = fes->GetElementTransformation(el);
2493  fe = fes->GetFE(el);
2494  }
2495  int ld = fes->GetLocalDofForDof(dof);
2496  const IntegrationPoint &ip = fe->GetNodes().IntPoint(ld);
2497  T->SetIntPoint(&ip);
2498  vcoeff.Eval(val, *T, ip);
2499  for (int vd = 0; vd < fes->GetVDim(); vd ++)
2500  {
2501  int vdof = fes->DofToVDof(dof, vd);
2502  (*this)(vdof) = val(vd);
2503  }
2504  }
2505 }
2506 
2508 {
2509  int i;
2510  Array<int> vdofs;
2511  Vector vals;
2512 
2513  DofTransformation * doftrans = NULL;
2514 
2515  for (i = 0; i < fes->GetNE(); i++)
2516  {
2517  if (fes->GetAttribute(i) != attribute)
2518  {
2519  continue;
2520  }
2521 
2522  doftrans = fes->GetElementVDofs(i, vdofs);
2523  vals.SetSize(vdofs.Size());
2524  fes->GetFE(i)->Project(vcoeff, *fes->GetElementTransformation(i), vals);
2525  if (doftrans)
2526  {
2527  doftrans->TransformPrimal(vals);
2528  }
2529  SetSubVector(vdofs, vals);
2530  }
2531 }
2532 
2534 {
2535  int i, j, fdof, d, ind, vdim;
2536  double val;
2537  const FiniteElement *fe;
2538  ElementTransformation *transf;
2539  // DofTransformation * doftrans;
2540  Array<int> vdofs;
2541 
2542  vdim = fes->GetVDim();
2543  for (i = 0; i < fes->GetNE(); i++)
2544  {
2545  fe = fes->GetFE(i);
2546  fdof = fe->GetDof();
2547  transf = fes->GetElementTransformation(i);
2548  const IntegrationRule &ir = fe->GetNodes();
2549  // doftrans = fes->GetElementVDofs(i, vdofs);
2550  fes->GetElementVDofs(i, vdofs);
2551  for (j = 0; j < fdof; j++)
2552  {
2553  const IntegrationPoint &ip = ir.IntPoint(j);
2554  transf->SetIntPoint(&ip);
2555  for (d = 0; d < vdim; d++)
2556  {
2557  if (!coeff[d]) { continue; }
2558 
2559  val = coeff[d]->Eval(*transf, ip);
2560  if ( (ind = vdofs[fdof*d+j]) < 0 )
2561  {
2562  val = -val, ind = -1-ind;
2563  }
2564  (*this)(ind) = val;
2565  }
2566  }
2567  }
2568 }
2569 
2571  Array<int> &dof_attr)
2572 {
2573  Array<int> vdofs;
2574  Vector vals;
2575 
2576  HostWrite();
2577  // maximal element attribute for each dof
2578  dof_attr.SetSize(fes->GetVSize());
2579  dof_attr = -1;
2580 
2581  // local projection
2582  for (int i = 0; i < fes->GetNE(); i++)
2583  {
2584  fes->GetElementVDofs(i, vdofs);
2585  vals.SetSize(vdofs.Size());
2586  fes->GetFE(i)->Project(coeff, *fes->GetElementTransformation(i), vals);
2587 
2588  // the values in shared dofs are determined from the element with maximal
2589  // attribute
2590  int attr = fes->GetAttribute(i);
2591  for (int j = 0; j < vdofs.Size(); j++)
2592  {
2593  if (attr > dof_attr[vdofs[j]])
2594  {
2595  (*this)(vdofs[j]) = vals[j];
2596  dof_attr[vdofs[j]] = attr;
2597  }
2598  }
2599  }
2600 }
2601 
2603 {
2604  Array<int> dof_attr;
2605  ProjectDiscCoefficient(coeff, dof_attr);
2606 }
2607 
2609 {
2610  // Harmonic (x1 ... xn) = [ (1/x1 + ... + 1/xn) / n ]^-1.
2611  // Arithmetic(x1 ... xn) = (x1 + ... + xn) / n.
2612 
2613  Array<int> zones_per_vdof;
2614  AccumulateAndCountZones(coeff, type, zones_per_vdof);
2615 
2616  ComputeMeans(type, zones_per_vdof);
2617 }
2618 
2620  AvgType type)
2621 {
2622  Array<int> zones_per_vdof;
2623  AccumulateAndCountZones(coeff, type, zones_per_vdof);
2624 
2625  ComputeMeans(type, zones_per_vdof);
2626 }
2627 
2629  Array<int> &attr)
2630 {
2631  Array<int> values_counter;
2632  AccumulateAndCountBdrValues(NULL, &vcoeff, attr, values_counter);
2633  ComputeMeans(ARITHMETIC, values_counter);
2634 
2635 #ifdef MFEM_DEBUG
2636  Array<int> ess_vdofs_marker;
2637  fes->GetEssentialVDofs(attr, ess_vdofs_marker);
2638  for (int i = 0; i < values_counter.Size(); i++)
2639  {
2640  MFEM_ASSERT(bool(values_counter[i]) == bool(ess_vdofs_marker[i]),
2641  "internal error");
2642  }
2643 #endif
2644 }
2645 
2647 {
2648  Array<int> values_counter;
2649  // this->HostReadWrite(); // done inside the next call
2650  AccumulateAndCountBdrValues(coeff, NULL, attr, values_counter);
2651  ComputeMeans(ARITHMETIC, values_counter);
2652 
2653 #ifdef MFEM_DEBUG
2654  Array<int> ess_vdofs_marker(Size());
2655  ess_vdofs_marker = 0;
2656  Array<int> component_dof_marker;
2657  for (int i = 0; i < fes->GetVDim(); i++)
2658  {
2659  if (!coeff[i]) { continue; }
2660  fes->GetEssentialVDofs(attr, component_dof_marker,i);
2661  for (int j = 0; j<Size(); j++)
2662  {
2663  ess_vdofs_marker[j] = bool(ess_vdofs_marker[j]) ||
2664  bool(component_dof_marker[j]);
2665  }
2666  }
2667  for (int i = 0; i < values_counter.Size(); i++)
2668  {
2669  MFEM_ASSERT(bool(values_counter[i]) == ess_vdofs_marker[i],
2670  "internal error");
2671  }
2672 #endif
2673 }
2674 
2676  VectorCoefficient &vcoeff, Array<int> &bdr_attr)
2677 {
2678 #if 0
2679  // implementation for the case when the face dofs are integrals of the
2680  // normal component.
2681  const FiniteElement *fe;
2683  Array<int> dofs;
2684  int dim = vcoeff.GetVDim();
2685  Vector vc(dim), nor(dim), lvec, shape;
2686 
2687  for (int i = 0; i < fes->GetNBE(); i++)
2688  {
2689  if (bdr_attr[fes->GetBdrAttribute(i)-1] == 0)
2690  {
2691  continue;
2692  }
2693  fe = fes->GetBE(i);
2695  int intorder = 2*fe->GetOrder(); // !!!
2696  const IntegrationRule &ir = IntRules.Get(fe->GetGeomType(), intorder);
2697  int nd = fe->GetDof();
2698  lvec.SetSize(nd);
2699  shape.SetSize(nd);
2700  lvec = 0.0;
2701  for (int j = 0; j < ir.GetNPoints(); j++)
2702  {
2703  const IntegrationPoint &ip = ir.IntPoint(j);
2704  T->SetIntPoint(&ip);
2705  vcoeff.Eval(vc, *T, ip);
2706  CalcOrtho(T->Jacobian(), nor);
2707  fe->CalcShape(ip, shape);
2708  lvec.Add(ip.weight * (vc * nor), shape);
2709  }
2710  fes->GetBdrElementDofs(i, dofs);
2711  SetSubVector(dofs, lvec);
2712  }
2713 #else
2714  // implementation for the case when the face dofs are scaled point
2715  // values of the normal component.
2716  const FiniteElement *fe;
2718  Array<int> dofs;
2719  int dim = vcoeff.GetVDim();
2720  Vector vc(dim), nor(dim), lvec;
2721 
2722  for (int i = 0; i < fes->GetNBE(); i++)
2723  {
2724  if (bdr_attr[fes->GetBdrAttribute(i)-1] == 0)
2725  {
2726  continue;
2727  }
2728  fe = fes->GetBE(i);
2730  const IntegrationRule &ir = fe->GetNodes();
2731  lvec.SetSize(fe->GetDof());
2732  for (int j = 0; j < ir.GetNPoints(); j++)
2733  {
2734  const IntegrationPoint &ip = ir.IntPoint(j);
2735  T->SetIntPoint(&ip);
2736  vcoeff.Eval(vc, *T, ip);
2737  CalcOrtho(T->Jacobian(), nor);
2738  lvec(j) = (vc * nor);
2739  }
2740  fes->GetBdrElementDofs(i, dofs);
2741  SetSubVector(dofs, lvec);
2742  }
2743 #endif
2744 }
2745 
2747  VectorCoefficient &vcoeff, Array<int> &bdr_attr)
2748 {
2749  Array<int> values_counter;
2750  AccumulateAndCountBdrTangentValues(vcoeff, bdr_attr, values_counter);
2751  ComputeMeans(ARITHMETIC, values_counter);
2752 #ifdef MFEM_DEBUG
2753  Array<int> ess_vdofs_marker;
2754  fes->GetEssentialVDofs(bdr_attr, ess_vdofs_marker);
2755  for (int i = 0; i < values_counter.Size(); i++)
2756  {
2757  MFEM_ASSERT(bool(values_counter[i]) == bool(ess_vdofs_marker[i]),
2758  "internal error");
2759  }
2760 #endif
2761 }
2762 
2764  Coefficient *exsol[], const IntegrationRule *irs[],
2765  const Array<int> *elems) const
2766 {
2767  double error = 0.0, a;
2768  const FiniteElement *fe;
2769  ElementTransformation *transf;
2770  Vector shape;
2771  Array<int> vdofs;
2772  int fdof, d, i, intorder, j, k;
2773 
2774  for (i = 0; i < fes->GetNE(); i++)
2775  {
2776  if (elems != NULL && (*elems)[i] == 0) { continue; }
2777  fe = fes->GetFE(i);
2778  fdof = fe->GetDof();
2779  transf = fes->GetElementTransformation(i);
2780  shape.SetSize(fdof);
2781  intorder = 2*fe->GetOrder() + 3; // <----------
2782  const IntegrationRule *ir;
2783  if (irs)
2784  {
2785  ir = irs[fe->GetGeomType()];
2786  }
2787  else
2788  {
2789  ir = &(IntRules.Get(fe->GetGeomType(), intorder));
2790  }
2791  fes->GetElementVDofs(i, vdofs);
2792  for (j = 0; j < ir->GetNPoints(); j++)
2793  {
2794  const IntegrationPoint &ip = ir->IntPoint(j);
2795  fe->CalcShape(ip, shape);
2796  for (d = 0; d < fes->GetVDim(); d++)
2797  {
2798  a = 0;
2799  for (k = 0; k < fdof; k++)
2800  if (vdofs[fdof*d+k] >= 0)
2801  {
2802  a += (*this)(vdofs[fdof*d+k]) * shape(k);
2803  }
2804  else
2805  {
2806  a -= (*this)(-1-vdofs[fdof*d+k]) * shape(k);
2807  }
2808  transf->SetIntPoint(&ip);
2809  a -= exsol[d]->Eval(*transf, ip);
2810  error += ip.weight * transf->Weight() * a * a;
2811  }
2812  }
2813  }
2814 
2815  return (error < 0.0) ? -sqrt(-error) : sqrt(error);
2816 }
2817 
2819  VectorCoefficient &exsol, const IntegrationRule *irs[],
2820  const Array<int> *elems) const
2821 {
2822  double error = 0.0;
2823  const FiniteElement *fe;
2825  DenseMatrix vals, exact_vals;
2826  Vector loc_errs;
2827 
2828  for (int i = 0; i < fes->GetNE(); i++)
2829  {
2830  if (elems != NULL && (*elems)[i] == 0) { continue; }
2831  fe = fes->GetFE(i);
2832  int intorder = 2*fe->GetOrder() + 3; // <----------
2833  const IntegrationRule *ir;
2834  if (irs)
2835  {
2836  ir = irs[fe->GetGeomType()];
2837  }
2838  else
2839  {
2840  ir = &(IntRules.Get(fe->GetGeomType(), intorder));
2841  }
2842  T = fes->GetElementTransformation(i);
2843  GetVectorValues(*T, *ir, vals);
2844  exsol.Eval(exact_vals, *T, *ir);
2845  vals -= exact_vals;
2846  loc_errs.SetSize(vals.Width());
2847  vals.Norm2(loc_errs);
2848  for (int j = 0; j < ir->GetNPoints(); j++)
2849  {
2850  const IntegrationPoint &ip = ir->IntPoint(j);
2851  T->SetIntPoint(&ip);
2852  error += ip.weight * T->Weight() * (loc_errs(j) * loc_errs(j));
2853  }
2854  }
2855 
2856  return (error < 0.0) ? -sqrt(-error) : sqrt(error);
2857 }
2858 
2860  VectorCoefficient *exgrad,
2861  const IntegrationRule *irs[]) const
2862 {
2863  double error = 0.0;
2864  const FiniteElement *fe;
2866  Array<int> dofs;
2867  Vector grad;
2868  int intorder;
2869  int dim = fes->GetMesh()->SpaceDimension();
2870  Vector vec(dim);
2871 
2872  fe = fes->GetFE(ielem);
2873  Tr = fes->GetElementTransformation(ielem);
2874  intorder = 2*fe->GetOrder() + 3; // <--------
2875  const IntegrationRule *ir;
2876  if (irs)
2877  {
2878  ir = irs[fe->GetGeomType()];
2879  }
2880  else
2881  {
2882  ir = &(IntRules.Get(fe->GetGeomType(), intorder));
2883  }
2884  fes->GetElementDofs(ielem, dofs);
2885  for (int j = 0; j < ir->GetNPoints(); j++)
2886  {
2887  const IntegrationPoint &ip = ir->IntPoint(j);
2888  Tr->SetIntPoint(&ip);
2889  GetGradient(*Tr,grad);
2890  exgrad->Eval(vec,*Tr,ip);
2891  vec-=grad;
2892  error += ip.weight * Tr->Weight() * (vec * vec);
2893  }
2894  return (error < 0.0) ? -sqrt(-error) : sqrt(error);
2895 }
2896 
2898  const IntegrationRule *irs[]) const
2899 {
2900  double error = 0.0;
2901  const FiniteElement *fe;
2903  Array<int> dofs;
2904  Vector grad;
2905  int intorder;
2906  int dim = fes->GetMesh()->SpaceDimension();
2907  Vector vec(dim);
2908 
2909  for (int i = 0; i < fes->GetNE(); i++)
2910  {
2911  fe = fes->GetFE(i);
2912  Tr = fes->GetElementTransformation(i);
2913  intorder = 2*fe->GetOrder() + 3; // <--------
2914  const IntegrationRule *ir;
2915  if (irs)
2916  {
2917  ir = irs[fe->GetGeomType()];
2918  }
2919  else
2920  {
2921  ir = &(IntRules.Get(fe->GetGeomType(), intorder));
2922  }
2923  fes->GetElementDofs(i, dofs);
2924  for (int j = 0; j < ir->GetNPoints(); j++)
2925  {
2926  const IntegrationPoint &ip = ir->IntPoint(j);
2927  Tr->SetIntPoint(&ip);
2928  GetGradient(*Tr,grad);
2929  exgrad->Eval(vec,*Tr,ip);
2930  vec-=grad;
2931  error += ip.weight * Tr->Weight() * (vec * vec);
2932  }
2933  }
2934  return (error < 0.0) ? -sqrt(-error) : sqrt(error);
2935 }
2936 
2938  const IntegrationRule *irs[]) const
2939 {
2940  double error = 0.0;
2941  const FiniteElement *fe;
2943  Array<int> dofs;
2944  int intorder;
2945  int n = CurlDim();
2946  Vector curl(n);
2947  Vector vec(n);
2948 
2949  for (int i = 0; i < fes->GetNE(); i++)
2950  {
2951  fe = fes->GetFE(i);
2952  Tr = fes->GetElementTransformation(i);
2953  intorder = 2*fe->GetOrder() + 3;
2954  const IntegrationRule *ir;
2955  if (irs)
2956  {
2957  ir = irs[fe->GetGeomType()];
2958  }
2959  else
2960  {
2961  ir = &(IntRules.Get(fe->GetGeomType(), intorder));
2962  }
2963  fes->GetElementDofs(i, dofs);
2964  for (int j = 0; j < ir->GetNPoints(); j++)
2965  {
2966  const IntegrationPoint &ip = ir->IntPoint(j);
2967  Tr->SetIntPoint(&ip);
2968  GetCurl(*Tr,curl);
2969  excurl->Eval(vec,*Tr,ip);
2970  vec-=curl;
2971  error += ip.weight * Tr->Weight() * ( vec * vec );
2972  }
2973  }
2974 
2975  return (error < 0.0) ? -sqrt(-error) : sqrt(error);
2976 }
2977 
2979  Coefficient *exdiv, const IntegrationRule *irs[]) const
2980 {
2981  double error = 0.0, a;
2982  const FiniteElement *fe;
2984  Array<int> dofs;
2985  int intorder;
2986 
2987  for (int i = 0; i < fes->GetNE(); i++)
2988  {
2989  fe = fes->GetFE(i);
2990  Tr = fes->GetElementTransformation(i);
2991  intorder = 2*fe->GetOrder() + 3;
2992  const IntegrationRule *ir;
2993  if (irs)
2994  {
2995  ir = irs[fe->GetGeomType()];
2996  }
2997  else
2998  {
2999  ir = &(IntRules.Get(fe->GetGeomType(), intorder));
3000  }
3001  fes->GetElementDofs(i, dofs);
3002  for (int j = 0; j < ir->GetNPoints(); j++)
3003  {
3004  const IntegrationPoint &ip = ir->IntPoint(j);
3005  Tr->SetIntPoint (&ip);
3006  a = GetDivergence(*Tr) - exdiv->Eval(*Tr, ip);
3007  error += ip.weight * Tr->Weight() * a * a;
3008  }
3009  }
3010 
3011  return (error < 0.0) ? -sqrt(-error) : sqrt(error);
3012 }
3013 
3015  Coefficient *ell_coeff,
3016  class JumpScaling jump_scaling,
3017  const IntegrationRule *irs[]) const
3018 {
3019  int fdof, intorder, k;
3020  Mesh *mesh;
3021  const FiniteElement *fe;
3022  ElementTransformation *transf;
3023  FaceElementTransformations *face_elem_transf;
3024  Vector shape, el_dofs, err_val, ell_coeff_val;
3025  Array<int> vdofs;
3026  IntegrationPoint eip;
3027  double error = 0.0;
3028 
3029  mesh = fes->GetMesh();
3030 
3031  for (int i = 0; i < mesh->GetNumFaces(); i++)
3032  {
3033  int i1, i2;
3034  mesh->GetFaceElements(i, &i1, &i2);
3035  double h = mesh->GetElementSize(i1);
3036  intorder = fes->GetFE(i1)->GetOrder();
3037  if (i2 >= 0)
3038  {
3039  if ( (k = fes->GetFE(i2)->GetOrder()) > intorder )
3040  {
3041  intorder = k;
3042  }
3043  h = std::min(h, mesh->GetElementSize(i2));
3044  }
3045  int p = intorder;
3046  intorder = 2 * intorder; // <-------------
3047  face_elem_transf = mesh->GetFaceElementTransformations(i, 5);
3048  const IntegrationRule *ir;
3049  if (irs)
3050  {
3051  ir = irs[face_elem_transf->GetGeometryType()];
3052  }
3053  else
3054  {
3055  ir = &(IntRules.Get(face_elem_transf->GetGeometryType(), intorder));
3056  }
3057  err_val.SetSize(ir->GetNPoints());
3058  ell_coeff_val.SetSize(ir->GetNPoints());
3059  // side 1
3060  transf = face_elem_transf->Elem1;
3061  fe = fes->GetFE(i1);
3062  fdof = fe->GetDof();
3063  fes->GetElementVDofs(i1, vdofs);
3064  shape.SetSize(fdof);
3065  el_dofs.SetSize(fdof);
3066  for (k = 0; k < fdof; k++)
3067  if (vdofs[k] >= 0)
3068  {
3069  el_dofs(k) = (*this)(vdofs[k]);
3070  }
3071  else
3072  {
3073  el_dofs(k) = - (*this)(-1-vdofs[k]);
3074  }
3075  for (int j = 0; j < ir->GetNPoints(); j++)
3076  {
3077  face_elem_transf->Loc1.Transform(ir->IntPoint(j), eip);
3078  fe->CalcShape(eip, shape);
3079  transf->SetIntPoint(&eip);
3080  ell_coeff_val(j) = ell_coeff->Eval(*transf, eip);
3081  err_val(j) = exsol->Eval(*transf, eip) - (shape * el_dofs);
3082  }
3083  if (i2 >= 0)
3084  {
3085  // side 2
3086  face_elem_transf = mesh->GetFaceElementTransformations(i, 10);
3087  transf = face_elem_transf->Elem2;
3088  fe = fes->GetFE(i2);
3089  fdof = fe->GetDof();
3090  fes->GetElementVDofs(i2, vdofs);
3091  shape.SetSize(fdof);
3092  el_dofs.SetSize(fdof);
3093  for (k = 0; k < fdof; k++)
3094  if (vdofs[k] >= 0)
3095  {
3096  el_dofs(k) = (*this)(vdofs[k]);
3097  }
3098  else
3099  {
3100  el_dofs(k) = - (*this)(-1-vdofs[k]);
3101  }
3102  for (int j = 0; j < ir->GetNPoints(); j++)
3103  {
3104  face_elem_transf->Loc2.Transform(ir->IntPoint(j), eip);
3105  fe->CalcShape(eip, shape);
3106  transf->SetIntPoint(&eip);
3107  ell_coeff_val(j) += ell_coeff->Eval(*transf, eip);
3108  ell_coeff_val(j) *= 0.5;
3109  err_val(j) -= (exsol->Eval(*transf, eip) - (shape * el_dofs));
3110  }
3111  }
3112  face_elem_transf = mesh->GetFaceElementTransformations(i, 16);
3113  transf = face_elem_transf;
3114  for (int j = 0; j < ir->GetNPoints(); j++)
3115  {
3116  const IntegrationPoint &ip = ir->IntPoint(j);
3117  transf->SetIntPoint(&ip);
3118  double nu = jump_scaling.Eval(h, p);
3119  error += (ip.weight * nu * ell_coeff_val(j) *
3120  transf->Weight() *
3121  err_val(j) * err_val(j));
3122  }
3123  }
3124 
3125  return (error < 0.0) ? -sqrt(-error) : sqrt(error);
3126 }
3127 
3129  Coefficient *ell_coeff,
3130  double Nu,
3131  const IntegrationRule *irs[]) const
3132 {
3133  return ComputeDGFaceJumpError(
3134  exsol, ell_coeff, {Nu, JumpScaling::ONE_OVER_H}, irs);
3135 }
3136 
3138  VectorCoefficient *exgrad,
3139  Coefficient *ell_coef, double Nu,
3140  int norm_type) const
3141 {
3142  double error1 = 0.0;
3143  double error2 = 0.0;
3144  if (norm_type & 1) { error1 = GridFunction::ComputeGradError(exgrad); }
3145  if (norm_type & 2)
3146  {
3148  exsol, ell_coef, {Nu, JumpScaling::ONE_OVER_H});
3149  }
3150 
3151  return sqrt(error1 * error1 + error2 * error2);
3152 }
3153 
3155  VectorCoefficient *exgrad,
3156  const IntegrationRule *irs[]) const
3157 {
3158  double L2error = GridFunction::ComputeLpError(2.0,*exsol,NULL,irs);
3159  double GradError = GridFunction::ComputeGradError(exgrad,irs);
3160  return sqrt(L2error*L2error + GradError*GradError);
3161 }
3162 
3164  Coefficient *exdiv,
3165  const IntegrationRule *irs[]) const
3166 {
3167  double L2error = GridFunction::ComputeLpError(2.0,*exsol,NULL,NULL,irs);
3168  double DivError = GridFunction::ComputeDivError(exdiv,irs);
3169  return sqrt(L2error*L2error + DivError*DivError);
3170 }
3171 
3173  VectorCoefficient *excurl,
3174  const IntegrationRule *irs[]) const
3175 {
3176  double L2error = GridFunction::ComputeLpError(2.0,*exsol,NULL,NULL,irs);
3177  double CurlError = GridFunction::ComputeCurlError(excurl,irs);
3178  return sqrt(L2error*L2error + CurlError*CurlError);
3179 }
3180 
3182  Coefficient *exsol[], const IntegrationRule *irs[]) const
3183 {
3184  double error = 0.0, a;
3185  const FiniteElement *fe;
3186  ElementTransformation *transf;
3187  Vector shape;
3188  Array<int> vdofs;
3189  int fdof, d, i, intorder, j, k;
3190 
3191  for (i = 0; i < fes->GetNE(); i++)
3192  {
3193  fe = fes->GetFE(i);
3194  fdof = fe->GetDof();
3195  transf = fes->GetElementTransformation(i);
3196  shape.SetSize(fdof);
3197  intorder = 2*fe->GetOrder() + 3; // <----------
3198  const IntegrationRule *ir;
3199  if (irs)
3200  {
3201  ir = irs[fe->GetGeomType()];
3202  }
3203  else
3204  {
3205  ir = &(IntRules.Get(fe->GetGeomType(), intorder));
3206  }
3207  fes->GetElementVDofs(i, vdofs);
3208  for (j = 0; j < ir->GetNPoints(); j++)
3209  {
3210  const IntegrationPoint &ip = ir->IntPoint(j);
3211  fe->CalcShape(ip, shape);
3212  transf->SetIntPoint(&ip);
3213  for (d = 0; d < fes->GetVDim(); d++)
3214  {
3215  a = 0;
3216  for (k = 0; k < fdof; k++)
3217  if (vdofs[fdof*d+k] >= 0)
3218  {
3219  a += (*this)(vdofs[fdof*d+k]) * shape(k);
3220  }
3221  else
3222  {
3223  a -= (*this)(-1-vdofs[fdof*d+k]) * shape(k);
3224  }
3225  a -= exsol[d]->Eval(*transf, ip);
3226  a = fabs(a);
3227  if (error < a)
3228  {
3229  error = a;
3230  }
3231  }
3232  }
3233  }
3234  return error;
3235 }
3236 
3238  Coefficient *exsol, VectorCoefficient *exgrad, int norm_type,
3239  const Array<int> *elems, const IntegrationRule *irs[]) const
3240 {
3241  // assuming vdim is 1
3242  int i, fdof, dim, intorder, j, k;
3243  Mesh *mesh;
3244  const FiniteElement *fe;
3245  ElementTransformation *transf;
3246  Vector e_grad, a_grad, shape, el_dofs, err_val, ell_coeff_val;
3247  DenseMatrix dshape, dshapet, Jinv;
3248  Array<int> vdofs;
3249  double a, error = 0.0;
3250 
3251  mesh = fes->GetMesh();
3252  dim = mesh->Dimension();
3253  e_grad.SetSize(dim);
3254  a_grad.SetSize(dim);
3255  Jinv.SetSize(dim);
3256 
3257  if (norm_type & 1) // L_1 norm
3258  for (i = 0; i < mesh->GetNE(); i++)
3259  {
3260  if (elems != NULL && (*elems)[i] == 0) { continue; }
3261  fe = fes->GetFE(i);
3262  fdof = fe->GetDof();
3263  transf = fes->GetElementTransformation(i);
3264  el_dofs.SetSize(fdof);
3265  shape.SetSize(fdof);
3266  intorder = 2*fe->GetOrder() + 1; // <----------
3267  const IntegrationRule *ir;
3268  if (irs)
3269  {
3270  ir = irs[fe->GetGeomType()];
3271  }
3272  else
3273  {
3274  ir = &(IntRules.Get(fe->GetGeomType(), intorder));
3275  }
3276  fes->GetElementVDofs(i, vdofs);
3277  for (k = 0; k < fdof; k++)
3278  if (vdofs[k] >= 0)
3279  {
3280  el_dofs(k) = (*this)(vdofs[k]);
3281  }
3282  else
3283  {
3284  el_dofs(k) = -(*this)(-1-vdofs[k]);
3285  }
3286  for (j = 0; j < ir->GetNPoints(); j++)
3287  {
3288  const IntegrationPoint &ip = ir->IntPoint(j);
3289  fe->CalcShape(ip, shape);
3290  transf->SetIntPoint(&ip);
3291  a = (el_dofs * shape) - (exsol->Eval(*transf, ip));
3292  error += ip.weight * transf->Weight() * fabs(a);
3293  }
3294  }
3295 
3296  if (norm_type & 2) // W^1_1 seminorm
3297  for (i = 0; i < mesh->GetNE(); i++)
3298  {
3299  if (elems != NULL && (*elems)[i] == 0) { continue; }
3300  fe = fes->GetFE(i);
3301  fdof = fe->GetDof();
3302  transf = mesh->GetElementTransformation(i);
3303  el_dofs.SetSize(fdof);
3304  dshape.SetSize(fdof, dim);
3305  dshapet.SetSize(fdof, dim);
3306  intorder = 2*fe->GetOrder() + 1; // <----------
3307  const IntegrationRule *ir;
3308  if (irs)
3309  {
3310  ir = irs[fe->GetGeomType()];
3311  }
3312  else
3313  {
3314  ir = &(IntRules.Get(fe->GetGeomType(), intorder));
3315  }
3316  fes->GetElementVDofs(i, vdofs);
3317  for (k = 0; k < fdof; k++)
3318  if (vdofs[k] >= 0)
3319  {
3320  el_dofs(k) = (*this)(vdofs[k]);
3321  }
3322  else
3323  {
3324  el_dofs(k) = -(*this)(-1-vdofs[k]);
3325  }
3326  for (j = 0; j < ir->GetNPoints(); j++)
3327  {
3328  const IntegrationPoint &ip = ir->IntPoint(j);
3329  fe->CalcDShape(ip, dshape);
3330  transf->SetIntPoint(&ip);
3331  exgrad->Eval(e_grad, *transf, ip);
3332  CalcInverse(transf->Jacobian(), Jinv);
3333  Mult(dshape, Jinv, dshapet);
3334  dshapet.MultTranspose(el_dofs, a_grad);
3335  e_grad -= a_grad;
3336  error += ip.weight * transf->Weight() * e_grad.Norml1();
3337  }
3338  }
3339 
3340  return error;
3341 }
3342 
3343 double GridFunction::ComputeLpError(const double p, Coefficient &exsol,
3344  Coefficient *weight,
3345  const IntegrationRule *irs[],
3346  const Array<int> *elems) const
3347 {
3348  double error = 0.0;
3349  const FiniteElement *fe;
3351  Vector vals;
3352 
3353  for (int i = 0; i < fes->GetNE(); i++)
3354  {
3355  if (elems != NULL && (*elems)[i] == 0) { continue; }
3356  fe = fes->GetFE(i);
3357  const IntegrationRule *ir;
3358  if (irs)
3359  {
3360  ir = irs[fe->GetGeomType()];
3361  }
3362  else
3363  {
3364  int intorder = 2*fe->GetOrder() + 3; // <----------
3365  ir = &(IntRules.Get(fe->GetGeomType(), intorder));
3366  }
3367  GetValues(i, *ir, vals);
3368  T = fes->GetElementTransformation(i);
3369  for (int j = 0; j < ir->GetNPoints(); j++)
3370  {
3371  const IntegrationPoint &ip = ir->IntPoint(j);
3372  T->SetIntPoint(&ip);
3373  double diff = fabs(vals(j) - exsol.Eval(*T, ip));
3374  if (p < infinity())
3375  {
3376  diff = pow(diff, p);
3377  if (weight)
3378  {
3379  diff *= weight->Eval(*T, ip);
3380  }
3381  error += ip.weight * T->Weight() * diff;
3382  }
3383  else
3384  {
3385  if (weight)
3386  {
3387  diff *= weight->Eval(*T, ip);
3388  }
3389  error = std::max(error, diff);
3390  }
3391  }
3392  }
3393 
3394  if (p < infinity())
3395  {
3396  // negative quadrature weights may cause the error to be negative
3397  if (error < 0.)
3398  {
3399  error = -pow(-error, 1./p);
3400  }
3401  else
3402  {
3403  error = pow(error, 1./p);
3404  }
3405  }
3406 
3407  return error;
3408 }
3409 
3411  Vector &error,
3412  Coefficient *weight,
3413  const IntegrationRule *irs[]) const
3414 {
3415  MFEM_ASSERT(error.Size() == fes->GetNE(),
3416  "Incorrect size for result vector");
3417 
3418  error = 0.0;
3419  const FiniteElement *fe;
3421  Vector vals;
3422 
3423  for (int i = 0; i < fes->GetNE(); i++)
3424  {
3425  fe = fes->GetFE(i);
3426  const IntegrationRule *ir;
3427  if (irs)
3428  {
3429  ir = irs[fe->GetGeomType()];
3430  }
3431  else
3432  {
3433  int intorder = 2*fe->GetOrder() + 3; // <----------
3434  ir = &(IntRules.Get(fe->GetGeomType(), intorder));
3435  }
3436  GetValues(i, *ir, vals);
3437  T = fes->GetElementTransformation(i);
3438  for (int j = 0; j < ir->GetNPoints(); j++)
3439  {
3440  const IntegrationPoint &ip = ir->IntPoint(j);
3441  T->SetIntPoint(&ip);
3442  double diff = fabs(vals(j) - exsol.Eval(*T, ip));
3443  if (p < infinity())
3444  {
3445  diff = pow(diff, p);
3446  if (weight)
3447  {
3448  diff *= weight->Eval(*T, ip);
3449  }
3450  error[i] += ip.weight * T->Weight() * diff;
3451  }
3452  else
3453  {
3454  if (weight)
3455  {
3456  diff *= weight->Eval(*T, ip);
3457  }
3458  error[i] = std::max(error[i], diff);
3459  }
3460  }
3461  if (p < infinity())
3462  {
3463  // negative quadrature weights may cause the error to be negative
3464  if (error[i] < 0.)
3465  {
3466  error[i] = -pow(-error[i], 1./p);
3467  }
3468  else
3469  {
3470  error[i] = pow(error[i], 1./p);
3471  }
3472  }
3473  }
3474 }
3475 
3477  Coefficient *weight,
3478  VectorCoefficient *v_weight,
3479  const IntegrationRule *irs[]) const
3480 {
3481  double error = 0.0;
3482  const FiniteElement *fe;
3484  DenseMatrix vals, exact_vals;
3485  Vector loc_errs;
3486 
3487  for (int i = 0; i < fes->GetNE(); i++)
3488  {
3489  fe = fes->GetFE(i);
3490  const IntegrationRule *ir;
3491  if (irs)
3492  {
3493  ir = irs[fe->GetGeomType()];
3494  }
3495  else
3496  {
3497  int intorder = 2*fe->GetOrder() + 3; // <----------
3498  ir = &(IntRules.Get(fe->GetGeomType(), intorder));
3499  }
3500  T = fes->GetElementTransformation(i);
3501  GetVectorValues(*T, *ir, vals);
3502  exsol.Eval(exact_vals, *T, *ir);
3503  vals -= exact_vals;
3504  loc_errs.SetSize(vals.Width());
3505  if (!v_weight)
3506  {
3507  // compute the lengths of the errors at the integration points
3508  // thus the vector norm is rotationally invariant
3509  vals.Norm2(loc_errs);
3510  }
3511  else
3512  {
3513  v_weight->Eval(exact_vals, *T, *ir);
3514  // column-wise dot product of the vector error (in vals) and the
3515  // vector weight (in exact_vals)
3516  for (int j = 0; j < vals.Width(); j++)
3517  {
3518  double errj = 0.0;
3519  for (int d = 0; d < vals.Height(); d++)
3520  {
3521  errj += vals(d,j)*exact_vals(d,j);
3522  }
3523  loc_errs(j) = fabs(errj);
3524  }
3525  }
3526  for (int j = 0; j < ir->GetNPoints(); j++)
3527  {
3528  const IntegrationPoint &ip = ir->IntPoint(j);
3529  T->SetIntPoint(&ip);
3530  double errj = loc_errs(j);
3531  if (p < infinity())
3532  {
3533  errj = pow(errj, p);
3534  if (weight)
3535  {
3536  errj *= weight->Eval(*T, ip);
3537  }
3538  error += ip.weight * T->Weight() * errj;
3539  }
3540  else
3541  {
3542  if (weight)
3543  {
3544  errj *= weight->Eval(*T, ip);
3545  }
3546  error = std::max(error, errj);
3547  }
3548  }
3549  }
3550 
3551  if (p < infinity())
3552  {
3553  // negative quadrature weights may cause the error to be negative
3554  if (error < 0.)
3555  {
3556  error = -pow(-error, 1./p);
3557  }
3558  else
3559  {
3560  error = pow(error, 1./p);
3561  }
3562  }
3563 
3564  return error;
3565 }
3566 
3568  VectorCoefficient &exsol,
3569  Vector &error,
3570  Coefficient *weight,
3571  VectorCoefficient *v_weight,
3572  const IntegrationRule *irs[]) const
3573 {
3574  MFEM_ASSERT(error.Size() == fes->GetNE(),
3575  "Incorrect size for result vector");
3576 
3577  error = 0.0;
3578  const FiniteElement *fe;
3580  DenseMatrix vals, exact_vals;
3581  Vector loc_errs;
3582 
3583  for (int i = 0; i < fes->GetNE(); i++)
3584  {
3585  fe = fes->GetFE(i);
3586  const IntegrationRule *ir;
3587  if (irs)
3588  {
3589  ir = irs[fe->GetGeomType()];
3590  }
3591  else
3592  {
3593  int intorder = 2*fe->GetOrder() + 3; // <----------
3594  ir = &(IntRules.Get(fe->GetGeomType(), intorder));
3595  }
3596  T = fes->GetElementTransformation(i);
3597  GetVectorValues(*T, *ir, vals);
3598  exsol.Eval(exact_vals, *T, *ir);
3599  vals -= exact_vals;
3600  loc_errs.SetSize(vals.Width());
3601  if (!v_weight)
3602  {
3603  // compute the lengths of the errors at the integration points thus the
3604  // vector norm is rotationally invariant
3605  vals.Norm2(loc_errs);
3606  }
3607  else
3608  {
3609  v_weight->Eval(exact_vals, *T, *ir);
3610  // column-wise dot product of the vector error (in vals) and the vector
3611  // weight (in exact_vals)
3612  for (int j = 0; j < vals.Width(); j++)
3613  {
3614  double errj = 0.0;
3615  for (int d = 0; d < vals.Height(); d++)
3616  {
3617  errj += vals(d,j)*exact_vals(d,j);
3618  }
3619  loc_errs(j) = fabs(errj);
3620  }
3621  }
3622  for (int j = 0; j < ir->GetNPoints(); j++)
3623  {
3624  const IntegrationPoint &ip = ir->IntPoint(j);
3625  T->SetIntPoint(&ip);
3626  double errj = loc_errs(j);
3627  if (p < infinity())
3628  {
3629  errj = pow(errj, p);
3630  if (weight)
3631  {
3632  errj *= weight->Eval(*T, ip);
3633  }
3634  error[i] += ip.weight * T->Weight() * errj;
3635  }
3636  else
3637  {
3638  if (weight)
3639  {
3640  errj *= weight->Eval(*T, ip);
3641  }
3642  error[i] = std::max(error[i], errj);
3643  }
3644  }
3645  if (p < infinity())
3646  {
3647  // negative quadrature weights may cause the error to be negative
3648  if (error[i] < 0.)
3649  {
3650  error[i] = -pow(-error[i], 1./p);
3651  }
3652  else
3653  {
3654  error[i] = pow(error[i], 1./p);
3655  }
3656  }
3657  }
3658 }
3659 
3661 {
3662  Vector::operator=(value);
3663  return *this;
3664 }
3665 
3667 {
3668  MFEM_ASSERT(fes && v.Size() == fes->GetVSize(), "");
3669  Vector::operator=(v);
3670  return *this;
3671 }
3672 
3673 void GridFunction::Save(std::ostream &os) const
3674 {
3675  fes->Save(os);
3676  os << '\n';
3677 #if 0
3678  // Testing: write NURBS GridFunctions using "NURBS_patches" format.
3679  if (fes->GetNURBSext())
3680  {
3681  os << "NURBS_patches\n";
3682  fes->GetNURBSext()->PrintSolution(*this, os);
3683  os.flush();
3684  return;
3685  }
3686 #endif
3687  if (fes->GetOrdering() == Ordering::byNODES)
3688  {
3689  Vector::Print(os, 1);
3690  }
3691  else
3692  {
3693  Vector::Print(os, fes->GetVDim());
3694  }
3695  os.flush();
3696 }
3697 
3698 void GridFunction::Save(const char *fname, int precision) const
3699 {
3700  ofstream ofs(fname);
3701  ofs.precision(precision);
3702  Save(ofs);
3703 }
3704 
3705 #ifdef MFEM_USE_ADIOS2
3707  const std::string& variable_name,
3708  const adios2stream::data_type type) const
3709 {
3710  os.Save(*this, variable_name, type);
3711 }
3712 #endif
3713 
3714 void GridFunction::SaveVTK(std::ostream &os, const std::string &field_name,
3715  int ref)
3716 {
3717  Mesh *mesh = fes->GetMesh();
3718  RefinedGeometry *RefG;
3719  Vector val;
3720  DenseMatrix vval, pmat;
3721  int vec_dim = VectorDim();
3722 
3723  if (vec_dim == 1)
3724  {
3725  // scalar data
3726  os << "SCALARS " << field_name << " double 1\n"
3727  << "LOOKUP_TABLE default\n";
3728  for (int i = 0; i < mesh->GetNE(); i++)
3729  {
3730  RefG = GlobGeometryRefiner.Refine(
3731  mesh->GetElementBaseGeometry(i), ref, 1);
3732 
3733  GetValues(i, RefG->RefPts, val, pmat);
3734 
3735  for (int j = 0; j < val.Size(); j++)
3736  {
3737  os << val(j) << '\n';
3738  }
3739  }
3740  }
3741  else if ( (vec_dim == 2 || vec_dim == 3) && mesh->SpaceDimension() > 1)
3742  {
3743  // vector data
3744  os << "VECTORS " << field_name << " double\n";
3745  for (int i = 0; i < mesh->GetNE(); i++)
3746  {
3747  RefG = GlobGeometryRefiner.Refine(
3748  mesh->GetElementBaseGeometry(i), ref, 1);
3749 
3750  // GetVectorValues(i, RefG->RefPts, vval, pmat);
3752  GetVectorValues(*T, RefG->RefPts, vval, &pmat);
3753 
3754  for (int j = 0; j < vval.Width(); j++)
3755  {
3756  os << vval(0, j) << ' ' << vval(1, j) << ' ';
3757  if (vval.Height() == 2)
3758  {
3759  os << 0.0;
3760  }
3761  else
3762  {
3763  os << vval(2, j);
3764  }
3765  os << '\n';
3766  }
3767  }
3768  }
3769  else
3770  {
3771  // other data: save the components as separate scalars
3772  for (int vd = 0; vd < vec_dim; vd++)
3773  {
3774  os << "SCALARS " << field_name << vd << " double 1\n"
3775  << "LOOKUP_TABLE default\n";
3776  for (int i = 0; i < mesh->GetNE(); i++)
3777  {
3778  RefG = GlobGeometryRefiner.Refine(
3779  mesh->GetElementBaseGeometry(i), ref, 1);
3780 
3781  GetValues(i, RefG->RefPts, val, pmat, vd + 1);
3782 
3783  for (int j = 0; j < val.Size(); j++)
3784  {
3785  os << val(j) << '\n';
3786  }
3787  }
3788  }
3789  }
3790  os.flush();
3791 }
3792 
3793 void GridFunction::SaveSTLTri(std::ostream &os, double p1[], double p2[],
3794  double p3[])
3795 {
3796  double v1[3] = { p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2] };
3797  double v2[3] = { p3[0] - p1[0], p3[1] - p1[1], p3[2] - p1[2] };
3798  double n[] = { v1[1] * v2[2] - v1[2] * v2[1],
3799  v1[2] * v2[0] - v1[0] * v2[2],
3800  v1[0] * v2[1] - v1[1] * v2[0]
3801  };
3802  double rl = 1.0 / sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]);
3803  n[0] *= rl; n[1] *= rl; n[2] *= rl;
3804 
3805  os << " facet normal " << n[0] << ' ' << n[1] << ' ' << n[2]
3806  << "\n outer loop"
3807  << "\n vertex " << p1[0] << ' ' << p1[1] << ' ' << p1[2]
3808  << "\n vertex " << p2[0] << ' ' << p2[1] << ' ' << p2[2]
3809  << "\n vertex " << p3[0] << ' ' << p3[1] << ' ' << p3[2]
3810  << "\n endloop\n endfacet\n";
3811 }
3812 
3813 void GridFunction::SaveSTL(std::ostream &os, int TimesToRefine)
3814 {
3815  Mesh *mesh = fes->GetMesh();
3816 
3817  if (mesh->Dimension() != 2)
3818  {
3819  return;
3820  }
3821 
3822  int i, j, k, l, n;
3823  DenseMatrix pointmat;
3824  Vector values;
3825  RefinedGeometry * RefG;
3826  double pts[4][3], bbox[3][2];
3827 
3828  os << "solid GridFunction\n";
3829 
3830  bbox[0][0] = bbox[0][1] = bbox[1][0] = bbox[1][1] =
3831  bbox[2][0] = bbox[2][1] = 0.0;
3832  for (i = 0; i < mesh->GetNE(); i++)
3833  {
3834  Geometry::Type geom = mesh->GetElementBaseGeometry(i);
3835  RefG = GlobGeometryRefiner.Refine(geom, TimesToRefine);
3836  GetValues(i, RefG->RefPts, values, pointmat);
3837  Array<int> &RG = RefG->RefGeoms;
3838  n = Geometries.NumBdr(geom);
3839  for (k = 0; k < RG.Size()/n; k++)
3840  {
3841  for (j = 0; j < n; j++)
3842  {
3843  l = RG[n*k+j];
3844  pts[j][0] = pointmat(0,l);
3845  pts[j][1] = pointmat(1,l);
3846  pts[j][2] = values(l);
3847  }
3848 
3849  if (n == 3)
3850  {
3851  SaveSTLTri(os, pts[0], pts[1], pts[2]);
3852  }
3853  else
3854  {
3855  SaveSTLTri(os, pts[0], pts[1], pts[2]);
3856  SaveSTLTri(os, pts[0], pts[2], pts[3]);
3857  }
3858  }
3859 
3860  if (i == 0)
3861  {
3862  bbox[0][0] = pointmat(0,0);
3863  bbox[0][1] = pointmat(0,0);
3864  bbox[1][0] = pointmat(1,0);
3865  bbox[1][1] = pointmat(1,0);
3866  bbox[2][0] = values(0);
3867  bbox[2][1] = values(0);
3868  }
3869 
3870  for (j = 0; j < values.Size(); j++)
3871  {
3872  if (bbox[0][0] > pointmat(0,j))
3873  {
3874  bbox[0][0] = pointmat(0,j);
3875  }
3876  if (bbox[0][1] < pointmat(0,j))
3877  {
3878  bbox[0][1] = pointmat(0,j);
3879  }
3880  if (bbox[1][0] > pointmat(1,j))
3881  {
3882  bbox[1][0] = pointmat(1,j);
3883  }
3884  if (bbox[1][1] < pointmat(1,j))
3885  {
3886  bbox[1][1] = pointmat(1,j);
3887  }
3888  if (bbox[2][0] > values(j))
3889  {
3890  bbox[2][0] = values(j);
3891  }
3892  if (bbox[2][1] < values(j))
3893  {
3894  bbox[2][1] = values(j);
3895  }
3896  }
3897  }
3898 
3899  mfem::out << "[xmin,xmax] = [" << bbox[0][0] << ',' << bbox[0][1] << "]\n"
3900  << "[ymin,ymax] = [" << bbox[1][0] << ',' << bbox[1][1] << "]\n"
3901  << "[zmin,zmax] = [" << bbox[2][0] << ',' << bbox[2][1] << ']'
3902  << endl;
3903 
3904  os << "endsolid GridFunction" << endl;
3905 }
3906 
3907 std::ostream &operator<<(std::ostream &os, const GridFunction &sol)
3908 {
3909  sol.Save(os);
3910  return os;
3911 }
3912 
3914 {
3915  const Mesh* mesh = fes->GetMesh();
3916  MFEM_ASSERT(mesh->Nonconforming(), "");
3917 
3918  // get the mapping (old_vertex_index -> new_vertex_index)
3919  Array<int> new_vertex, old_vertex;
3920  mesh->ncmesh->LegacyToNewVertexOrdering(new_vertex);
3921  MFEM_ASSERT(new_vertex.Size() == mesh->GetNV(), "");
3922 
3923  // get the mapping (new_vertex_index -> old_vertex_index)
3924  old_vertex.SetSize(new_vertex.Size());
3925  for (int i = 0; i < new_vertex.Size(); i++)
3926  {
3927  old_vertex[new_vertex[i]] = i;
3928  }
3929 
3930  Vector tmp = *this;
3931 
3932  // reorder vertex DOFs
3933  Array<int> old_vdofs, new_vdofs;
3934  for (int i = 0; i < mesh->GetNV(); i++)
3935  {
3936  fes->GetVertexVDofs(i, old_vdofs);
3937  fes->GetVertexVDofs(new_vertex[i], new_vdofs);
3938 
3939  for (int j = 0; j < new_vdofs.Size(); j++)
3940  {
3941  tmp(new_vdofs[j]) = (*this)(old_vdofs[j]);
3942  }
3943  }
3944 
3945  // reorder edge DOFs -- edge orientation has changed too
3946  Array<int> dofs, ev;
3947  for (int i = 0; i < mesh->GetNEdges(); i++)
3948  {
3949  mesh->GetEdgeVertices(i, ev);
3950  if (old_vertex[ev[0]] > old_vertex[ev[1]])
3951  {
3952  const int *ind = fec->DofOrderForOrientation(Geometry::SEGMENT, -1);
3953 
3954  fes->GetEdgeInteriorDofs(i, dofs);
3955  for (int k = 0; k < dofs.Size(); k++)
3956  {
3957  int new_dof = dofs[k];
3958  int old_dof = dofs[(ind[k] < 0) ? -1-ind[k] : ind[k]];
3959 
3960  for (int j = 0; j < fes->GetVDim(); j++)
3961  {
3962  int new_vdof = fes->DofToVDof(new_dof, j);
3963  int old_vdof = fes->DofToVDof(old_dof, j);
3964 
3965  double sign = (ind[k] < 0) ? -1.0 : 1.0;
3966  tmp(new_vdof) = sign * (*this)(old_vdof);
3967  }
3968  }
3969  }
3970  }
3971 
3972  Vector::Swap(tmp);
3973 }
3974 
3976  GridFunction &u,
3977  GridFunction &flux, Vector &error_estimates,
3978  Array<int>* aniso_flags,
3979  int with_subdomains,
3980  bool with_coeff)
3981 {
3982  FiniteElementSpace *ufes = u.FESpace();
3983  FiniteElementSpace *ffes = flux.FESpace();
3984  ElementTransformation *Transf;
3985 
3986  int dim = ufes->GetMesh()->Dimension();
3987  int nfe = ufes->GetNE();
3988 
3989  Array<int> udofs;
3990  Array<int> fdofs;
3991  Vector ul, fl, fla, d_xyz;
3992 
3993  error_estimates.SetSize(nfe);
3994  if (aniso_flags)
3995  {
3996  aniso_flags->SetSize(nfe);
3997  d_xyz.SetSize(dim);
3998  }
3999 
4000  int nsd = 1;
4001  if (with_subdomains)
4002  {
4003  nsd = ufes->GetMesh()->attributes.Max();
4004  }
4005 
4006  double total_error = 0.0;
4007  for (int s = 1; s <= nsd; s++)
4008  {
4009  // This calls the parallel version when u is a ParGridFunction
4010  u.ComputeFlux(blfi, flux, with_coeff, (with_subdomains ? s : -1));
4011 
4012  for (int i = 0; i < nfe; i++)
4013  {
4014  if (with_subdomains && ufes->GetAttribute(i) != s) { continue; }
4015 
4016  ufes->GetElementVDofs(i, udofs);
4017  ffes->GetElementVDofs(i, fdofs);
4018 
4019  u.GetSubVector(udofs, ul);
4020  flux.GetSubVector(fdofs, fla);
4021 
4022  Transf = ufes->GetElementTransformation(i);
4023  blfi.ComputeElementFlux(*ufes->GetFE(i), *Transf, ul,
4024  *ffes->GetFE(i), fl, with_coeff);
4025 
4026  fl -= fla;
4027 
4028  double eng = blfi.ComputeFluxEnergy(*ffes->GetFE(i), *Transf, fl,
4029  (aniso_flags ? &d_xyz : NULL));
4030 
4031  error_estimates(i) = std::sqrt(eng);
4032  total_error += eng;
4033 
4034  if (aniso_flags)
4035  {
4036  double sum = 0;
4037  for (int k = 0; k < dim; k++)
4038  {
4039  sum += d_xyz[k];
4040  }
4041 
4042  double thresh = 0.15 * 3.0/dim;
4043  int flag = 0;
4044  for (int k = 0; k < dim; k++)
4045  {
4046  if (d_xyz[k] / sum > thresh) { flag |= (1 << k); }
4047  }
4048 
4049  (*aniso_flags)[i] = flag;
4050  }
4051  }
4052  }
4053 #ifdef MFEM_USE_MPI
4054  auto pfes = dynamic_cast<ParFiniteElementSpace*>(ufes);
4055  if (pfes)
4056  {
4057  auto process_local_error = total_error;
4058  MPI_Allreduce(&process_local_error, &total_error, 1, MPI_DOUBLE,
4059  MPI_SUM, pfes->GetComm());
4060  }
4061 #endif // MFEM_USE_MPI
4062  return std::sqrt(total_error);
4063 }
4064 
4065 void TensorProductLegendre(int dim, // input
4066  int order, // input
4067  const Vector &x_in, // input
4068  const Vector &xmax, // input
4069  const Vector &xmin, // input
4070  Vector &poly, // output
4071  double angle, // input (optional)
4072  const Vector *midpoint) // input (optional)
4073 {
4074  MFEM_VERIFY(dim >= 1, "dim must be positive");
4075  MFEM_VERIFY(dim <= 3, "dim cannot be greater than 3");
4076  MFEM_VERIFY(order >= 0, "order cannot be negative");
4077 
4078  bool rotate = (angle != 0.0) || (midpoint->Norml2() != 0.0);
4079 
4080  Vector x(dim);
4081  if (rotate && dim == 2)
4082  {
4083  // Rotate coordinates to match rotated bounding box
4084  Vector tmp(dim);
4085  tmp = x_in;
4086  tmp -= *midpoint;
4087  x[0] = tmp[0]*cos(-angle) - tmp[1]*sin(-angle);
4088  x[1] = tmp[0]*sin(-angle) + tmp[1]*cos(-angle);
4089  }
4090  else
4091  {
4092  // Bounding box is not reoriented no need to change orientation
4093  x = x_in;
4094  }
4095 
4096  // Map x to [0, 1] to use CalcLegendre since it uses shifted Legendre Polynomials.
4097  double x1 = (x(0) - xmin(0))/(xmax(0)-xmin(0)), x2, x3;
4098  Vector poly_x(order+1), poly_y(order+1), poly_z(order+1);
4099  poly1d.CalcLegendre(order, x1, poly_x.GetData());
4100  if (dim > 1)
4101  {
4102  x2 = (x(1)-xmin(1))/(xmax(1)-xmin(1));
4103  poly1d.CalcLegendre(order, x2, poly_y.GetData());
4104  }
4105  if (dim == 3)
4106  {
4107  x3 = (x(2)-xmin(2))/(xmax(2)-xmin(2));
4108  poly1d.CalcLegendre(order, x3, poly_z.GetData());
4109  }
4110 
4111  int basis_dimension = static_cast<int>(pow(order+1,dim));
4112  poly.SetSize(basis_dimension);
4113  switch (dim)
4114  {
4115  case 1:
4116  {
4117  for (int i = 0; i <= order; i++)
4118  {
4119  poly(i) = poly_x(i);
4120  }
4121  }
4122  break;
4123  case 2:
4124  {
4125  for (int j = 0; j <= order; j++)
4126  {
4127  for (int i = 0; i <= order; i++)
4128  {
4129  int cnt = i + (order+1) * j;
4130  poly(cnt) = poly_x(i) * poly_y(j);
4131  }
4132  }
4133  }
4134  break;
4135  case 3:
4136  {
4137  for (int k = 0; k <= order; k++)
4138  {
4139  for (int j = 0; j <= order; j++)
4140  {
4141  for (int i = 0; i <= order; i++)
4142  {
4143  int cnt = i + (order+1) * j + (order+1) * (order+1) * k;
4144  poly(cnt) = poly_x(i) * poly_y(j) * poly_z(k);
4145  }
4146  }
4147  }
4148  }
4149  break;
4150  default:
4151  {
4152  MFEM_ABORT("TensorProductLegendre: invalid value of dim");
4153  }
4154  }
4155 }
4156 
4157 void BoundingBox(const Array<int> &patch, // input
4158  FiniteElementSpace *ufes, // input
4159  int order, // input
4160  Vector &xmin, // output
4161  Vector &xmax, // output
4162  double &angle, // output
4163  Vector &midpoint, // output
4164  int iface) // input (optional)
4165 {
4166  Mesh *mesh = ufes->GetMesh();
4167  int dim = mesh->Dimension();
4168  int num_elems = patch.Size();
4170 
4171  xmax = -infinity();
4172  xmin = infinity();
4173  angle = 0.0;
4174  midpoint = 0.0;
4175  bool rotate = (dim == 2);
4176 
4177  // Rotate bounding box to match the face orientation
4178  if (rotate && iface >= 0)
4179  {
4180  IntegrationPoint reference_pt;
4181  mesh->GetFaceTransformation(iface, &Tr);
4182  Vector physical_pt(2);
4183  Vector physical_diff(2);
4184  physical_diff = 0.0;
4185  // Get the endpoints of the edge in physical space
4186  // then compute midpoint and angle
4187  for (int i = 0; i < 2; i++)
4188  {
4189  reference_pt.Set1w((double)i, 0.0);
4190  Tr.Transform(reference_pt, physical_pt);
4191  midpoint += physical_pt;
4192  physical_pt *= pow(-1.0,i);
4193  physical_diff += physical_pt;
4194  }
4195  midpoint /= 2.0;
4196  angle = atan2(physical_diff(1),physical_diff(0));
4197  }
4198 
4199  for (int i = 0; i < num_elems; i++)
4200  {
4201  int ielem = patch[i];
4202  const IntegrationRule *ir = &(IntRules.Get(mesh->GetElementGeometry(ielem),
4203  order));
4204  ufes->GetElementTransformation(ielem, &Tr);
4205  for (int k = 0; k < ir->GetNPoints(); k++)
4206  {
4207  const IntegrationPoint ip = ir->IntPoint(k);
4208  Vector transip(dim);
4209  Tr.Transform(ip, transip);
4210  if (rotate)
4211  {
4212  transip -= midpoint;
4213  Vector tmp(dim);
4214  tmp = transip;
4215  transip[0] = tmp[0]*cos(-angle) - tmp[1]*sin(-angle);
4216  transip[1] = tmp[0]*sin(-angle) + tmp[1]*cos(-angle);
4217  }
4218  for (int d = 0; d < dim; d++) { xmax(d) = max(xmax(d), transip(d)); }
4219  for (int d = 0; d < dim; d++) { xmin(d) = min(xmin(d), transip(d)); }
4220  }
4221  }
4222 }
4223 
4225  GridFunction &u, // input
4226  Vector &error_estimates, // output
4227  bool subdomain_reconstruction, // input (optional)
4228  bool with_coeff, // input (optional)
4229  double tichonov_coeff) // input (optional)
4230 {
4231  MFEM_VERIFY(tichonov_coeff >= 0.0, "tichonov_coeff cannot be negative");
4232  FiniteElementSpace *ufes = u.FESpace();
4233  ElementTransformation *Transf;
4234 
4235  Mesh *mesh = ufes->GetMesh();
4236  int dim = mesh->Dimension();
4237  int sdim = mesh->SpaceDimension();
4238  int nfe = ufes->GetNE();
4239  int nfaces = ufes->GetNF();
4240 
4241  Array<int> udofs;
4242  Array<int> fdofs;
4243  Vector ul, fl, fla;
4244 
4245  error_estimates.SetSize(nfe);
4246  error_estimates = 0.0;
4247  Array<int> counters(nfe);
4248  counters = 0;
4249 
4250  Vector xmax(dim);
4251  Vector xmin(dim);
4252  double angle = 0.0;
4253  Vector midpoint(dim);
4254 
4255  // Compute the number of subdomains
4256  int nsd = 1;
4257  if (subdomain_reconstruction)
4258  {
4259  nsd = ufes->GetMesh()->attributes.Max();
4260  }
4261 
4262  double total_error = 0.0;
4263  for (int iface = 0; iface < nfaces; iface++)
4264  {
4265  // 1.A. Find all elements in the face patch.
4266  int el1;
4267  int el2;
4268  mesh->GetFaceElements(iface, &el1, &el2);
4269  Array<int> patch(2);
4270  patch[0] = el1; patch[1] = el2;
4271 
4272  // 1.B. Check if boundary face or non-conforming coarse face and continue if true.
4273  if (el1 == -1 || el2 == -1)
4274  {
4275  continue;
4276  }
4277 
4278  // 1.C Check if face patch crosses an attribute interface and
4279  // continue if true (only active if subdomain_reconstruction == true)
4280  if (nsd > 1)
4281  {
4282  int el1_attr = ufes->GetAttribute(el1);
4283  int el2_attr = ufes->GetAttribute(el2);
4284  if (el1_attr != el2_attr) { continue; }
4285  }
4286 
4287  // 2. Compute global flux polynomial.
4288 
4289  // 2.A. Compute polynomial order of patch (for hp FEM)
4290  const int patch_order = max(ufes->GetElementOrder(el1),
4291  ufes->GetElementOrder(el2));
4292 
4293  int num_basis_functions = static_cast<int>(pow(patch_order+1,dim));
4294  int flux_order = 2*patch_order + 1;
4295  DenseMatrix A(num_basis_functions);
4296  Array<double> b(sdim * num_basis_functions);
4297  A = 0.0;
4298  b = 0.0;
4299 
4300  // 2.B. Estimate the smallest bounding box around the face patch
4301  // (this is used in 2.C.ii. to define a global polynomial basis)
4302  BoundingBox(patch, ufes, flux_order,
4303  xmin, xmax, angle, midpoint, iface);
4304 
4305  // 2.C. Compute the normal equations for the least-squares problem
4306  // 2.C.i. Evaluate the discrete flux at all integration points in all
4307  // elements in the face patch
4308  for (int i = 0; i < patch.Size(); i++)
4309  {
4310  int ielem = patch[i];
4311  const IntegrationRule *ir = &(IntRules.Get(mesh->GetElementGeometry(ielem),
4312  flux_order));
4313  int num_integration_pts = ir->GetNPoints();
4314 
4315  ufes->GetElementVDofs(ielem, udofs);
4316  u.GetSubVector(udofs, ul);
4317  Transf = ufes->GetElementTransformation(ielem);
4318  FiniteElement *dummy = nullptr;
4319  blfi.ComputeElementFlux(*ufes->GetFE(ielem), *Transf, ul,
4320  *dummy, fl, with_coeff, ir);
4321 
4322  // 2.C.ii. Use global polynomial basis to construct normal
4323  // equations
4324  for (int k = 0; k < num_integration_pts; k++)
4325  {
4326  const IntegrationPoint ip = ir->IntPoint(k);
4327  double tmp[3];
4328  Vector transip(tmp, 3);
4329  Transf->Transform(ip, transip);
4330 
4331  Vector p;
4332  TensorProductLegendre(dim, patch_order, transip, xmax, xmin, p, angle,
4333  &midpoint);
4334  AddMultVVt(p, A);
4335 
4336  for (int l = 0; l < num_basis_functions; l++)
4337  {
4338  // Loop through each component of the discrete flux
4339  for (int n = 0; n < sdim; n++)
4340  {
4341  b[l + n * num_basis_functions] += p(l) * fl(k + n * num_integration_pts);
4342  }
4343  }
4344  }
4345  }
4346 
4347  // 2.D. Shift spectrum of A to avoid conditioning issues.
4348  // Regularization is necessary if the tensor product space used for the
4349  // flux reconstruction leads to an underdetermined system of linear equations.
4350  // This should not happen if there are tensor product elements in the patch,
4351  // but it can happen if there are other element shapes (those with few
4352  // integration points) in the patch.
4353  for (int i = 0; i < num_basis_functions; i++)
4354  {
4355  A(i,i) += tichonov_coeff;
4356  }
4357 
4358  // 2.E. Solve for polynomial coefficients
4359  Array<int> ipiv(num_basis_functions);
4360  LUFactors lu(A.Data(), ipiv);
4361  double TOL = 1e-9;
4362  if (!lu.Factor(num_basis_functions,TOL))
4363  {
4364  // Singular matrix
4365  mfem::out << "LSZZErrorEstimator: Matrix A is singular.\t"
4366  << "Consider increasing tichonov_coeff." << endl;
4367  for (int i = 0; i < num_basis_functions; i++)
4368  {
4369  A(i,i) += 1e-8;
4370  }
4371  lu.Factor(num_basis_functions,TOL);
4372  }
4373  lu.Solve(num_basis_functions, sdim, b);
4374 
4375  // 2.F. Construct l2-minimizing global polynomial
4376  auto global_poly_tmp = [=] (const Vector &x, Vector &f)
4377  {
4378  Vector p;
4379  TensorProductLegendre(dim, patch_order, x, xmax, xmin, p, angle, &midpoint);
4380  f = 0.0;
4381  for (int i = 0; i < num_basis_functions; i++)
4382  {
4383  for (int j = 0; j < sdim; j++)
4384  {
4385  f(j) += b[i + j * num_basis_functions] * p(i);
4386  }
4387  }
4388  };
4389  VectorFunctionCoefficient global_poly(sdim, global_poly_tmp);
4390 
4391  // 3. Compute error contributions from the face.
4392  double element_error = 0.0;
4393  double patch_error = 0.0;
4394  for (int i = 0; i < patch.Size(); i++)
4395  {
4396  int ielem = patch[i];
4397  element_error = u.ComputeElementGradError(ielem, &global_poly);
4398  element_error *= element_error;
4399  patch_error += element_error;
4400  error_estimates(ielem) += element_error;
4401  counters[ielem]++;
4402  }
4403 
4404  total_error += patch_error;
4405  }
4406 
4407  // 4. Calibrate the final error estimates. Note that the l2 norm of
4408  // error_estimates vector converges to total_error.
4409  // The error estimates have been calibrated so that high order
4410  // benchmark problems with tensor product elements are asymptotically
4411  // exact.
4412  for (int ielem = 0; ielem < nfe; ielem++)
4413  {
4414  if (counters[ielem] == 0)
4415  {
4416  error_estimates(ielem) = infinity();
4417  }
4418  else
4419  {
4420  error_estimates(ielem) /= counters[ielem]/2.0;
4421  error_estimates(ielem) = sqrt(error_estimates(ielem));
4422  }
4423  }
4424  return std::sqrt(total_error/dim);
4425 }
4426 
4427 double ComputeElementLpDistance(double p, int i,
4428  GridFunction& gf1, GridFunction& gf2)
4429 {
4430  double norm = 0.0;
4431 
4432  FiniteElementSpace *fes1 = gf1.FESpace();
4433  FiniteElementSpace *fes2 = gf2.FESpace();
4434 
4435  const FiniteElement* fe1 = fes1->GetFE(i);
4436  const FiniteElement* fe2 = fes2->GetFE(i);
4437 
4438  const IntegrationRule *ir;
4439  int intorder = 2*std::max(fe1->GetOrder(),fe2->GetOrder()) + 1; // <-------
4440  ir = &(IntRules.Get(fe1->GetGeomType(), intorder));
4441  int nip = ir->GetNPoints();
4442  Vector val1, val2;
4443 
4444 
4446  for (int j = 0; j < nip; j++)
4447  {
4448  const IntegrationPoint &ip = ir->IntPoint(j);
4449  T->SetIntPoint(&ip);
4450 
4451  gf1.GetVectorValue(i, ip, val1);
4452  gf2.GetVectorValue(i, ip, val2);
4453 
4454  val1 -= val2;
4455  double errj = val1.Norml2();
4456  if (p < infinity())
4457  {
4458  errj = pow(errj, p);
4459  norm += ip.weight * T->Weight() * errj;
4460  }
4461  else
4462  {
4463  norm = std::max(norm, errj);
4464  }
4465  }
4466 
4467  if (p < infinity())
4468  {
4469  // Negative quadrature weights may cause the norm to be negative
4470  if (norm < 0.)
4471  {
4472  norm = -pow(-norm, 1./p);
4473  }
4474  else
4475  {
4476  norm = pow(norm, 1./p);
4477  }
4478  }
4479 
4480  return norm;
4481 }
4482 
4483 
4485  const IntegrationPoint &ip)
4486 {
4487  ElementTransformation *T_in =
4488  mesh_in->GetElementTransformation(T.ElementNo / n);
4489  T_in->SetIntPoint(&ip);
4490  return sol_in.Eval(*T_in, ip);
4491 }
4492 
4493 
4495  GridFunction *sol, const int ny)
4496 {
4497  GridFunction *sol2d;
4498 
4499  FiniteElementCollection *solfec2d;
4500  const char *name = sol->FESpace()->FEColl()->Name();
4501  string cname = name;
4502  if (cname == "Linear")
4503  {
4504  solfec2d = new LinearFECollection;
4505  }
4506  else if (cname == "Quadratic")
4507  {
4508  solfec2d = new QuadraticFECollection;
4509  }
4510  else if (cname == "Cubic")
4511  {
4512  solfec2d = new CubicFECollection;
4513  }
4514  else if (!strncmp(name, "H1_", 3))
4515  {
4516  solfec2d = new H1_FECollection(atoi(name + 7), 2);
4517  }
4518  else if (!strncmp(name, "H1Pos_", 6))
4519  {
4520  // use regular (nodal) H1_FECollection
4521  solfec2d = new H1_FECollection(atoi(name + 10), 2);
4522  }
4523  else if (!strncmp(name, "L2_T", 4))
4524  {
4525  solfec2d = new L2_FECollection(atoi(name + 10), 2);
4526  }
4527  else if (!strncmp(name, "L2_", 3))
4528  {
4529  solfec2d = new L2_FECollection(atoi(name + 7), 2);
4530  }
4531  else
4532  {
4533  mfem::err << "Extrude1DGridFunction : unknown FE collection : "
4534  << cname << endl;
4535  return NULL;
4536  }
4537  FiniteElementSpace *solfes2d;
4538  // assuming sol is scalar
4539  solfes2d = new FiniteElementSpace(mesh2d, solfec2d);
4540  sol2d = new GridFunction(solfes2d);
4541  sol2d->MakeOwner(solfec2d);
4542  {
4543  GridFunctionCoefficient csol(sol);
4544  ExtrudeCoefficient c2d(mesh, csol, ny);
4545  sol2d->ProjectCoefficient(c2d);
4546  }
4547  return sol2d;
4548 }
4549 
4550 }
void SaveSTLTri(std::ostream &out, double p1[], double p2[], double p3[])
Definition: gridfunc.cpp:3793
Abstract class for all finite elements.
Definition: fe_base.hpp:232
virtual double ComputeL2Error(Coefficient *exsol[], const IntegrationRule *irs[]=NULL, const Array< int > *elems=NULL) const
Definition: gridfunc.cpp:2763
void GetEdgeInteriorDofs(int i, Array< int > &dofs) const
Definition: fespace.cpp:3066
virtual void Mult(const Vector &x, Vector &y) const
Matrix vector multiplication.
Definition: sparsemat.cpp:733
virtual double ComputeGradError(VectorCoefficient *exgrad, const IntegrationRule *irs[]=NULL) const
Returns ||grad u_ex - grad u_h||_L2 for H1 or L2 elements.
Definition: gridfunc.cpp:2897
void SetSubVector(const Array< int > &dofs, const double value)
Set the entries listed in dofs to the given value.
Definition: vector.cpp:574
bool IsLegacyLoaded() const
I/O: Return true if the mesh was loaded from the legacy v1.1 format.
Definition: ncmesh.hpp:384
int GetNPoints() const
Returns the number of the points in the integration rule.
Definition: intrules.hpp:247
void Save(const GridFunction &grid_function, const std::string &variable_name, const data_type type)
Class for an integration rule - an Array of IntegrationPoint.
Definition: intrules.hpp:90
void NewDataAndSize(double *d, int s)
Set the Vector data and size, deleting the old data, if owned.
Definition: vector.hpp:162
Class for grid function - Vector with associated FE space.
Definition: gridfunc.hpp:30
Memory< double > data
Definition: vector.hpp:64
Class used for extruding scalar GridFunctions.
Definition: gridfunc.hpp:855
virtual void GetVectorValue(int i, const IntegrationPoint &ip, Vector &val) const
Definition: gridfunc.cpp:479
void SumFluxAndCount(BilinearFormIntegrator &blfi, GridFunction &flux, Array< int > &counts, bool wcoef, int subdomain)
Definition: gridfunc.cpp:252
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
Definition: intrules.cpp:923
virtual void ComputeElementFlux(const FiniteElement &el, ElementTransformation &Trans, Vector &u, const FiniteElement &fluxelem, Vector &flux, bool with_coef=true, const IntegrationRule *ir=NULL)
Virtual method required for Zienkiewicz-Zhu type error estimators.
Definition: bilininteg.hpp:223
void MergeGridFunctions(GridFunction *gf_array[], int num_pieces, GridFunction &merged)
Definition: nurbs.cpp:2115
OutStream err(std::cerr)
Global stream used by the library for standard error output. Initially it uses the same std::streambu...
Definition: globals.hpp:71
Base class for vector Coefficients that optionally depend on time and space.
void ProjectDeltaCoefficient(DeltaCoefficient &delta_coeff, double &integral)
Definition: gridfunc.cpp:2333
void PrintSolution(const GridFunction &sol, std::ostream &out) const
Definition: nurbs.cpp:3051
Geometry::Type GetElementBaseGeometry(int i) const
Definition: mesh.hpp:1108
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 ...
bool Nonconforming() const
Definition: fespace.hpp:448
int Dimension() const
Definition: mesh.hpp:1047
virtual int GetContType() const =0
int GetNumFaces() const
Return the number of faces (3D), edges (2D) or vertices (1D).
Definition: mesh.cpp:5389
void SetSize(int s)
Resize the vector to size s.
Definition: vector.hpp:512
void RestrictConforming()
Definition: gridfunc.cpp:1979
GridFunction * Extrude1DGridFunction(Mesh *mesh, Mesh *mesh2d, GridFunction *sol, const int ny)
Extrude a scalar 1D GridFunction, after extruding the mesh with Extrude1D.
Definition: gridfunc.cpp:4494
void GetVectorGradient(ElementTransformation &tr, DenseMatrix &grad) const
Compute the vector gradient with respect to the physical element variable.
Definition: gridfunc.cpp:1739
void LegacyToNewVertexOrdering(Array< int > &order) const
I/O: Return a map from old (v1.1) vertex indices to new vertex indices.
Definition: ncmesh.cpp:6177
double Scale()
Return the scale factor times the optional time dependent function. Returns with when not set by th...
void GetVertexVDofs(int i, Array< int > &vdofs) const
Definition: fespace.cpp:324
int CurlDim() const
Definition: gridfunc.cpp:347
virtual void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
Definition: vector.hpp:117
void ProjectDiscCoefficient(VectorCoefficient &coeff, Array< int > &dof_attr)
Definition: gridfunc.cpp:2570
void GetFaceVDofs(int i, Array< int > &vdofs) const
Returns indexes of degrees of freedom for i&#39;th face element (2D and 3D).
Definition: fespace.cpp:312
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
Definition: table.cpp:475
void Print(std::ostream &out=mfem::out, int width=8) const
Prints vector to stream out.
Definition: vector.cpp:725
virtual void ComputeElementLpErrors(const double p, Coefficient &exsol, Vector &error, Coefficient *weight=NULL, const IntegrationRule *irs[]=NULL) const
Definition: gridfunc.cpp:3410
bool FaceIsInterior(int FaceNo) const
Return true if the given face is interior.
Definition: mesh.hpp:1341
void GetGradient(ElementTransformation &tr, Vector &grad) const
Gradient of a scalar function at a quadrature point.
Definition: gridfunc.cpp:1646
int GetCurlDim() const
Returns the dimension of the curl for vector-valued finite elements.
Definition: fe_base.hpp:316
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
Definition: operator.hpp:72
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const =0
virtual DofTransformation * GetBdrElementDofs(int bel, Array< int > &dofs) const
Returns indices of degrees of freedom for boundary element &#39;bel&#39;.
Definition: fespace.cpp:2814
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
virtual void CalcPhysLaplacian(ElementTransformation &Trans, Vector &Laplacian) const
Evaluate the Laplacian of all shape functions of a scalar finite element in reference space at the gi...
Definition: fe_base.cpp:202
bool Nonconforming() const
Definition: mesh.hpp:1729
int Size() const
Returns the size of the vector.
Definition: vector.hpp:199
Coefficient defined by a GridFunction. This coefficient is mesh dependent.
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
Definition: array.cpp:68
void GetElementAverages(GridFunction &avgs) const
Definition: gridfunc.cpp:1801
Piecewise-(bi/tri)linear continuous finite elements.
Definition: fe_coll.hpp:695
Data type dense matrix using column-major storage.
Definition: densemat.hpp:23
virtual double * HostWrite()
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), false).
Definition: vector.hpp:460
Delta function coefficient optionally multiplied by a weight coefficient and a scaled time dependent ...
const NURBSExtension * GetNURBSext() const
Definition: fespace.hpp:443
double * Data() const
Returns the matrix data array.
Definition: densemat.hpp:111
int GetNDofs() const
Returns number of degrees of freedom.
Definition: fespace.hpp:584
IntegrationPointTransformation Loc2
Definition: eltrans.hpp:524
double Tol()
Return the tolerance used to identify the mesh vertices.
int GetNEdges() const
Return the number of edges.
Definition: mesh.hpp:942
const DenseMatrix & InverseJacobian()
Return the inverse of the Jacobian matrix of the transformation at the currently set IntegrationPoint...
Definition: eltrans.hpp:145
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
void AccumulateAndCountBdrTangentValues(VectorCoefficient &vcoeff, Array< int > &bdr_attr, Array< int > &values_counter)
Definition: gridfunc.cpp:2256
Abstract parallel finite element space.
Definition: pfespace.hpp:28
void LoadSolution(std::istream &input, GridFunction &sol) const
Definition: nurbs.cpp:3014
void MakeOwner(FiniteElementCollection *fec_)
Make the GridFunction the owner of fec and fes.
Definition: gridfunc.hpp:122
FiniteElementCollection * Load(Mesh *m, std::istream &input)
Read a FiniteElementSpace from a stream. The returned FiniteElementCollection is owned by the caller...
Definition: fespace.cpp:3515
STL namespace.
double Eval(double h, int p) const
Definition: gridfunc.hpp:776
virtual void Transform(const IntegrationPoint &, Vector &)
Transform integration point from reference coordinates to physical coordinates and store them in the ...
Definition: eltrans.cpp:492
void GetSubVector(const Array< int > &dofs, Vector &elemvect) const
Extract entries listed in dofs to the output Vector elemvect.
Definition: vector.cpp:548
const IntegrationPoint & GetIntPoint()
Get a const reference to the currently set integration point. This will return NULL if no integration...
Definition: eltrans.hpp:98
static void CalcLegendre(const int p, const double x, double *u)
Definition: fe_base.cpp:2073
void ComputeMeans(AvgType type, Array< int > &zones_per_vdof)
Definition: gridfunc.cpp:2308
virtual double ComputeFluxEnergy(const FiniteElement &fluxelem, ElementTransformation &Trans, Vector &flux, Vector *d_energy=NULL)
Virtual method required for Zienkiewicz-Zhu type error estimators.
Definition: bilininteg.hpp:249
ElementTransformation * Elem2
Definition: eltrans.hpp:522
void CalcOrtho(const DenseMatrix &J, Vector &n)
Definition: densemat.cpp:2693
void GetHessians(int i, const IntegrationRule &ir, DenseMatrix &hess, int vdim=1) const
Definition: gridfunc.cpp:611
virtual FaceElementTransformations * GetFaceElementTransformations(int FaceNo, int mask=31)
Definition: mesh.cpp:961
const IntegrationRule * GetVertices(int GeomType)
Return an IntegrationRule consisting of all vertices of the given Geometry::Type, GeomType...
Definition: geom.cpp:265
Geometry Geometries
Definition: fe.cpp:49
virtual double GetValue(int i, const IntegrationPoint &ip, int vdim=1) const
Definition: gridfunc.cpp:452
void skip_comment_lines(std::istream &is, const char comment_char)
Check if the stream starts with comment_char. If so skip it.
Definition: text.hpp:31
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i&#39;th element in t...
Definition: fespace.cpp:2783
int GetNumGeometries(int dim) const
Return the number of geometries of the given dimension present in the mesh.
Definition: mesh.cpp:5921
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
Definition: intrules.hpp:379
void GetEdgeTransformation(int i, IsoparametricTransformation *EdTr)
Definition: mesh.cpp:574
void GetFaceElements(int Face, int *Elem1, int *Elem2) const
Definition: mesh.cpp:1394
const FiniteElement * GetFaceElement(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i&#39;th face in the ...
Definition: fespace.cpp:3135
void ImposeBounds(int i, const Vector &weights, const Vector &lo_, const Vector &hi_)
Definition: gridfunc.cpp:1904
Vector & operator=(const double *v)
Copy Size() entries from v.
Definition: vector.cpp:124
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:125
int GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
Definition: mesh.hpp:933
Geometry::Type GetGeomType() const
Returns the Geometry::Type of the reference element.
Definition: fe_base.hpp:319
void Load(std::istream **in, int np, int *dim)
Reads a vector from multiple files.
Definition: vector.cpp:57
Piecewise-(bi)cubic continuous finite elements.
Definition: fe_coll.hpp:775
int GetNEDofs() const
Number of all scalar edge-interior dofs.
Definition: fespace.hpp:606
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip)
Evaluate the coefficient in the element described by T at the point ip.
Definition: gridfunc.cpp:4484
virtual double ComputeMaxError(Coefficient &exsol, const IntegrationRule *irs[]=NULL) const
Definition: gridfunc.hpp:570
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
Definition: intrules.hpp:250
void GetDerivative(int comp, int der_comp, GridFunction &der)
Compute a certain derivative of a function&#39;s component. Derivatives of the function are computed at t...
Definition: gridfunc.cpp:1433
void GetTrueDofs(Vector &tv) const
Extract the true-dofs from the GridFunction.
Definition: gridfunc.cpp:367
void GetBdrElementFace(int i, int *f, int *o) const
Return the index and the orientation of the face of bdr element i. (3D)
Definition: mesh.cpp:6212
void ProjectBdrCoefficientNormal(VectorCoefficient &vcoeff, Array< int > &bdr_attr)
Definition: gridfunc.cpp:2675
void SetTrueVector()
Shortcut for calling GetTrueDofs() with GetTrueVector() as argument.
Definition: gridfunc.hpp:144
void GetCurl(ElementTransformation &tr, Vector &curl) const
Definition: gridfunc.cpp:1550
GeometryRefiner GlobGeometryRefiner
Definition: geom.cpp:1773
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
Definition: solvers.cpp:71
void GetValues(int i, const IntegrationRule &ir, Vector &vals, int vdim=1) const
Definition: gridfunc.cpp:524
double f(const Vector &xvec)
Definition: lor_mms.hpp:32
double GetElementSize(ElementTransformation *T, int type=0)
Definition: mesh.cpp:76
void Norm2(double *v) const
Take the 2-norm of the columns of A and store in v.
Definition: densemat.cpp:834
Data type sparse matrix.
Definition: sparsemat.hpp:50
const double * Center()
void Swap(Vector &other)
Swap the contents of two Vectors.
Definition: vector.hpp:614
Geometry::Type GetGeometryType() const
Return the Geometry::Type of the reference element.
Definition: eltrans.hpp:162
const FiniteElementCollection * FEColl() const
Definition: fespace.hpp:601
IntegrationPointTransformation Loc1
Definition: eltrans.hpp:524
ElementTransformation * GetBdrElementTransformation(int i) const
Returns ElementTransformation for the i-th boundary element.
Definition: fespace.hpp:656
void MultTranspose(const double *x, double *y) const
Multiply a vector with the transpose matrix.
Definition: densemat.cpp:215
Coefficient * Weight()
See SetWeight() for description of the weight Coefficient.
double b
Definition: lissajous.cpp:42
void GetFaceTransformation(int i, IsoparametricTransformation *FTr)
Definition: mesh.cpp:497
virtual const SparseMatrix * GetRestrictionMatrix() const
The returned SparseMatrix is owned by the FiniteElementSpace.
Definition: fespace.hpp:495
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
virtual void ProjectDelta(int vertex, Vector &dofs) const
Project a delta function centered on the given vertex in the local finite dimensional space represent...
Definition: fe_base.cpp:149
void MakeTRef(FiniteElementSpace *f, double *tv)
Associate a new FiniteElementSpace and new true-dof data with the GridFunction.
Definition: gridfunc.cpp:222
void SetMaxIter(int max_it)
Definition: solvers.hpp:201
void GetEdgeVertices(int i, Array< int > &vert) const
Returns the indices of the vertices of edge i.
Definition: mesh.cpp:6029
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 BoundingBox(const Array< int > &patch, FiniteElementSpace *ufes, int order, Vector &xmin, Vector &xmax, double &angle, Vector &midpoint, int iface)
Defines the bounding box for the face patches used by NewZZErorrEstimator.
Definition: gridfunc.cpp:4157
virtual double ComputeHDivError(VectorCoefficient *exsol, Coefficient *exdiv, const IntegrationRule *irs[]=NULL) const
Returns the error measured in H(div)-norm for RT elements.
Definition: gridfunc.cpp:3163
void SetLinearConstraint(const Vector &w_, double a_)
Definition: solvers.cpp:2365
double Sum() const
Return the sum of the vector entries.
Definition: vector.cpp:912
virtual double ComputeCurlError(VectorCoefficient *excurl, const IntegrationRule *irs[]=NULL) const
Returns ||curl u_ex - curl u_h||_L2 for ND elements.
Definition: gridfunc.cpp:2937
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:70
const double * GetVertex(int i) const
Return pointer to vertex i&#39;s coordinates.
Definition: mesh.hpp:1053
virtual const char * Name() const
Definition: fe_coll.hpp:73
double LSZZErrorEstimator(BilinearFormIntegrator &blfi, GridFunction &u, Vector &error_estimates, bool subdomain_reconstruction, bool with_coeff, double tichonov_coeff)
A ‘‘true’’ ZZ error estimator that uses face-based patches for flux reconstruction.
Definition: gridfunc.cpp:4224
void rotate(double *x)
Definition: snake.cpp:316
long GetSequence() const
Definition: fespace.hpp:922
void GetElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of element i.
Definition: mesh.hpp:1148
void AccumulateAndCountDerivativeValues(int comp, int der_comp, GridFunction &der, Array< int > &zones_per_dof)
Used for the serial and parallel implementations of the GetDerivative() method; see its documentation...
Definition: gridfunc.cpp:1380
const SparseMatrix * GetConformingProlongation() const
The returned SparseMatrix is owned by the FiniteElementSpace.
Definition: fespace.cpp:1232
void AddMultVVt(const Vector &v, DenseMatrix &VVt)
VVt += v v^t.
Definition: densemat.cpp:3187
double Weight()
Return the weight of the Jacobian matrix of the transformation at the currently set IntegrationPoint...
Definition: eltrans.hpp:131
void AccumulateAndCountZones(Coefficient &coeff, AvgType type, Array< int > &zones_per_vdof)
Accumulates (depending on type) the values of coeff at all shared vdofs and counts in how many zones ...
Definition: gridfunc.cpp:2018
virtual void MakeRef(FiniteElementSpace *f, double *v)
Make the GridFunction reference external data on a new FiniteElementSpace.
Definition: gridfunc.cpp:204
IntegrationRule RefPts
Definition: geom.hpp:314
RefinedGeometry * Refine(Geometry::Type Geom, int Times, int ETimes=1)
Definition: geom.cpp:1099
double GetDivergence(ElementTransformation &tr) const
Definition: gridfunc.cpp:1460
int GetVDim()
Returns dimension of the vector.
A class for non-conforming AMR. The class is not used directly by the user, rather it is an extension...
Definition: ncmesh.hpp:121
FaceElementTransformations * GetBdrFaceTransformations(int BdrElemNo)
Definition: mesh.cpp:1095
FiniteElementSpace * FESpace()
Definition: gridfunc.hpp:683
GridFunction & operator=(const GridFunction &rhs)
Copy assignment. Only the data of the base class Vector is copied.
Definition: gridfunc.hpp:116
void Mult(const double *x, double *y) const
Matrix vector multiplication.
Definition: densemat.cpp:173
int GetNE() const
Returns number of elements in the mesh.
Definition: fespace.hpp:614
virtual double ComputeW11Error(Coefficient *exsol, VectorCoefficient *exgrad, int norm_type, const Array< int > *elems=NULL, const IntegrationRule *irs[]=NULL) const
Definition: gridfunc.cpp:3237
virtual void GetBoundaryClosure(const Array< int > &bdr_attr_is_ess, Array< int > &bdr_vertices, Array< int > &bdr_edges)
Definition: ncmesh.cpp:5180
void AddElementVector(const Array< int > &dofs, const Vector &elemvect)
Add elements of the elemvect Vector to the entries listed in dofs. Negative dof values cause the -dof...
Definition: vector.cpp:640
void GetNodalValues(int i, Array< double > &nval, int vdim=1) const
Returns the values in the vertices of i&#39;th element for dimension vdim.
Definition: gridfunc.cpp:396
double * GetData() const
Return a pointer to the beginning of the Vector data.
Definition: vector.hpp:208
void CalcInverse(const DenseMatrix &a, DenseMatrix &inva)
Definition: densemat.cpp:2587
int GetVDim() const
Returns vector dimension.
Definition: fespace.hpp:581
A general vector function coefficient.
DofTransformation * GetElementVDofs(int i, Array< int > &vdofs) const
Returns indexes of degrees of freedom in array dofs for i&#39;th element.
Definition: fespace.cpp:281
Geometry::Type GetElementGeometry(int i) const
Definition: mesh.hpp:1094
virtual void GetElementDofValues(int el, Vector &dof_vals) const
Definition: gridfunc.cpp:1841
int GetNF() const
Returns number of faces (i.e. co-dimension 1 entities) in the mesh.
Definition: fespace.hpp:620
bool IsIdentityProlongation(const Operator *P)
Definition: operator.hpp:720
virtual int GetTrueVSize() const
Return the number of vector true (conforming) dofs.
Definition: fespace.hpp:590
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const =0
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i]...
Mesh * GetMesh() const
Returns the mesh.
Definition: fespace.hpp:441
virtual void InvTransformPrimal(double *v) const =0
Abstract base class BilinearFormIntegrator.
Definition: bilininteg.hpp:35
void SetAbsTol(double atol)
Definition: solvers.hpp:200
void SetRelTol(double rtol)
Definition: solvers.hpp:199
int GetDim() const
Returns the reference space dimension for the finite element.
Definition: fe_base.hpp:310
ComplexDenseMatrix * MultAtB(const ComplexDenseMatrix &A, const ComplexDenseMatrix &B)
Multiply the complex conjugate transpose of a matrix A with a matrix B. A^H*B.
double Distance(const double *x, const double *y, const int n)
Definition: vector.hpp:643
virtual double ComputeElementGradError(int ielem, VectorCoefficient *exgrad, const IntegrationRule *irs[]=NULL) const
Returns ||grad u_ex - grad u_h||_L2 in element ielem for H1 or L2 elements.
Definition: gridfunc.cpp:2859
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition: fespace.hpp:96
virtual double ComputeDGFaceJumpError(Coefficient *exsol, Coefficient *ell_coeff, class JumpScaling jump_scaling, const IntegrationRule *irs[]=NULL) const
Definition: gridfunc.cpp:3014
Base class Coefficients that optionally depend on space and time. These are used by the BilinearFormI...
Definition: coefficient.hpp:41
FiniteElementSpace * fes
FE space on which the grid function lives. Owned if fec is not NULL.
Definition: gridfunc.hpp:34
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
Definition: fe_coll.hpp:26
virtual double ComputeH1Error(Coefficient *exsol, VectorCoefficient *exgrad, Coefficient *ell_coef, double Nu, int norm_type) const
Definition: gridfunc.cpp:3137
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Definition: globals.hpp:66
void ProjectGridFunction(const GridFunction &src)
Project the src GridFunction to this GridFunction, both of which must be on the same mesh...
Definition: gridfunc.cpp:1852
virtual double ComputeDivError(Coefficient *exdiv, const IntegrationRule *irs[]=NULL) const
Returns ||div u_ex - div u_h||_L2 for RT elements.
Definition: gridfunc.cpp:2978
double Min() const
Returns the minimal element of the vector.
Definition: vector.cpp:1194
virtual void GetEssentialVDofs(const Array< int > &bdr_attr_is_ess, Array< int > &ess_vdofs, int component=-1) const
Mark degrees of freedom associated with boundary elements with the specified boundary attributes (mar...
Definition: fespace.cpp:495
virtual void TransformPrimal(double *v) const =0
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition: array.hpp:684
int GetElementForDof(int i) const
Return the index of the first element that contains dof i.
Definition: fespace.hpp:773
void GetVectorFieldNodalValues(Vector &val, int comp) const
Definition: gridfunc.cpp:1309
void Transform(const IntegrationPoint &, IntegrationPoint &)
Definition: eltrans.cpp:546
int GetEdgeDofs(int edge, Array< int > &dofs, int variant=0) const
Returns the indices of the degrees of freedom for the specified edge, including the DOFs for the vert...
Definition: fespace.cpp:2987
int NumBdr(int GeomType)
Return the number of boundary "faces" of a given Geometry::Type.
Definition: geom.hpp:126
void GetColumnReference(int c, Vector &col)
Definition: densemat.hpp:312
Poly_1D poly1d
Definition: fe.cpp:28
FiniteElementCollection * fec
Used when the grid function is read from a file. It can also be set explicitly, see MakeOwner()...
Definition: gridfunc.hpp:40
int GetDof() const
Returns the number of degrees of freedom in the finite element.
Definition: fe_base.hpp:322
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Definition: operator.hpp:66
void GetElementVertices(int i, Array< int > &vertices) const
Returns the vertices of element i.
Definition: fespace.hpp:639
void GetVectorGradientHat(ElementTransformation &T, DenseMatrix &gh) const
Compute the vector gradient with respect to the reference element variable.
Definition: gridfunc.cpp:1444
void TensorProductLegendre(int dim, int order, const Vector &x_in, const Vector &xmax, const Vector &xmin, Vector &poly, double angle, const Vector *midpoint)
Defines the global tensor product polynomial space used by NewZZErorrEstimator.
Definition: gridfunc.cpp:4065
virtual DofTransformation * GetElementDofs(int elem, Array< int > &dofs) const
Returns indices of degrees of freedom of element &#39;elem&#39;.
Definition: fespace.cpp:2680
double Max() const
Returns the maximal element of the vector.
Definition: vector.cpp:894
int GetNVDofs() const
Number of all scalar vertex dofs.
Definition: fespace.hpp:604
double Norml1() const
Returns the l_1 norm of the vector.
Definition: vector.cpp:833
virtual void Update()
Transform by the Space UpdateMatrix (e.g., on Mesh change).
Definition: gridfunc.cpp:165
double ComputeElementLpDistance(double p, int i, GridFunction &gf1, GridFunction &gf2)
Compute the Lp distance between two grid functions on the given element.
Definition: gridfunc.cpp:4427
int SpaceDimension() const
Definition: mesh.hpp:1048
int GetAttribute(int i) const
Definition: fespace.hpp:659
static FiniteElementCollection * New(const char *name)
Factory method: return a newly allocated FiniteElementCollection according to the given name...
Definition: fe_coll.cpp:116
virtual double ComputeHCurlError(VectorCoefficient *exsol, VectorCoefficient *excurl, const IntegrationRule *irs[]=NULL) const
Returns the error measured in H(curl)-norm for ND elements.
Definition: gridfunc.cpp:3172
int GetNE() const
Returns number of elements.
Definition: mesh.hpp:936
virtual double ComputeLpError(const double p, Coefficient &exsol, Coefficient *weight=NULL, const IntegrationRule *irs[]=NULL, const Array< int > *elems=NULL) const
Definition: gridfunc.cpp:3343
double ZZErrorEstimator(BilinearFormIntegrator &blfi, GridFunction &u, GridFunction &flux, Vector &error_estimates, Array< int > *aniso_flags, int with_subdomains, bool with_coeff)
Definition: gridfunc.cpp:3975
double a
Definition: lissajous.cpp:41
NURBSExtension * NURBSext
Optional NURBS mesh extension.
Definition: mesh.hpp:277
virtual const Operator * GetProlongationMatrix() const
The returned Operator is owned by the FiniteElementSpace.
Definition: fespace.hpp:479
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:181
Vector & Add(const double a, const Vector &Va)
(*this) += a * Va
Definition: vector.cpp:253
Class for integration point with weight.
Definition: intrules.hpp:25
int VectorDim() const
Definition: gridfunc.cpp:324
int GetElementOrder(int i) const
Returns the order of the i&#39;th finite element.
Definition: fespace.cpp:178
A standard isoparametric element transformation.
Definition: eltrans.hpp:361
virtual void Mult(const Vector &xt, Vector &x) const
Definition: solvers.cpp:2380
void SaveSTL(std::ostream &out, int TimesToRefine=1)
Write the GridFunction in STL format. Note that the mesh dimension must be 2 and that quad elements w...
Definition: gridfunc.cpp:3813
void GetElementTransformation(int i, IsoparametricTransformation *ElTr)
Definition: mesh.cpp:348
int GetVDim() const
Returns the vector dimension for vector-valued finite elements.
Definition: fe_base.hpp:313
int GetBdrAttribute(int i) const
Definition: fespace.hpp:661
Ordering::Type GetOrdering() const
Return the ordering method.
Definition: fespace.hpp:599
DofTransformation * GetBdrElementVDofs(int i, Array< int > &vdofs) const
Returns indexes of degrees of freedom for i&#39;th boundary element.
Definition: fespace.cpp:297
void Save(std::ostream &out) const
Save finite element space to output stream out.
Definition: fespace.cpp:3446
virtual void AssembleElementMatrix2(const FiniteElement &trial_fe, const FiniteElement &test_fe, ElementTransformation &Trans, DenseMatrix &elmat)
void GetVectorFieldValues(int i, const IntegrationRule &ir, DenseMatrix &vals, DenseMatrix &tr, int comp=0) const
Definition: gridfunc.cpp:1244
int dim
Definition: ex24.cpp:53
void NewMemoryAndSize(const Memory< double > &mem, int s, bool own_mem)
Reset the Vector to use the given external Memory mem and size s.
Definition: vector.hpp:561
void GetGradients(ElementTransformation &tr, const IntegrationRule &ir, DenseMatrix &grad) const
Extension of GetGradient(...) for a collection of IntegrationPoints.
Definition: gridfunc.cpp:1715
ElementTransformation & GetElement1Transformation()
Definition: eltrans.cpp:591
void GetEdgeVDofs(int i, Array< int > &vdofs) const
Returns indexes of degrees of freedom for i&#39;th edge.
Definition: fespace.cpp:318
int GetNBE() const
Returns number of boundary elements in the mesh.
Definition: fespace.hpp:623
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:39
const Operator * GetUpdateOperator()
Get the GridFunction update operator.
Definition: fespace.hpp:897
virtual void ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff, Array< int > &bdr_attr)
Project the tangential components of the given VectorCoefficient on the boundary. Only boundary attri...
Definition: gridfunc.cpp:2746
void LegacyNCReorder()
Loading helper.
Definition: gridfunc.cpp:3913
int GetFaceValues(int i, int side, const IntegrationRule &ir, Vector &vals, DenseMatrix &tr, int vdim=1) const
Definition: gridfunc.cpp:667
ElementTransformation * Elem1
Definition: eltrans.hpp:522
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
Definition: fespace.hpp:587
int GetMapType() const
Returns the FiniteElement::MapType of the element describing how reference functions are mapped to ph...
Definition: fe_base.hpp:348
double infinity()
Define a shortcut for std::numeric_limits<double>::infinity()
Definition: vector.hpp:46
int GetFaceVectorValues(int i, int side, const IntegrationRule &ir, DenseMatrix &vals, DenseMatrix &tr) const
Definition: gridfunc.cpp:1117
virtual void ProjectCoefficient(Coefficient &coeff)
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
Definition: gridfunc.cpp:2396
double Norml2() const
Returns the l2 norm of the vector.
Definition: vector.cpp:804
Piecewise-(bi)quadratic continuous finite elements.
Definition: fe_coll.hpp:723
virtual void SetSpace(FiniteElementSpace *f)
Associate a new FiniteElementSpace with the GridFunction.
Definition: gridfunc.cpp:196
void ReorderByNodes()
For a vector grid function, makes sure that the ordering is byNODES.
Definition: gridfunc.cpp:1282
std::ostream & operator<<(std::ostream &os, SparseMatrix const &mat)
Definition: sparsemat.hpp:711
NCMesh * ncmesh
Optional nonconforming mesh extension.
Definition: mesh.hpp:278
void GetVectorValues(int i, const IntegrationRule &ir, DenseMatrix &vals, DenseMatrix &tr) const
Definition: gridfunc.cpp:717
void GetLaplacians(int i, const IntegrationRule &ir, Vector &laps, int vdim=1) const
Definition: gridfunc.cpp:572
int Size() const
Return the logical size of the array.
Definition: array.hpp:141
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip)=0
Evaluate the coefficient in the element described by T at the point ip.
void filter_dos(std::string &line)
Check for, and remove, a trailing &#39;\r&#39; from and std::string.
Definition: text.hpp:45
virtual bool UseDevice() const
Return the device flag of the Memory object used by the Vector.
Definition: vector.hpp:120
int DofToVDof(int dof, int vd, int ndofs=-1) const
Definition: fespace.cpp:251
int GetNV() const
Returns number of vertices in the mesh.
Definition: fespace.hpp:611
Vector data type.
Definition: vector.hpp:60
virtual void Transform(const IntegrationPoint &, Vector &)=0
Transform integration point from reference coordinates to physical coordinates and store them in the ...
void be_to_bfe(Geometry::Type geom, int o, const IntegrationPoint &ip, IntegrationPoint &fip)
Definition: gridfunc.cpp:726
void MakeRef(Vector &base, int offset, int size)
Reset the Vector to be a reference to a sub-vector of base.
Definition: vector.hpp:576
virtual void ComputeFlux(BilinearFormIntegrator &blfi, GridFunction &flux, bool wcoef=true, int subdomain=-1)
Definition: gridfunc.cpp:309
int GetRangeType() const
Returns the FiniteElement::RangeType of the element, one of {SCALAR, VECTOR}.
Definition: fe_base.hpp:339
Arbitrary order H1-conforming (continuous) finite elements.
Definition: fe_coll.hpp:252
void pts(int iphi, int t, double x[])
RefCoord s[3]
Field is continuous across element interfaces.
Definition: fe_coll.hpp:45
double u(const Vector &xvec)
Definition: lor_mms.hpp:24
const FiniteElement * GetEdgeElement(int i, int variant=0) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i&#39;th edge in the ...
Definition: fespace.cpp:3165
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
Definition: densemat.hpp:105
virtual void CalcPhysHessian(ElementTransformation &Trans, DenseMatrix &Hessian) const
Evaluate the Hessian of all shape functions of a scalar finite element in reference space at the give...
Definition: fe_base.cpp:287
virtual void Save(std::ostream &out) const
Save the GridFunction to an output stream.
Definition: gridfunc.cpp:3673
Abstract operator.
Definition: operator.hpp:24
void SetBounds(const Vector &lo_, const Vector &hi_)
Definition: solvers.cpp:2359
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
Definition: fe_base.hpp:388
virtual void SetFromTrueDofs(const Vector &tv)
Set the GridFunction from the given true-dof vector.
Definition: gridfunc.cpp:382
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...
virtual int GetFaceDofs(int face, Array< int > &dofs, int variant=0) const
Returns the indices of the degrees of freedom for the specified face, including the DOFs for the edge...
Definition: fespace.cpp:2906
void BuildDofToArrays()
Initialize internal data that enables the use of the methods GetElementForDof() and GetLocalDofForDof...
Definition: fespace.cpp:460
const FiniteElement * GetBE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i&#39;th boundary fac...
Definition: fespace.cpp:3102
void Set1w(const double x1, const double w)
Definition: intrules.hpp:84
int GetNFDofs() const
Number of all scalar face-interior dofs.
Definition: fespace.hpp:608
void GetValuesFrom(const GridFunction &orig_func)
Definition: gridfunc.cpp:1160
int GetLocalDofForDof(int i) const
Return the local dof index in the first element that contains dof i.
Definition: fespace.hpp:777
void DofsToVDofs(Array< int > &dofs, int ndofs=-1) const
Definition: fespace.cpp:215
Array< int > RefGeoms
Definition: geom.hpp:315
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...
Definition: fe_base.hpp:326
virtual double * HostReadWrite()
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), false).
Definition: vector.hpp:468
void GetBdrValuesFrom(const GridFunction &orig_func)
Definition: gridfunc.cpp:1206
static void AdjustVDofs(Array< int > &vdofs)
Definition: fespace.cpp:267
Array< int > attributes
A list of all unique element attributes used by the Mesh.
Definition: mesh.hpp:273
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:51
void AccumulateAndCountBdrValues(Coefficient *coeff[], VectorCoefficient *vcoeff, Array< int > &attr, Array< int > &values_counter)
Definition: gridfunc.cpp:2114
void SaveVTK(std::ostream &out, const std::string &field_name, int ref)
Write the GridFunction in VTK format. Note that Mesh::PrintVTK must be called first. The parameter ref > 0 must match the one used in Mesh::PrintVTK.
Definition: gridfunc.cpp:3714
void ProjectBdrCoefficient(Coefficient &coeff, Array< int > &attr)
Project a Coefficient on the GridFunction, modifying only DOFs on the boundary associated with the bo...
Definition: gridfunc.hpp:464
Arbitrary order "L2-conforming" discontinuous finite elements.
Definition: fe_coll.hpp:320
void ProjectVectorFieldOn(GridFunction &vec_field, int comp=0)
Definition: gridfunc.cpp:1340
ElementTransformation * GetElementTransformation(int i) const
Returns ElementTransformation for the i-th element.
Definition: fespace.hpp:647