MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
pa.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2026, 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#include "../tmop.hpp"
13#include "../tmop_tools.hpp"
14#include "../gridfunc.hpp"
16
17namespace mfem
18{
19
21 const FiniteElementSpace &fes)
22{
23 MFEM_VERIFY(PA.enabled, "PA extension setup has not been done!");
24 MFEM_VERIFY(PA.fes == &fes, "");
25 // TODO: we need a more robust way to check that the 'fes' used when
26 // AssemblePA() was called has not been modified or completely destroyed and
27 // a new object created at the same address.
28
29 // Form the Vector of node positions, depending on what's the input.
30 Vector xe(de.Size());
31 xe.UseDevice(true);
32 if (x_0)
33 {
34 // The input is the displacement.
35 add(PA.X0, de, xe);
36 }
37 else { xe = de; }
38
39 if (PA.Jtr_needs_update || targetC->UsesPhysicalCoordinates())
40 {
42 PA.Jtr_debug_grad = true;
43 }
44
45 if (PA.dim == 2)
46 {
49 if (adapt_lim_gf.Size() > 0) { AssembleGradPA_AdaptLim_2D(xe); }
50 }
51
52 if (PA.dim == 3)
53 {
56 if (adapt_lim_gf.Size() > 0) { AssembleGradPA_AdaptLim_3D(xe); }
57 }
58}
59
61{
62 const MemoryType mt =
64 // Return immediately if limiting is not enabled
65 if (lim_coeff == nullptr) { return; }
66 MFEM_VERIFY(lim_nodes0, "internal error");
67
68 MFEM_VERIFY(PA.enabled, "AssemblePA_Limiting but PA is not enabled!");
69 MFEM_VERIFY(lim_func, "No TMOP_LimiterFunction specification!")
70 MFEM_VERIFY(
71 dynamic_cast<TMOP_QuadraticLimiter *>(lim_func) ||
72 dynamic_cast<TMOP_ExponentialLimiter *>(lim_func),
73 "Only TMOP_QuadraticLimiter and TMOP_ExponentialLimiter are supported");
74
75 const FiniteElementSpace *fes = PA.fes;
76 const int NE = PA.ne;
77 if (NE == 0) { return; } // Quick return for empty processors
78 const IntegrationRule &ir = *PA.ir;
79
81
82 // H0 for lim_coeff, (dim x dim) Q-vector
83 PA.H0.UseDevice(true);
84 PA.H0.SetSize(PA.dim * PA.dim * PA.nq * NE, mt);
85
86 // lim_coeff -> PA.C0 (Q-vector)
87 PA.C0.UseDevice(true);
88 if (auto *cQ = dynamic_cast<ConstantCoefficient *>(lim_coeff))
89 {
90 PA.C0.SetSize(1, Device::GetMemoryType());
91 PA.C0.HostWrite();
92 PA.C0(0) = cQ->constant;
93 }
94 else
95 {
96 PA.C0.SetSize(PA.nq * PA.ne, Device::GetMemoryType());
97 auto C0 = Reshape(PA.C0.HostWrite(), PA.nq, PA.ne);
98 for (int e = 0; e < NE; ++e)
99 {
101 for (int q = 0; q < ir.GetNPoints(); ++q)
102 {
103 C0(q, e) = lim_coeff->Eval(T, ir.IntPoint(q));
104 }
105 }
106 }
107
108 // lim_nodes0 -> PA.XL (E-vector)
109 MFEM_VERIFY(lim_nodes0->FESpace()->GetVSize() == fes->GetVSize(), "");
110 const Operator *n0_R = fes->GetElementRestriction(ordering);
111 PA.XL.SetSize(n0_R->Height(), Device::GetMemoryType());
112 PA.XL.UseDevice(true);
113 n0_R->Mult(*lim_nodes0, PA.XL);
114
115 // Limiting distances: lim_dist -> PA.LD (E-vector)
116 // TODO: remove the hack for the case lim_dist == NULL.
117 const FiniteElementSpace *limfes = (lim_dist) ? lim_dist->FESpace() : fes;
118 const FiniteElement &lim_fe = *limfes->GetTypicalFE();
119 PA.maps_lim = &lim_fe.GetDofToQuad(ir, DofToQuad::TENSOR);
120 PA.LD.SetSize(NE * lim_fe.GetDof(), Device::GetMemoryType());
121 PA.LD.UseDevice(true);
122 if (lim_dist)
123 {
124 const Operator *ld_R = limfes->GetElementRestriction(ordering);
125 ld_R->Mult(*lim_dist, PA.LD);
126 }
127 else { PA.LD = 1.0; }
128}
129
131 const IntegrationRule &ir,
132 const Vector &xe,
133 DenseTensor &Jtr) const
134{
135 MFEM_VERIFY(Jtr.SizeI() == Jtr.SizeJ() && Jtr.SizeI() > 1, "");
136 const int dim = Jtr.SizeI();
137 bool done = false;
138 if (dim == 2) { done = ComputeAllElementTargets<2>(fes, ir, xe, Jtr); }
139 if (dim == 3) { done = ComputeAllElementTargets<3>(fes, ir, xe, Jtr); }
140
141 if (!done) { ComputeAllElementTargets_Fallback(fes, ir, xe, Jtr); }
142}
143
145 const IntegrationRule &ir,
146 const Vector &xe,
147 DenseTensor &Jtr) const
148{
149 ComputeAllElementTargets_Fallback(fes, ir, xe, Jtr);
150}
151
152// Code paths leading to ComputeElementTargets:
153// - GetElementEnergy(elfun) which is done through GetGridFunctionEnergyPA(x)
154// - AssembleElementVectorExact(elfun)
155// - AssembleElementGradExact(elfun)
156// - EnableNormalization(x) -> ComputeNormalizationEnergies(x)
157// - (AssembleElementVectorFD(elfun))
158// - (AssembleElementGradFD(elfun))
159// ============================================================================
160// - TargetConstructor():
161// - IDEAL_SHAPE_UNIT_SIZE: Wideal
162// - IDEAL_SHAPE_EQUAL_SIZE: α * Wideal
163// - IDEAL_SHAPE_GIVEN_SIZE: β * Wideal
164// - GIVEN_SHAPE_AND_SIZE: β * Wideal
165// - AnalyticAdaptTC(elfun):
166// - GIVEN_FULL: matrix_tspec->Eval(Jtr(elfun))
167// - DiscreteAdaptTC():
168// - IDEAL_SHAPE_GIVEN_SIZE: size^{1.0/dim} * Jtr(i) (size)
169// - GIVEN_SHAPE_AND_SIZE: Jtr(i) *= D_rho (ratio)
170// Jtr(i) *= Q_phi (skew)
171// Jtr(i) *= R_theta (orientation)
173{
174 PA.Jtr_needs_update = false;
175 PA.Jtr_debug_grad = false;
176 const FiniteElementSpace *fes = PA.fes;
177 if (PA.ne == 0) { return; } // Quick return for empty processors
178 const IntegrationRule &ir = *PA.ir;
179
180 const FiniteElement &fe = *fes->GetTypicalFE();
181 MFEM_VERIFY(PA.ir == &EnergyIntegrationRule(fe),
182 "TMOP_Integrator::ComputeAllElementTargets() called with "
183 "different IntegrationRule than the one used in AssemblePA()!");
184
185 // Compute PA.Jtr for all elements
187}
188
190{
191 Vector x_loc;
192 if (periodic)
193 {
194 GetPeriodicPositions(*x_0, d_loc, *x_0->FESpace(), *PA.fes, x_loc);
195 }
196 else
197 {
198 x_loc.SetSize(x_0->Size());
199 add(*x_0, d_loc, x_loc);
200 }
201
202
203 // All are constant or not specified.
204 const int nal = PA.nal;
205 const bool alc_is_qvec =
206 (nal > 0) ? (PA.ALC.Size() == nal * PA.nq * PA.ne) : false;
207 if (PA.MC.Size() == 1 && PA.C0.Size() <= 1 && !alc_is_qvec) { return; }
208
209 // Coefficients are always evaluated on the CPU for now.
210 PA.MC.HostWrite();
211 PA.C0.HostWrite();
212 if (alc_is_qvec) { PA.ALC.HostWrite(); }
213
214 const IntegrationRule &ir = *PA.ir;
215 auto T = new IsoparametricTransformation;
216 for (int e = 0; e < PA.ne; ++e)
217 {
218 // Uses the node positions in x_loc.
219 PA.fes->GetMesh()->GetElementTransformation(e, x_loc, T);
220
221 if (PA.MC.Size() > 1)
222 {
223 for (int q = 0; q < PA.nq; ++q)
224 {
225 PA.MC(q + e * PA.nq) = metric_coeff->Eval(*T, ir.IntPoint(q));
226 }
227 }
228
229 if (PA.C0.Size() > 1)
230 {
231 for (int q = 0; q < PA.nq; ++q)
232 {
233 PA.C0(q + e * PA.nq) = lim_coeff->Eval(*T, ir.IntPoint(q));
234 }
235 }
236
237 if (alc_is_qvec)
238 {
239 MFEM_VERIFY(nal == adapt_lim_coeff.Size(), "internal error");
240 for (int c = 0; c < nal; c++)
241 {
242 real_t *ALC_c = PA.ALC.HostWrite() + c * PA.nq * PA.ne;
243 for (int q = 0; q < PA.nq; ++q)
244 {
245 ALC_c[q + e * PA.nq] =
246 adapt_lim_coeff[c]->Eval(*T, ir.IntPoint(q));
247 }
248 }
249 }
250 }
251
252 delete T;
253}
254
256{
257 const MemoryType mt =
259 PA.enabled = true;
260 PA.fes = &fes;
261 Mesh *mesh = fes.GetMesh();
262 const int ne = PA.ne = mesh->GetNE();
263 if (ne == 0) { return; } // Quick return for empty processors
264 const int dim = PA.dim = mesh->Dimension();
265
266 MFEM_VERIFY(PA.dim == 2 || PA.dim == 3, "Not yet implemented!");
267 MFEM_VERIFY(mesh->GetNumGeometries(dim) <= 1,
268 "TMOP+PA does not support mixed meshes.");
269 MFEM_VERIFY(mesh->HasGeometry(Geometry::SQUARE) ||
271 "TMOP+PA only supports squares and cubes.");
272 MFEM_VERIFY(!fes.IsVariableOrder(), "variable orders are not supported");
273 MFEM_VERIFY(fes.GetOrdering() == Ordering::byNODES,
274 "TMOP+PAP only supports Ordering::byNODES!");
275
276 const FiniteElement &fe = *fes.GetTypicalFE();
277 PA.ir = &EnergyIntegrationRule(fe);
278 const IntegrationRule &ir = *PA.ir;
279 const int nq = PA.nq = ir.GetNPoints();
281 PA.maps = &fe.GetDofToQuad(ir, mode);
282 // Note - initial mesh. TODO delete this?
284
285 // Initial node positions.
286 // PA.X0 is also updated in TMOP_Integrator::SetInitialMeshPos.
287 if (x_0 != nullptr)
288 {
290 auto n0_R = x_0->FESpace()->GetElementRestriction(ord);
291 PA.X0.UseDevice(true);
292 PA.X0.SetSize(n0_R->Height(), Device::GetMemoryType());
293 n0_R->Mult(*x_0, PA.X0);
294 }
295
296 // Energy vector, scalar Q-vector
297 PA.E.UseDevice(true);
298 PA.E.SetSize(ne * nq, Device::GetDeviceMemoryType());
299
300 // H for Grad, (dim x dim) Q-vector
301 PA.H.UseDevice(true);
302 PA.H.SetSize(dim * dim * dim * dim * nq * ne, mt);
303
304 // Scalar Q-vector of '1', used to compute sums via dot product
305 PA.O.UseDevice(true);
306 PA.O.SetSize(ne * nq, Device::GetDeviceMemoryType());
307 PA.O = 1.0;
308
309 if (metric_coeff)
310 {
311 if (auto cc = dynamic_cast<ConstantCoefficient *>(metric_coeff))
312 {
313 PA.MC.SetSize(1, Device::GetMemoryType());
314 PA.MC.HostWrite();
315 PA.MC(0) = cc->constant;
316 }
317 else
318 {
319 PA.MC.SetSize(PA.nq * PA.ne, Device::GetMemoryType());
320 auto M0 = Reshape(PA.MC.HostWrite(), PA.nq, PA.ne);
321 for (int e = 0; e < PA.ne; ++e)
322 {
323 ElementTransformation &T = *PA.fes->GetElementTransformation(e);
324 for (int q = 0; q < ir.GetNPoints(); ++q)
325 {
326 // Note that this is always on the initial mesh.
327 M0(q,e) = metric_coeff->Eval(T, ir.IntPoint(q));
328 }
329 }
330 }
331 }
332 else
333 {
334 PA.MC.SetSize(1, Device::GetMemoryType());
335 PA.MC.HostWrite();
336 PA.MC(0) = 1.0;
337 }
338
339 // Setup ref->target Jacobians, PA.Jtr, (dim x dim) Q-vector, DenseTensor
340 PA.Jtr.SetSize(dim, dim, PA.ne * PA.nq, mt);
341 PA.Jtr_needs_update = true;
342 PA.Jtr_debug_grad = false;
343
344 // Limiting: lim_coeff -> PA.C0, lim_nodes0 -> PA.XL, lim_dist -> PA.LD, PA.H0
346 // Adaptive limiting: adapt_lim_coeff -> PA.ALC, adapt_lim_gf -> PA.ALF,
347 // adapt_lim_gf0 -> PA.ALF0, adapt_lim_delta_max -> PA.ALD
348 if (adapt_lim_gf.Size() > 0) { AssemblePA_AdaptLim(); }
349}
350
352{
353 const int nal = adapt_lim_coeff.Size();
354 MFEM_VERIFY(nal > 0, "internal error");
355
356 MFEM_VERIFY(adapt_lim_gf.Size() == nal && adapt_lim_gf0.Size() == nal,
357 "internal error");
358 const FiniteElementSpace *alfes = adapt_lim_gf[0]->FESpace();
359 MFEM_VERIFY(alfes && alfes->GetVDim() == 1, "internal error");
360
361 MFEM_VERIFY(strcmp(alfes->FEColl()->Name(), PA.fes->FEColl()->Name()) == 0 &&
362 alfes->FEColl()->GetOrder() == PA.fes->FEColl()->GetOrder(),
363 "The PA code assumes the same FE spaces for mesh and limiting.");
364
365 PA.AL_grads_assembled = false;
366 PA.nal = nal;
367
368 // adapt_lim_coeff -> PA.ALC
369 // Keep the ConstantCoefficient fast-path: when all coefficients are
370 // constant, store one scalar per adaptive-limiting term.
371 bool all_const = true;
372 for (int c = 0; c < nal; c++)
373 {
374 if (!dynamic_cast<ConstantCoefficient *>(adapt_lim_coeff[c]))
375 {
376 all_const = false;
377 break;
378 }
379 }
380 PA.ALC.UseDevice(true);
381 if (all_const)
382 {
383 PA.ALC.SetSize(nal, Device::GetMemoryType());
384 real_t *ALC_all = PA.ALC.HostWrite();
385 for (int c = 0; c < nal; c++)
386 {
387 auto *cc = dynamic_cast<ConstantCoefficient *>(adapt_lim_coeff[c]);
388 MFEM_VERIFY(cc, "internal error");
389 ALC_all[c] = cc->constant;
390 }
391 }
392 else
393 {
394 // If one Coefficient is not constant, we allocate the full size for
395 // all Coefficients. Could be optimized in the future.
396 PA.ALC.SetSize(nal * PA.nq * PA.ne, Device::GetMemoryType());
397 real_t *ALC_all = PA.ALC.HostWrite();
398 for (int c = 0; c < nal; c++)
399 {
400 real_t *ALC_c = ALC_all + c * PA.nq * PA.ne;
401 for (int e = 0; e < PA.ne; ++e)
402 {
403 ElementTransformation &T = *PA.fes->GetElementTransformation(e);
404 for (int q = 0; q < PA.ir->GetNPoints(); ++q)
405 {
406 ALC_c[q + e * PA.nq] =
407 adapt_lim_coeff[c]->Eval(T, PA.ir->IntPoint(q));
408 }
409 }
410 }
411 }
412
414
415 const FiniteElement *fe_n = PA.fes->GetTypicalFE();
416 // GetNodes() for tensor H1 elements with H1_DOF_MAP is stored in NATIVE
417 // order (via dof_map), while DofToQuad::TENSOR assumes LEXICOGRAPHIC
418 // ordering of the integration points.
419 const IntegrationRule &nodes = fe_n->GetNodes();
420 const auto *nfe = dynamic_cast<const NodalFiniteElement *>(fe_n);
421 const Array<int> *lex = (nfe && nfe->GetLexicographicOrdering().Size() > 0)
422 ? &nfe->GetLexicographicOrdering() : nullptr;
423 if (!lex)
424 {
425 PA.maps_nodes = &fe_n->GetDofToQuad(nodes, DofToQuad::TENSOR);
426 }
427 else
428 {
429 IntegrationRule lex_nodes(nodes.GetNPoints());
430 MFEM_VERIFY(lex->Size() == nodes.GetNPoints(), "");
431 for (int i = 0; i < nodes.GetNPoints(); i++)
432 {
433 lex_nodes.IntPoint(i) = nodes.IntPoint((*lex)[i]);
434 }
435 PA.maps_nodes = &fe_n->GetDofToQuad(lex_nodes, DofToQuad::TENSOR);
436 }
437
438 // Restrict each adaptive limiting field into separate contiguous E-vectors
439 // (one block per adaptive limiting term).
440 const Operator *alf_R = alfes->GetElementRestriction(ordering);
441 const int ndofs = alfes->GetVSize();
442
443 const int Esize = alf_R->Height();
444 PA.ALF.SetSize(nal * Esize, Device::GetMemoryType());
445 PA.ALF.UseDevice(true);
446 PA.ALFmF0.SetSize(nal * Esize, Device::GetMemoryType());
447 PA.ALFmF0.UseDevice(true);
448
449 Vector ALFc, ALF0c;
450 for (int c = 0; c < nal; c++)
451 {
452 ALFc.MakeRef(PA.ALF, c * Esize, Esize);
453 ALF0c.MakeRef(PA.ALFmF0, c * Esize, Esize);
454
455 MFEM_VERIFY(adapt_lim_gf[c]->Size() == ndofs, "internal error");
456 MFEM_VERIFY(adapt_lim_gf0[c]->Size() == ndofs, "internal error");
457 alf_R->Mult(*adapt_lim_gf[c], ALFc);
458 alf_R->Mult(*adapt_lim_gf0[c], ALF0c);
459 }
460
461 // Build differences in-place: ALFmF0 = ALF - ALF0.
462 PA.ALFmF0 *= -1.0;
463 PA.ALFmF0 += PA.ALF;
464
465 // Per-field delta_max values.
466 MFEM_VERIFY(adapt_lim_delta_max.Size() == nal, "internal error");
467 PA.ALD.SetSize(nal);
468 PA.ALD.HostWrite();
469 for (int c = 0; c < nal; c++) { PA.ALD(c) = adapt_lim_delta_max[c]; }
470
471 // Allocate storage for gradient and Hessian of ALF at quadrature points
472 // These will be filled during AssembleGradPA
473 const int dim = PA.dim;
474 PA.ALFG.UseDevice(true);
475 PA.ALFG.SetSize(nal * dim * PA.nq * PA.ne, Device::GetMemoryType());
476 PA.ALFH.UseDevice(true);
477 PA.ALFH.SetSize(nal * dim * dim * PA.nq * PA.ne, Device::GetMemoryType());
478
479}
480
482{
483 // This method must be called after AssembleGradPA().
484
485 MFEM_VERIFY(PA.Jtr_needs_update == false, "");
486
488 {
489 MFEM_VERIFY(PA.Jtr_debug_grad == true,
490 "AssembleGradPA() was not called"
491 " or Jtr was overwritten by another method!");
492 }
493
494 if (PA.dim == 2)
495 {
498 if (adapt_lim_gf.Size() > 0) { AssembleDiagonalPA_AdaptLim_2D(de); }
499 }
500
501 if (PA.dim == 3)
502 {
505 if (adapt_lim_gf.Size() > 0) { AssembleDiagonalPA_AdaptLim_3D(de); }
506 }
507}
508
509void TMOP_Integrator::AddMultPA(const Vector &de, Vector &ye) const
510{
511 // This method must be called after AssemblePA().
512
513 // Form the Vector of node positions, depending on what's the input.
514 Vector xe(de.Size());
515 xe.UseDevice(true);
516 if (x_0)
517 {
518 // The input is the displacement.
519 add(PA.X0, de, xe);
520 }
521 else { xe = de; }
522
523 if (PA.Jtr_needs_update || targetC->UsesPhysicalCoordinates())
524 {
526 }
527
528 if (PA.dim == 2)
529 {
530 AddMultPA_2D(xe, ye);
531 if (lim_coeff) { AddMultPA_C0_2D(xe, ye); }
532 if (adapt_lim_gf.Size() > 0)
533 {
534 // AddMultPA_AdaptLim_2D uses the precomputed AdaptLim field gradient
535 // at quadrature points (PA.ALFG). Ensure it is up-to-date for the
536 // current mesh configuration.
538 AddMultPA_AdaptLim_2D(xe, ye);
539 }
540
541 }
542
543 if (PA.dim == 3)
544 {
545 AddMultPA_3D(xe, ye);
546 if (lim_coeff) { AddMultPA_C0_3D(xe, ye); }
547 if (adapt_lim_gf.Size() > 0)
548 {
550 AddMultPA_AdaptLim_3D(xe, ye);
551 }
552 }
553}
554
556{
557 // This method must be called after AssembleGradPA().
558
559 MFEM_VERIFY(PA.Jtr_needs_update == false, "");
560
562 {
563 MFEM_VERIFY(PA.Jtr_debug_grad == true,
564 "AssembleGradPA() was not called or "
565 "Jtr was overwritten by another method!");
566 }
567
568 if (PA.dim == 2)
569 {
570 AddMultGradPA_2D(re, ce);
571 if (lim_coeff) { AddMultGradPA_C0_2D(re, ce); }
572 if (adapt_lim_gf.Size() > 0) { AddMultGradPA_AdaptLim_2D(re, ce); }
573 }
574
575 if (PA.dim == 3)
576 {
577 AddMultGradPA_3D(re, ce);
578 if (lim_coeff) { AddMultGradPA_C0_3D(re, ce); }
579 if (adapt_lim_gf.Size() > 0) { AddMultGradPA_AdaptLim_3D(re, ce); }
580 }
581}
582
584{
585 // This method must be called after AssemblePA().
586
587 // Form the Vector of node positions, depending on what's the input.
588 Vector xe(de.Size());
589 xe.UseDevice(true);
590 if (x_0)
591 {
592 // The input is the displacement.
593 add(PA.X0, de, xe);
594 }
595 else { xe = de; }
596
597 real_t energy = 0.0;
598
599 if (PA.Jtr_needs_update || targetC->UsesPhysicalCoordinates())
600 {
602 }
603
604 if (PA.dim == 2)
605 {
606 GetLocalStateEnergyPA_2D(xe, energy);
607 if (lim_coeff) { energy += GetLocalStateEnergyPA_C0_2D(xe); }
608 if (adapt_lim_gf.Size() > 0)
609 { energy += GetLocalStateEnergyPA_AdaptLim_2D(); }
610 }
611
612 if (PA.dim == 3)
613 {
614 GetLocalStateEnergyPA_3D(xe, energy);
615 if (lim_coeff) { energy += GetLocalStateEnergyPA_C0_3D(xe); }
616 if (adapt_lim_gf.Size() > 0)
617 { energy += GetLocalStateEnergyPA_AdaptLim_3D(); }
618 }
619
620 return energy;
621}
622
623} // namespace mfem
void ComputeAllElementTargets(const FiniteElementSpace &fes, const IntegrationRule &ir, const Vector &xe, DenseTensor &Jtr) const override
Computes reference-to-target transformation Jacobians for all quadrature points in all elements.
Definition pa.cpp:144
int Size() const
Return the logical size of the array.
Definition array.hpp:192
void UseDevice(bool use_dev) const
Set the device flag of the Array, i.e. the device flag of the Memory object used by the Array.
Definition array.hpp:174
virtual real_t Eval(ElementTransformation &T, const IntegrationPoint &ip)=0
Evaluate the coefficient in the element described by T at the point ip.
A coefficient that is constant across space and time.
Rank 3 tensor (array of matrices)
int SizeJ() const
int SizeI() const
static MemoryType GetMemoryType()
(DEPRECATED) Equivalent to GetDeviceMemoryType().
Definition device.hpp:302
static MemoryType GetDeviceMemoryType()
Get the current Device MemoryType. This is the MemoryType used by most MFEM classes when allocating m...
Definition device.hpp:298
Mode
Type of data stored in the arrays B, Bt, G, and Gt.
Definition fe_base.hpp:154
@ TENSOR
Tensor product representation using 1D matrices/tensors with dimensions using 1D number of quadrature...
Definition fe_base.hpp:165
const IntegrationPoint * IntPoint
Definition eltrans.hpp:30
int GetOrder() const
Return the order (polynomial degree) of the FE collection, corresponding to the order/degree returned...
Definition fe_coll.hpp:248
virtual const char * Name() const
Definition fe_coll.hpp:79
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:210
bool IsVariableOrder() const
Returns true if the space contains elements of varying polynomial orders.
Definition fespace.hpp:673
ElementTransformation * GetElementTransformation(int i) const
Definition fespace.hpp:903
Ordering::Type GetOrdering() const
Return the ordering method.
Definition fespace.hpp:852
const ElementRestrictionOperator * GetElementRestriction(ElementDofOrdering e_ordering) const
Return an Operator that converts L-vectors to E-vectors.
Definition fespace.cpp:1476
const FiniteElementCollection * FEColl() const
Definition fespace.hpp:854
Mesh * GetMesh() const
Returns the mesh.
Definition fespace.hpp:639
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
Definition fespace.hpp:824
int GetVDim() const
Returns the vector dimension of the finite element space.
Definition fespace.hpp:817
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:3896
Abstract class for all finite elements.
Definition fe_base.hpp:294
virtual const DofToQuad & GetDofToQuad(const IntegrationRule &ir, DofToQuad::Mode mode) const
Return a DofToQuad structure corresponding to the given IntegrationRule using the given DofToQuad::Mo...
Definition fe_base.cpp:373
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
Definition fe_base.hpp:476
int GetDof() const
Returns the number of degrees of freedom in the finite element.
Definition fe_base.hpp:410
FiniteElementSpace * FESpace()
Class for an integration rule - an Array of IntegrationPoint.
Definition intrules.hpp:96
int GetNPoints() const
Returns the number of the points in the integration rule.
Definition intrules.hpp:255
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
Definition intrules.hpp:258
A standard isoparametric element transformation.
Definition eltrans.hpp:629
Mesh data type.
Definition mesh.hpp:67
int GetNE() const
Returns number of elements.
Definition mesh.hpp:1390
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1314
const GeometricFactors * GetGeometricFactors(const IntegrationRule &ir, const int flags, MemoryType d_mt=MemoryType::DEFAULT)
Return the mesh geometric factors corresponding to the given integration rule.
Definition mesh.cpp:958
bool HasGeometry(Geometry::Type geom) const
Return true iff the given geom is encountered in the mesh. Geometries of dimensions lower than Dimens...
Definition mesh.hpp:1348
int GetNumGeometries(int dim) const
Return the number of geometries of the given dimension present in the mesh.
Definition mesh.cpp:8014
Class for standard nodal finite elements.
Definition fe_base.hpp:798
Abstract operator.
Definition operator.hpp:27
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Definition operator.hpp:68
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
Exponential limiter function in TMOP_Integrator.
Definition tmop.hpp:1454
void AddMultGradPA(const Vector &, Vector &) const override
Method for partially assembled gradient action.
Definition pa.cpp:555
real_t GetLocalStateEnergyPA_AdaptLim_2D() const
void GetLocalStateEnergyPA_3D(const Vector &x, real_t &energy) const
real_t GetLocalStateEnergyPA_C0_2D(const Vector &) const
TMOP_LimiterFunction * lim_func
Definition tmop.hpp:2036
void ComputeAllElementTargets(const Vector &xe=Vector()) const
Definition pa.cpp:172
void AddMultGradPA_AdaptLim_2D(const Vector &, Vector &) const
void AddMultPA_C0_3D(const Vector &, Vector &) const
void AddMultPA_AdaptLim_3D(const Vector &, Vector &) const
void AssembleDiagonalPA_2D(Vector &) const
void AssembleDiagonalPA_AdaptLim_3D(Vector &) const
Coefficient * lim_coeff
Definition tmop.hpp:2032
const GridFunction * lim_dist
Definition tmop.hpp:2034
void AssembleDiagonalPA_C0_3D(Vector &) const
struct mfem::TMOP_Integrator::@25 PA
void AddMultGradPA_2D(const Vector &, Vector &) const
void AssembleGradPA_C0_2D(const Vector &) const
const TargetConstructor * targetC
Definition tmop.hpp:2016
void GetLocalStateEnergyPA_2D(const Vector &x, real_t &energy) const
const GridFunction * lim_nodes0
Definition tmop.hpp:2031
Array< Coefficient * > adapt_lim_coeff
Definition tmop.hpp:2049
const IntegrationRule * ir
Definition tmop.hpp:2159
void AssemblePA(const FiniteElementSpace &) override
Method defining partial assembly.
Definition pa.cpp:255
void AssembleGradDiagonalPA(Vector &) const override
Method for computing the diagonal of the gradient with partial assembly.
Definition pa.cpp:481
void AssembleDiagonalPA_C0_2D(Vector &) const
real_t GetLocalStateEnergyPA_C0_3D(const Vector &) const
void AddMultGradPA_3D(const Vector &, Vector &) const
const FiniteElementSpace * fes
Definition tmop.hpp:2158
void AssembleDiagonalPA_AdaptLim_2D(Vector &) const
void AssemblePA_Limiting()
Definition pa.cpp:60
const IntegrationRule & EnergyIntegrationRule(const FiniteElement &el) const
Definition tmop.hpp:2219
void AddMultPA_2D(const Vector &, Vector &) const
void AddMultGradPA_AdaptLim_3D(const Vector &, Vector &) const
real_t GetLocalStateEnergyPA_AdaptLim_3D() const
void AddMultPA_3D(const Vector &, Vector &) const
Array< GridFunction * > adapt_lim_gf0
Definition tmop.hpp:2046
void AssembleGradPA_AdaptLim_2D(const Vector &) const
void AssembleGradPA_C0_3D(const Vector &) const
void AssembleGradPA_2D(const Vector &) const
void AddMultPA_AdaptLim_2D(const Vector &, Vector &) const
void AssembleGradPA_AdaptLim_3D(const Vector &) const
Coefficient * metric_coeff
Definition tmop.hpp:2024
Array< GridFunction * > adapt_lim_gf
Definition tmop.hpp:2047
const GridFunction * x_0
Definition tmop.hpp:2011
void AddMultPA(const Vector &, Vector &) const override
Method for partially assembled action.
Definition pa.cpp:509
void AddMultGradPA_C0_2D(const Vector &, Vector &) const
void AssembleDiagonalPA_3D(Vector &) const
void AssemblePA_AdaptLim()
Definition pa.cpp:351
void UpdateCoefficientsPA(const Vector &d_loc)
Definition pa.cpp:189
void AssembleGradPA_3D(const Vector &) const
Array< real_t > adapt_lim_delta_max
Definition tmop.hpp:2051
void AssembleGradPA(const Vector &, const FiniteElementSpace &) override
Prepare the integrator for partial assembly (PA) gradient evaluations on the given FE space fes at th...
Definition pa.cpp:20
void AddMultPA_C0_2D(const Vector &, Vector &) const
real_t GetLocalStateEnergyPA(const Vector &) const override
Compute the local (to the MPI rank) energy with partial assembly.
Definition pa.cpp:583
void AddMultGradPA_C0_3D(const Vector &, Vector &) const
Default limiter function in TMOP_Integrator.
Definition tmop.hpp:1422
bool UsesPhysicalCoordinates() const
Return true if the methods ComputeElementTargets(), ComputeAllElementTargets(), and ComputeElementTar...
Definition tmop.hpp:1683
void ComputeAllElementTargets_Fallback(const FiniteElementSpace &fes, const IntegrationRule &ir, const Vector &xe, DenseTensor &Jtr) const
Definition tmop.cpp:2432
bool ComputeAllElementTargets(const FiniteElementSpace &fes, const IntegrationRule &ir, const Vector &xe, DenseTensor &Jtr) const
Vector data type.
Definition vector.hpp:82
int Size() const
Returns the size of the vector.
Definition vector.hpp:234
virtual void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
Definition vector.hpp:145
void SetSize(int s)
Resize the vector to size s.
Definition vector.hpp:633
void MakeRef(Vector &base, int offset, int size)
Reset the Vector to be a reference to a sub-vector of base.
Definition vector.hpp:709
int dim
Definition ex24.cpp:53
void add(const Vector &v1, const Vector &v2, Vector &v)
Definition vector.cpp:414
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims... dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
Definition dtensor.hpp:138
void GetPeriodicPositions(const Vector &x_0, const Vector &dx, const FiniteElementSpace &fesL2, const FiniteElementSpace &fesH1, Vector &x)
float real_t
Definition config.hpp:46
MemoryType
Memory types supported by MFEM.
ElementDofOrdering
Constants describing the possible orderings of the DOFs in one element.
Definition fespace.hpp:49
std::array< int, NCMesh::MaxFaceNodes > nodes