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