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