MFEM v4.7.0
Finite element discretization library
Loading...
Searching...
No Matches
tmop.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2024, 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 "linearform.hpp"
14#include "pgridfunc.hpp"
15#include "tmop_tools.hpp"
16#include "../general/forall.hpp"
17
18namespace mfem
19{
20
21// Target-matrix optimization paradigm (TMOP) mesh quality metrics.
22
24{
25 real_t metric = 0.;
26 for (int i = 0; i < tmop_q_arr.Size(); i++)
27 {
28 metric += wt_arr[i]*tmop_q_arr[i]->EvalWMatrixForm(Jpt);
29 }
30 return metric;
31}
32
34{
35 real_t metric = 0.;
36 for (int i = 0; i < tmop_q_arr.Size(); i++)
37 {
38 metric += wt_arr[i]*tmop_q_arr[i]->EvalW(Jpt);
39 }
40 return metric;
41}
42
44 DenseMatrix &P) const
45{
46 DenseMatrix Pt(P.Size());
47 P = 0.0;
48 for (int i = 0; i < tmop_q_arr.Size(); i++)
49 {
50 tmop_q_arr[i]->EvalP(Jpt, Pt);
51 P.Add(wt_arr[i], Pt);
52 }
53}
54
56 const DenseMatrix &DS,
57 const real_t weight,
58 DenseMatrix &A) const
59{
60 DenseMatrix At(A.Size());
61 for (int i = 0; i < tmop_q_arr.Size(); i++)
62 {
63 At = 0.0;
64 tmop_q_arr[i]->AssembleH(Jpt, DS, weight * wt_arr[i], At);
65 A += At;
66 }
67}
68
71 const TargetConstructor &tc, Vector &weights) const
72{
73 const int m_cnt = tmop_q_arr.Size();
74 Vector averages;
75 ComputeAvgMetrics(nodes, tc, averages);
76 weights.SetSize(m_cnt);
77
78 // For [ combo_A_B_C = a m_A + b m_B + c m_C ] we would have:
79 // a = BC / (AB + AC + BC), b = AC / (AB + AC + BC), c = AB / (AB + AC + BC),
80 // where A = avg_m_A, B = avg_m_B, C = avg_m_C.
81 // Nested loop to avoid division, as some avg may be 0.
82 Vector products_no_m(m_cnt); products_no_m = 1.0;
83 for (int m_p = 0; m_p < m_cnt; m_p++)
84 {
85 for (int m_a = 0; m_a < m_cnt; m_a++)
86 {
87 if (m_p != m_a) { products_no_m(m_p) *= averages(m_a); }
88 }
89 }
90 const real_t pnm_sum = products_no_m.Sum();
91
92 if (pnm_sum == 0.0) { weights = 1.0 / m_cnt; return; }
93 for (int m = 0; m < m_cnt; m++) { weights(m) = products_no_m(m) / pnm_sum; }
94
95 MFEM_ASSERT(fabs(weights.Sum() - 1.0) < 1e-14,
96 "Error: sum should be 1 always: " << weights.Sum());
97}
98
100 const TargetConstructor &tc,
101 Vector &averages) const
102{
103 const int m_cnt = tmop_q_arr.Size(),
104 NE = nodes.FESpace()->GetNE(),
105 dim = nodes.FESpace()->GetMesh()->Dimension();
106
107 averages.SetSize(m_cnt);
108
109 // Integrals of all metrics.
110 Array<int> pos_dofs;
111 averages = 0.0;
112 real_t volume = 0.0;
113 for (int e = 0; e < NE; e++)
114 {
115 const FiniteElement &fe_pos = *nodes.FESpace()->GetFE(e);
116 const IntegrationRule &ir = IntRules.Get(fe_pos.GetGeomType(),
117 2 * fe_pos.GetOrder());
118 const int nsp = ir.GetNPoints(), dof = fe_pos.GetDof();
119
120 DenseMatrix dshape(dof, dim);
121 DenseMatrix pos(dof, dim);
122 pos.SetSize(dof, dim);
123 Vector posV(pos.Data(), dof * dim);
124
125 nodes.FESpace()->GetElementVDofs(e, pos_dofs);
126 nodes.GetSubVector(pos_dofs, posV);
127
128 DenseTensor W(dim, dim, nsp);
129 DenseMatrix Winv(dim), T(dim), A(dim);
130 tc.ComputeElementTargets(e, fe_pos, ir, posV, W);
131
132 for (int q = 0; q < nsp; q++)
133 {
134 const DenseMatrix &Wj = W(q);
135 CalcInverse(Wj, Winv);
136
137 const IntegrationPoint &ip = ir.IntPoint(q);
138 fe_pos.CalcDShape(ip, dshape);
139 MultAtB(pos, dshape, A);
140 Mult(A, Winv, T);
141
142 const real_t w_detA = ip.weight * A.Det();
143 for (int m = 0; m < m_cnt; m++)
144 {
145 tmop_q_arr[m]->SetTargetJacobian(Wj);
146 averages(m) += tmop_q_arr[m]->EvalW(T) * w_detA;
147 }
148 volume += w_detA;
149 }
150 }
151
152 // Parallel case.
153#ifdef MFEM_USE_MPI
154 auto par_nodes = dynamic_cast<const ParGridFunction *>(&nodes);
155 if (par_nodes)
156 {
157 MPI_Allreduce(MPI_IN_PLACE, averages.GetData(), m_cnt,
158 MPITypeMap<real_t>::mpi_type, MPI_SUM, par_nodes->ParFESpace()->GetComm());
159 MPI_Allreduce(MPI_IN_PLACE, &volume, 1, MPITypeMap<real_t>::mpi_type, MPI_SUM,
160 par_nodes->ParFESpace()->GetComm());
161 }
162#endif
163
164 averages /= volume;
165}
166
168const
169{
170 real_t metric_tilde = EvalWBarrier(Jpt);
171 real_t metric = metric_tilde;
173 {
174 metric = std::pow(metric_tilde, exponent);
175 }
176 else if (wctype == WorstCaseType::Beta)
177 {
179 metric = metric_tilde/(beta-metric_tilde);
180 }
181 return metric;
182}
183
185 const DenseMatrix &Jpt) const
186{
187 real_t denominator = 1.0;
189 {
190 denominator = 2.0*(Jpt.Det()-std::min(alpha*min_detT-detT_ep, (real_t) 0.0));
191 }
192 else if (btype == BarrierType::Pseudo)
193 {
194 real_t detT = Jpt.Det();
195 denominator = detT + std::sqrt(detT*detT + detT_ep*detT_ep);
196 }
197 return tmop_metric.EvalW(Jpt)/denominator;
198}
199
201{
202 ie.SetJacobian(Jpt.GetData());
203 return ie.Get_I1();
204}
205
207{
208 ie.SetJacobian(Jpt.GetData());
209 P = ie.Get_dI1();
210}
211
213 const DenseMatrix &DS,
214 const real_t weight,
215 DenseMatrix &A) const
216{
217 ie.SetJacobian(Jpt.GetData());
219 ie.Assemble_ddI1(weight, A.GetData());
220}
221
223{
224 MFEM_VERIFY(Jtr != NULL,
225 "Requires a target Jacobian, use SetTargetJacobian().");
226
227 DenseMatrix Jpr(2, 2);
228 Mult(Jpt, *Jtr, Jpr);
229
230 Vector col1, col2;
231 Jpr.GetColumn(0, col1);
232 Jpr.GetColumn(1, col2);
233 real_t norm_prod = col1.Norml2() * col2.Norml2();
234 const real_t cos_Jpr = (col1 * col2) / norm_prod,
235 sin_Jpr = fabs(Jpr.Det()) / norm_prod;
236
237 Jtr->GetColumn(0, col1);
238 Jtr->GetColumn(1, col2);
239 norm_prod = col1.Norml2() * col2.Norml2();
240 const real_t cos_Jtr = (col1 * col2) / norm_prod,
241 sin_Jtr = fabs(Jtr->Det()) / norm_prod;
242
243 return 0.5 * (1.0 - cos_Jpr * cos_Jtr - sin_Jpr * sin_Jtr);
244}
245
247{
248 MFEM_VERIFY(Jtr != NULL,
249 "Requires a target Jacobian, use SetTargetJacobian().");
250
251 DenseMatrix Jpr(3, 3);
252 Mult(Jpt, *Jtr, Jpr);
253
254 Vector col1, col2, col3;
255 Jpr.GetColumn(0, col1);
256 Jpr.GetColumn(1, col2);
257 Jpr.GetColumn(2, col3);
258 real_t norm_c1 = col1.Norml2(),
259 norm_c2 = col2.Norml2(),
260 norm_c3 = col3.Norml2();
261 real_t cos_Jpr_12 = (col1 * col2) / (norm_c1 * norm_c2),
262 cos_Jpr_13 = (col1 * col3) / (norm_c1 * norm_c3),
263 cos_Jpr_23 = (col2 * col3) / (norm_c2 * norm_c3);
264 real_t sin_Jpr_12 = std::sqrt(1.0 - cos_Jpr_12 * cos_Jpr_12),
265 sin_Jpr_13 = std::sqrt(1.0 - cos_Jpr_13 * cos_Jpr_13),
266 sin_Jpr_23 = std::sqrt(1.0 - cos_Jpr_23 * cos_Jpr_23);
267
268 Jtr->GetColumn(0, col1);
269 Jtr->GetColumn(1, col2);
270 Jtr->GetColumn(2, col3);
271 norm_c1 = col1.Norml2();
272 norm_c2 = col2.Norml2(),
273 norm_c3 = col3.Norml2();
274 real_t cos_Jtr_12 = (col1 * col2) / (norm_c1 * norm_c2),
275 cos_Jtr_13 = (col1 * col3) / (norm_c1 * norm_c3),
276 cos_Jtr_23 = (col2 * col3) / (norm_c2 * norm_c3);
277 real_t sin_Jtr_12 = std::sqrt(1.0 - cos_Jtr_12 * cos_Jtr_12),
278 sin_Jtr_13 = std::sqrt(1.0 - cos_Jtr_13 * cos_Jtr_13),
279 sin_Jtr_23 = std::sqrt(1.0 - cos_Jtr_23 * cos_Jtr_23);
280
281 return (3.0 - cos_Jpr_12 * cos_Jtr_12 - sin_Jpr_12 * sin_Jtr_12
282 - cos_Jpr_13 * cos_Jtr_13 - sin_Jpr_13 * sin_Jtr_13
283 - cos_Jpr_23 * cos_Jtr_23 - sin_Jpr_23 * sin_Jtr_23) / 6.0;
284}
285
287{
288 MFEM_VERIFY(Jtr != NULL,
289 "Requires a target Jacobian, use SetTargetJacobian().");
290
291 DenseMatrix Jpr(2, 2);
292 Mult(Jpt, *Jtr, Jpr);
293
294 Vector col1, col2;
295 Jpr.GetColumn(0, col1);
296 Jpr.GetColumn(1, col2);
297 const real_t ratio_Jpr = col2.Norml2() / col1.Norml2();
298
299 Jtr->GetColumn(0, col1);
300 Jtr->GetColumn(1, col2);
301 const real_t ratio_Jtr = col2.Norml2() / col1.Norml2();
302
303 return 0.5 * (ratio_Jpr / ratio_Jtr + ratio_Jtr / ratio_Jpr) - 1.0;
304}
305
307{
308 MFEM_VERIFY(Jtr != NULL,
309 "Requires a target Jacobian, use SetTargetJacobian().");
310
311 DenseMatrix Jpr(3, 3);
312 Mult(Jpt, *Jtr, Jpr);
313
314 Vector col1, col2, col3;
315 Jpr.GetColumn(0, col1);
316 Jpr.GetColumn(1, col2);
317 Jpr.GetColumn(2, col3);
318 real_t norm_c1 = col1.Norml2(),
319 norm_c2 = col2.Norml2(),
320 norm_c3 = col3.Norml2();
321 real_t ratio_Jpr_1 = norm_c1 / std::sqrt(norm_c2 * norm_c3),
322 ratio_Jpr_2 = norm_c2 / std::sqrt(norm_c1 * norm_c3),
323 ratio_Jpr_3 = norm_c3 / std::sqrt(norm_c1 * norm_c2);
324
325 Jtr->GetColumn(0, col1);
326 Jtr->GetColumn(1, col2);
327 Jtr->GetColumn(2, col3);
328 norm_c1 = col1.Norml2();
329 norm_c2 = col2.Norml2();
330 norm_c3 = col3.Norml2();
331 real_t ratio_Jtr_1 = norm_c1 / std::sqrt(norm_c2 * norm_c3),
332 ratio_Jtr_2 = norm_c2 / std::sqrt(norm_c1 * norm_c3),
333 ratio_Jtr_3 = norm_c3 / std::sqrt(norm_c1 * norm_c2);
334
335 return ( 0.5 * (ratio_Jpr_1 / ratio_Jtr_1 + ratio_Jtr_1 / ratio_Jpr_1) +
336 0.5 * (ratio_Jpr_2 / ratio_Jtr_2 + ratio_Jtr_2 / ratio_Jpr_2) +
337 0.5 * (ratio_Jpr_3 / ratio_Jtr_3 + ratio_Jtr_3 / ratio_Jpr_3) - 3.0
338 ) / 3.0;
339}
340
342{
343 return 0.5 * Jpt.FNorm2() / Jpt.Det() - 1.0;
344}
345
347{
348 ie.SetJacobian(Jpt.GetData());
349 return 0.5 * ie.Get_I1b() - 1.0;
350}
351
353{
354 ie.SetJacobian(Jpt.GetData());
355 P.Set(0.5, ie.Get_dI1b());
356}
357
359 const DenseMatrix &DS,
360 const real_t weight,
361 DenseMatrix &A) const
362{
363 ie.SetJacobian(Jpt.GetData());
365 ie.Assemble_ddI1b(0.5*weight, A.GetData());
366}
367
369{
370 ie.SetJacobian(Jpt.GetData());
371 return ie.Get_I1() - 2.0*ie.Get_I2b();
372}
373
375{
376 ie.SetJacobian(Jpt.GetData());
377 Add(1.0, ie.Get_dI1(), -2.0, ie.Get_dI2b(), P);
378}
379
381 const DenseMatrix &DS,
382 const real_t weight,
383 DenseMatrix &A) const
384{
385 ie.SetJacobian(Jpt.GetData());
387
388 ie.Assemble_ddI1(weight, A.GetData());
389 ie.Assemble_ddI2b(-2.0*weight, A.GetData());
390}
391
393{
394 // mu_7 = |J-J^{-t}|^2 = |J|^2 + |J^{-1}|^2 - 4
395 ie.SetJacobian(Jpt.GetData());
396 return ie.Get_I1()*(1. + 1./ie.Get_I2()) - 4.0;
397}
398
400{
401 // P = d(I1*(1 + 1/I2)) = (1 + 1/I2) dI1 - I1/I2^2 dI2
402 ie.SetJacobian(Jpt.GetData());
403 const real_t I2 = ie.Get_I2();
404 Add(1. + 1./I2, ie.Get_dI1(), -ie.Get_I1()/(I2*I2), ie.Get_dI2(), P);
405}
406
408 const DenseMatrix &DS,
409 const real_t weight,
410 DenseMatrix &A) const
411{
412 // P = d(I1*(1 + 1/I2))
413 // = (1 + 1/I2) dI1 - I1/I2^2 dI2
414 //
415 // dP = (-1/I2^2) (dI1 x dI2) + (1 + 1/I2) ddI1 -
416 // (dI2 x d(I1/I2^2)) - I1/I2^2 ddI2
417 // = (-1/I2^2) (dI1 x dI2) + (1 + 1/I2) ddI1 +
418 // (-1/I2^2) (dI2 x [dI1 - 2 I1/I2 dI2]) - I1/I2^2 ddI2
419 // = (-1/I2^2) (dI1 x dI2 + dI2 x dI1) + (1 + 1/I2) ddI1 +
420 // (2 I1/I2^3) (dI2 x dI2) - I1/I2^2 ddI2
421 ie.SetJacobian(Jpt.GetData());
423 const real_t c1 = 1./ie.Get_I2();
424 const real_t c2 = weight*c1*c1;
425 const real_t c3 = ie.Get_I1()*c2;
426 ie.Assemble_ddI1(weight*(1. + c1), A.GetData());
427 ie.Assemble_ddI2(-c3, A.GetData());
428 ie.Assemble_TProd(-c2, ie.Get_dI1(), ie.Get_dI2(), A.GetData());
429 ie.Assemble_TProd(2*c1*c3, ie.Get_dI2(), A.GetData());
430}
431
433{
434 // mu_9 = det(J)*|J-J^{-t}|^2 = I1b * (I2b^2 + 1) - 4 * I2b
435 // = (I1 - 4)*I2b + I1b
436 ie.SetJacobian(Jpt.GetData());
437 return (ie.Get_I1() - 4.0)*ie.Get_I2b() + ie.Get_I1b();
438}
439
441{
442 // mu_9 = (I1 - 4)*I2b + I1b
443 // P = (I1 - 4)*dI2b + I2b*dI1 + dI1b
444 ie.SetJacobian(Jpt.GetData());
445 Add(ie.Get_I1() - 4.0, ie.Get_dI2b(), ie.Get_I2b(), ie.Get_dI1(), P);
446 P += ie.Get_dI1b();
447}
448
450 const DenseMatrix &DS,
451 const real_t weight,
452 DenseMatrix &A) const
453{
454 // P = (I1 - 4)*dI2b + I2b*dI1 + dI1b
455 // dP = dI2b x dI1 + (I1-4)*ddI2b + dI1 x dI2b + I2b*ddI1 + ddI1b
456 // = (dI1 x dI2b + dI2b x dI1) + (I1-4)*ddI2b + I2b*ddI1 + ddI1b
457 ie.SetJacobian(Jpt.GetData());
459 ie.Assemble_TProd(weight, ie.Get_dI1(), ie.Get_dI2b(), A.GetData());
460 ie.Assemble_ddI2b(weight*(ie.Get_I1()-4.0), A.GetData());
461 ie.Assemble_ddI1(weight*ie.Get_I2b(), A.GetData());
462 ie.Assemble_ddI1b(weight, A.GetData());
463}
464
466{
467 // mu_14 = |J - I|^2.
468 DenseMatrix Mat(Jpt);
469 Mat(0,0) -= 1.0;
470 Mat(1,1) -= 1.0;
471 return Mat.FNorm2();
472}
473
475{
476 // mu_14 = |J - I|^2 = I1[J-I].
477 DenseMatrix Mat(Jpt);
478 Mat(0,0) -= 1.0;
479 Mat(1,1) -= 1.0;
480
481 ie.SetJacobian(Mat.GetData());
482 return ie.Get_I1();
483}
484
486{
487 // P = dI1[J-I] d/dJ[J-I] = dI1[J-I].
488 DenseMatrix JptMinusId = Jpt;
489 for (int i = 0; i < Jpt.Size(); i++)
490 {
491 JptMinusId(i, i) -= 1.0;
492 }
493 ie.SetJacobian(JptMinusId.GetData());
494 P = ie.Get_dI1();
495}
496
498 const DenseMatrix &DS,
499 const real_t weight,
500 DenseMatrix &A) const
501{
502 // dP = ddI1[J-I].
503 DenseMatrix JptMinusId = Jpt;
504 for (int i = 0; i < Jpt.Size(); i++)
505 {
506 JptMinusId(i, i) -= 1.0;
507 }
508 ie.SetJacobian(JptMinusId.GetData());
510 ie.Assemble_ddI1(weight, A.GetData());
511}
512
514{
515 // mu_22 = (0.5*|J|^2 - det(J)) / (det(J) - tau0)
516 // = (0.5*I1 - I2b) / (I2b - tau0)
517 ie.SetJacobian(Jpt.GetData());
518 const real_t I2b = ie.Get_I2b();
519
520 real_t d = I2b - min_detT;
521 if (d < 0.0 && min_detT == 0.0)
522 {
523 // The mesh has been untangled, but it's still possible to get negative
524 // detJ in FD calculations, as they move the nodes around with some small
525 // increments and can produce negative determinants. Thus we put a small
526 // value in the denominator. Note that here I2b < 0.
527 d = - I2b * 0.1;
528 }
529
530 return (0.5*ie.Get_I1() - I2b) / d;
531}
532
534{
535 // mu_22 = (0.5*I1 - I2b) / (I2b - tau0)
536 // P = 1/(I2b - tau0)*(0.5*dI1 - dI2b) - (0.5*I1 - I2b)/(I2b - tau0)^2*dI2b
537 // = 0.5/(I2b - tau0)*dI1 + (tau0 - 0.5*I1)/(I2b - tau0)^2*dI2b
538 ie.SetJacobian(Jpt.GetData());
539 const real_t c1 = 1.0/(ie.Get_I2b() - min_detT);
540 Add(c1/2, ie.Get_dI1(), (min_detT - ie.Get_I1()/2)*c1*c1, ie.Get_dI2b(), P);
541}
542
544 const DenseMatrix &DS,
545 const real_t weight,
546 DenseMatrix &A) const
547{
548 // P = 0.5/(I2b - tau0)*dI1 + (tau0 - 0.5*I1)/(I2b - tau0)^2*dI2b
549 // dP = -0.5/(I2b - tau0)^2*(dI1 x dI2b) + 0.5/(I2b - tau0)*ddI1
550 // + (dI2b x dz) + z*ddI2b
551 //
552 // z = (tau0 - 0.5*I1)/(I2b - tau0)^2
553 // dz = -0.5/(I2b - tau0)^2*dI1 - 2*(tau0 - 0.5*I1)/(I2b - tau0)^3*dI2b
554 //
555 // dP = -0.5/(I2b - tau0)^2*(dI1 x dI2b + dI2b x dI1)
556 // -2*z/(I2b - tau0)*(dI2b x dI2b)
557 // +0.5/(I2b - tau0)*ddI1 + z*ddI2b
558 ie.SetJacobian(Jpt.GetData());
560 const real_t c1 = 1.0/(ie.Get_I2b() - min_detT);
561 const real_t c2 = weight*c1/2;
562 const real_t c3 = c1*c2;
563 const real_t c4 = (2*min_detT - ie.Get_I1())*c3; // weight*z
564 ie.Assemble_TProd(-c3, ie.Get_dI1(), ie.Get_dI2b(), A.GetData());
565 ie.Assemble_TProd(-2*c1*c4, ie.Get_dI2b(), A.GetData());
566 ie.Assemble_ddI1(c2, A.GetData());
567 ie.Assemble_ddI2b(c4, A.GetData());
568}
569
571{
572 // mu_50 = 0.5 |J^t J|^2 / det(J)^2 - 1.
573 DenseMatrix JtJ(2);
574 MultAAt(Jpt, JtJ);
575 JtJ.Transpose();
576 real_t det = Jpt.Det();
577
578 return 0.5 * JtJ.FNorm2()/(det*det) - 1.0;
579}
580
582{
583 // mu_50 = 0.5*|J^t J|^2/det(J)^2 - 1
584 // = 0.5*(l1^4 + l2^4)/(l1*l2)^2 - 1
585 // = 0.5*((l1/l2)^2 + (l2/l1)^2) - 1 = 0.5*(l1/l2 - l2/l1)^2
586 // = 0.5*(l1/l2 + l2/l1)^2 - 2 = 0.5*I1b^2 - 2.
587 ie.SetJacobian(Jpt.GetData());
588 const real_t I1b = ie.Get_I1b();
589 return 0.5*I1b*I1b - 2.0;
590}
591
593{
594 // mu_50 = 0.5*I1b^2 - 2
595 // P = I1b*dI1b
596 ie.SetJacobian(Jpt.GetData());
597 P.Set(ie.Get_I1b(), ie.Get_dI1b());
598}
599
601 const DenseMatrix &DS,
602 const real_t weight,
603 DenseMatrix &A) const
604{
605 // P = I1b*dI1b
606 // dP = dI1b x dI1b + I1b*ddI1b
607 ie.SetJacobian(Jpt.GetData());
609 ie.Assemble_TProd(weight, ie.Get_dI1b(), A.GetData());
610 ie.Assemble_ddI1b(weight*ie.Get_I1b(), A.GetData());
611}
612
614{
615 // mu_55 = (det(J) - 1)^2 = (I2b - 1)^2
616 ie.SetJacobian(Jpt.GetData());
617 const real_t c1 = ie.Get_I2b() - 1.0;
618 return c1*c1;
619}
620
622{
623 // mu_55 = (I2b - 1)^2
624 // P = 2*(I2b - 1)*dI2b
625 ie.SetJacobian(Jpt.GetData());
626 P.Set(2*(ie.Get_I2b() - 1.0), ie.Get_dI2b());
627}
628
630 const DenseMatrix &DS,
631 const real_t weight,
632 DenseMatrix &A) const
633{
634 // P = 2*(I2b - 1)*dI2b
635 // dP = 2*(dI2b x dI2b) + 2*(I2b - 1)*ddI2b
636 ie.SetJacobian(Jpt.GetData());
638 ie.Assemble_TProd(2*weight, ie.Get_dI2b(), A.GetData());
639 ie.Assemble_ddI2b(2*weight*(ie.Get_I2b() - 1.0), A.GetData());
640}
641
643{
644 // mu_56 = 0.5 (det(J) + 1 / det(J)) - 1.
645 const real_t d = Jpt.Det();
646 return 0.5 * (d + 1.0 / d) - 1.0;
647}
648
650{
651 // mu_56 = 0.5*(I2b + 1/I2b) - 1.
652 ie.SetJacobian(Jpt.GetData());
653 const real_t I2b = ie.Get_I2b();
654 return 0.5*(I2b + 1.0/I2b) - 1.0;
655}
656
658{
659 // mu_56 = 0.5*(I2b + 1/I2b) - 1.
660 // P = 0.5*(1 - 1/I2b^2)*dI2b.
661 ie.SetJacobian(Jpt.GetData());
662 P.Set(0.5 - 0.5/ie.Get_I2(), ie.Get_dI2b());
663}
664
666 const DenseMatrix &DS,
667 const real_t weight,
668 DenseMatrix &A) const
669{
670 // P = 0.5*(1 - 1/I2b^2)*dI2b.
671 // dP = (1/I2b^3)*(dI2b x dI2b) + (0.5 - 0.5/I2)*ddI2b.
672 ie.SetJacobian(Jpt.GetData());
674 ie.Assemble_TProd(weight/(ie.Get_I2()*ie.Get_I2b()),
675 ie.Get_dI2b(), A.GetData());
676 ie.Assemble_ddI2b(weight*(0.5 - 0.5/ie.Get_I2()), A.GetData());
677}
678
680{
681 // mu_58 = |J^t J|^2 / det(J)^2 - 2|J|^2 / det(J) + 2.
682 DenseMatrix JtJ(2);
683 MultAAt(Jpt, JtJ);
684 JtJ.Transpose();
685 real_t det = Jpt.Det();
686
687 return JtJ.FNorm2()/(det*det) - 2*Jpt.FNorm2()/det + 2.0;
688}
689
691{
692 // mu_58 = I1b*(I1b - 2)
693 ie.SetJacobian(Jpt.GetData());
694 const real_t I1b = ie.Get_I1b();
695 return I1b*(I1b - 2.0);
696}
697
699{
700 // mu_58 = I1b*(I1b - 2)
701 // P = (2*I1b - 2)*dI1b
702 ie.SetJacobian(Jpt.GetData());
703 P.Set(2*ie.Get_I1b() - 2.0, ie.Get_dI1b());
704}
705
707 const DenseMatrix &DS,
708 const real_t weight,
709 DenseMatrix &A) const
710{
711 // P = (2*I1b - 2)*dI1b
712 // dP = 2*(dI1b x dI1b) + (2*I1b - 2)*ddI1b
713 ie.SetJacobian(Jpt.GetData());
715 ie.Assemble_TProd(2*weight, ie.Get_dI1b(), A.GetData());
716 ie.Assemble_ddI1b(weight*(2*ie.Get_I1b() - 2.0), A.GetData());
717}
718
720{
721 // mu_77 = 0.5 (det(J)^2 + 1 / det(J)^2) - 1.
722 const real_t d = Jpt.Det();
723 return 0.5 * (d*d + 1.0/(d*d)) - 1.0;
724}
726{
727 // mu_77 = 0.5 (I2 + 1 / I2) - 1.0.
728 ie.SetJacobian(Jpt.GetData());
729 const real_t I2 = ie.Get_I2();
730 return 0.5*(I2 + 1.0/I2) - 1.0;
731}
732
734{
735 // mu_77 = 0.5 (I2 + 1 / I2) - 1.0.
736 // P = 1/2 (1 - 1/I2^2) dI2_dJ.
737 ie.SetJacobian(Jpt.GetData());
738 const real_t I2 = ie.Get_I2();
739 P.Set(0.5 * (1.0 - 1.0 / (I2 * I2)), ie.Get_dI2());
740}
741
743 const DenseMatrix &DS,
744 const real_t weight,
745 DenseMatrix &A) const
746{
747 ie.SetJacobian(Jpt.GetData());
749 const real_t I2 = ie.Get_I2(), I2inv_sq = 1.0 / (I2 * I2);
750 ie.Assemble_ddI2(weight*0.5*(1.0 - I2inv_sq), A.GetData());
751 ie.Assemble_TProd(weight * I2inv_sq / I2, ie.Get_dI2(), A.GetData());
752}
753
754// mu_85 = |T-T'|^2, where T'= |T|*I/sqrt(2)
756{
757 MFEM_VERIFY(Jtr != NULL,
758 "Requires a target Jacobian, use SetTargetJacobian().");
759
760 DenseMatrix Id(2,2);
761 DenseMatrix Mat(2,2);
762 Mat = Jpt;
763
764 Id(0,0) = 1; Id(0,1) = 0;
765 Id(1,0) = 0; Id(1,1) = 1;
766 Id *= Mat.FNorm()/pow(2,0.5);
767
768 Mat.Add(-1.,Id);
769 return Mat.FNorm2();
770}
771
772// mu_98 = 1/(tau)|T-I|^2
774{
775 MFEM_VERIFY(Jtr != NULL,
776 "Requires a target Jacobian, use SetTargetJacobian().");
777
778 DenseMatrix Id(2,2);
779
780 Id(0,0) = 1; Id(0,1) = 0;
781 Id(1,0) = 0; Id(1,1) = 1;
782
783 DenseMatrix Mat(2,2);
784 Mat = Jpt;
785 Mat.Add(-1,Id);
786 return Mat.FNorm2()/Jtr->Det();
787}
788
790{
791 // mu_211 = (det(J) - 1)^2 - det(J) + (det(J)^2 + eps)^{1/2}
792 // = (I2b - 1)^2 - I2b + sqrt(I2b^2 + eps)
793 ie.SetJacobian(Jpt.GetData());
794 const real_t I2b = ie.Get_I2b();
795 return (I2b - 1.0)*(I2b - 1.0) - I2b + std::sqrt(I2b*I2b + eps);
796}
797
799{
800 MFEM_ABORT("Metric not implemented yet. Use metric mu_55 instead.");
801}
802
804 const DenseMatrix &DS,
805 const real_t weight,
806 DenseMatrix &A) const
807{
808 MFEM_ABORT("Metric not implemented yet. Use metric mu_55 instead.");
809}
810
812{
813 // mu_252 = 0.5*(det(J) - 1)^2 / (det(J) - tau0).
814 ie.SetJacobian(Jpt.GetData());
815 const real_t I2b = ie.Get_I2b();
816 return 0.5*(I2b - 1.0)*(I2b - 1.0)/(I2b - tau0);
817}
818
820{
821 // mu_252 = 0.5*(det(J) - 1)^2 / (det(J) - tau0)
822 // P = (c - 0.5*c*c ) * dI2b
823 //
824 // c = (I2b - 1)/(I2b - tau0), see TMOP_Metric_352 for details
825 ie.SetJacobian(Jpt.GetData());
826 const real_t I2b = ie.Get_I2b();
827 const real_t c = (I2b - 1.0)/(I2b - tau0);
828 P.Set(c - 0.5*c*c, ie.Get_dI2b());
829}
830
832 const DenseMatrix &DS,
833 const real_t weight,
834 DenseMatrix &A) const
835{
836 // c = (I2b - 1)/(I2b - tau0), see TMOP_Metric_352 for details
837 //
838 // P = (c - 0.5*c*c ) * dI2b
839 // dP = (1 - c)^2/(I2b - tau0)*(dI2b x dI2b) + (c - 0.5*c*c)*ddI2b
840 ie.SetJacobian(Jpt.GetData());
842 const real_t I2b = ie.Get_I2b();
843 const real_t c0 = 1.0/(I2b - tau0);
844 const real_t c = c0*(I2b - 1.0);
845 ie.Assemble_TProd(weight*c0*(1.0 - c)*(1.0 - c), ie.Get_dI2b(), A.GetData());
846 ie.Assemble_ddI2b(weight*(c - 0.5*c*c), A.GetData());
847}
848
850{
851 // mu_301 = 1/3 |J| |J^-1| - 1.
852 ie.SetJacobian(Jpt.GetData());
853 DenseMatrix inv(3);
854 CalcInverse(Jpt, inv);
855 return Jpt.FNorm() * inv.FNorm() / 3.0 - 1.0;
856}
857
859{
860 // mu_301 = 1/3 sqrt(I1b * I2b) - 1
861 ie.SetJacobian(Jpt.GetData());
862 return std::sqrt(ie.Get_I1b()*ie.Get_I2b())/3. - 1.;
863}
864
866{
867 // W = (1/3)*sqrt(I1b*I2b) - 1
868 // dW = (1/6)/sqrt(I1b*I2b)*[I2b*dI1b + I1b*dI2b]
869 ie.SetJacobian(Jpt.GetData());
870 const real_t a = 1./(6.*std::sqrt(ie.Get_I1b()*ie.Get_I2b()));
871 Add(a*ie.Get_I2b(), ie.Get_dI1b(), a*ie.Get_I1b(), ie.Get_dI2b(), P);
872}
873
875 const DenseMatrix &DS,
876 const real_t weight,
877 DenseMatrix &A) const
878{
879 // dW = (1/6)/sqrt(I1b*I2b)*[I2b*dI1b + I1b*dI2b]
880 // dW = (1/6)*[z2*dI1b + z1*dI2b], z1 = sqrt(I1b/I2b), z2 = sqrt(I2b/I1b)
881 // ddW = (1/6)*[dI1b x dz2 + z2*ddI1b + dI2b x dz1 + z1*ddI2b]
882 //
883 // dz1 = (1/2)*sqrt(I2b/I1b) [ (1/I2b)*dI1b - (I1b/(I2b*I2b))*dI2b ]
884 // = (1/2)/sqrt(I1b*I2b) [ dI1b - (I1b/I2b)*dI2b ]
885 // dz2 = (1/2)/sqrt(I1b*I2b) [ dI2b - (I2b/I1b)*dI1b ]
886 //
887 // dI1b x dz2 + dI2b x dz1 =
888 // (1/2)/sqrt(I1b*I2b) dI1b x [ dI2b - (I2b/I1b)*dI1b ] +
889 // (1/2)/sqrt(I1b*I2b) dI2b x [ dI1b - (I1b/I2b)*dI2b ] =
890 // (1/2)/sqrt(I1b*I2b) [sqrt(I1b/I2b)*dI2b - sqrt(I2b/I1b)*dI1b] x
891 // [sqrt(I2b/I1b)*dI1b - sqrt(I1b/I2b)*dI2b] =
892 // (1/2)*(I1b*I2b)^{-3/2} (I1b*dI2b - I2b*dI1b) x (I2b*dI1b - I1b*dI2b)
893 // and the last two parentheses are the same up to a sign.
894 //
895 // z1 = I1b/sqrt(I1b*I2b), z2 = I2b/sqrt(I1b*I2b)
896
897 ie.SetJacobian(Jpt.GetData());
899 real_t X_data[9];
900 DenseMatrix X(X_data, 3, 3);
901 Add(- ie.Get_I2b(), ie.Get_dI1b(), ie.Get_I1b(), ie.Get_dI2b(), X);
902 const real_t I1b_I2b = ie.Get_I1b()*ie.Get_I2b();
903 const real_t a = weight/(6*std::sqrt(I1b_I2b));
906 ie.Assemble_TProd(-a/(2*I1b_I2b), X_data, A.GetData());
907}
908
910{
911 // mu_301 = |J|^2 |J^{-1}|^2 / 9 - 1.
912 ie.SetJacobian(Jpt.GetData());
913 DenseMatrix inv(3);
914 CalcInverse(Jpt, inv);
915 return Jpt.FNorm2() * inv.FNorm2() / 9.0 - 1.0;
916}
917
919{
920 // mu_2 = |J|^2 |J^{-1}|^2 / 9 - 1
921 // = (l1^2 + l2^2 + l3^3)*(l1^{-2} + l2^{-2} + l3^{-2}) / 9 - 1
922 // = I1*(l2^2*l3^2 + l1^2*l3^2 + l1^2*l2^2)/l1^2/l2^2/l3^2/9 - 1
923 // = I1*I2/det(J)^2/9 - 1 = I1b*I2b/9-1
924 ie.SetJacobian(Jpt.GetData());
925 return ie.Get_I1b()*ie.Get_I2b()/9. - 1.;
926}
927
929{
930 // mu_2 = I1b*I2b/9-1
931 // P = (I1b/9)*dI2b + (I2b/9)*dI1b
932 ie.SetJacobian(Jpt.GetData());
933 Add(ie.Get_I1b()/9, ie.Get_dI2b(), ie.Get_I2b()/9, ie.Get_dI1b(), P);
934}
935
937 const DenseMatrix &DS,
938 const real_t weight,
939 DenseMatrix &A) const
940{
941 // P = (I1b/9)*dI2b + (I2b/9)*dI1b
942 // dP = (dI2b x dI1b)/9 + (I1b/9)*ddI2b + (dI1b x dI2b)/9 + (I2b/9)*ddI1b
943 // = (dI2b x dI1b + dI1b x dI2b)/9 + (I1b/9)*ddI2b + (I2b/9)*ddI1b
944 ie.SetJacobian(Jpt.GetData());
946 const real_t c1 = weight/9;
950}
951
953{
954 // mu_303 = |J|^2 / 3 / det(J)^(2/3) - 1.
955 ie.SetJacobian(Jpt.GetData());
956 return Jpt.FNorm2() / 3.0 / pow(Jpt.Det(), 2.0 / 3.0) - 1.0;
957}
958
960{
961 // mu_303 = |J|^2 / 3 / det(J)^(2/3) - 1 = I1b/3 - 1.
962 ie.SetJacobian(Jpt.GetData());
963 return ie.Get_I1b()/3.0 - 1.0;
964}
965
967{
968 // mu_304 = I1b/3 - 1.
969 // P = dI1b/3.
970 ie.SetJacobian(Jpt.GetData());
971 P.Set(1./3., ie.Get_dI1b());
972}
973
975 const DenseMatrix &DS,
976 const real_t weight,
977 DenseMatrix &A) const
978{
979 // P = dI1b/3.
980 // dP = ddI1b/3.
981 ie.SetJacobian(Jpt.GetData());
983 ie.Assemble_ddI1b(weight/3., A.GetData());
984}
985
987{
988 // mu_304 = |J|^3 / 3^(3/2) / det(J) - 1
989 const real_t fnorm = Jpt.FNorm();
990 return fnorm * fnorm * fnorm / pow(3.0, 1.5) / Jpt.Det() - 1.0;
991}
992
994{
995 // mu_304 = (I1b/3)^3/2 - 1.
996 ie.SetJacobian(Jpt.GetData());
997 return pow(ie.Get_I1b()/3.0, 1.5) - 1.0;
998}
999
1001{
1002 // mu_304 = (I1b/3)^3/2 - 1.
1003 // P = 3/2 * (I1b/3)^1/2 * dI1b / 3 = 1/2 * (I1b/3)^1/2 * dI1b.
1004 ie.SetJacobian(Jpt.GetData());
1005 P.Set(0.5 * sqrt(ie.Get_I1b()/3.0), ie.Get_dI1b());
1006}
1007
1009 const real_t weight, DenseMatrix &A) const
1010{
1011 // P = 1/2 * (I1b/3)^1/2 * dI1b.
1012 // dP = 1/12 * (I1b/3)^(-1/2) * (dI1b x dI1b) + 1/2 * (I1b/3)^1/2 * ddI1b.
1013 ie.SetJacobian(Jpt.GetData());
1015 ie.Assemble_TProd(weight / 12.0 / sqrt(ie.Get_I1b()/3.0),
1016 ie.Get_dI1b(), A.GetData());
1017 ie.Assemble_ddI1b(weight / 2.0 * sqrt(ie.Get_I1b()/3.0), A.GetData());
1018}
1019
1021{
1022 // mu_311 = (det(J) - 1)^2 - det(J) + (det(J)^2 + eps)^{1/2}
1023 // = (I3b - 1)^2 - I3b + sqrt(I3b^2 + eps)
1024 ie.SetJacobian(Jpt.GetData());
1025 const real_t I3b = ie.Get_I3b();
1026 return (I3b - 1.0)*(I3b - 1.0) - I3b + std::sqrt(I3b*I3b + eps);
1027}
1028
1030{
1031 ie.SetJacobian(Jpt.GetData());
1032 const real_t I3b = ie.Get_I3b();
1033 const real_t c = 2*I3b-3+(I3b)/(std::pow((I3b*I3b+eps),0.5));
1034 P.Set(c, ie.Get_dI3b());
1035}
1036
1038 const DenseMatrix &DS,
1039 const real_t weight,
1040 DenseMatrix &A) const
1041{
1042 ie.SetJacobian(Jpt.GetData());
1044 const real_t I3b = ie.Get_I3b();
1045 const real_t c0 = I3b*I3b+eps;
1046 const real_t c1 = 2 + 1/(pow(c0,0.5)) - I3b*I3b/(pow(c0,1.5));
1047 const real_t c2 = 2*I3b - 3 + I3b/(pow(c0,0.5));
1048 ie.Assemble_TProd(weight*c1, ie.Get_dI3b(), A.GetData());
1049 ie.Assemble_ddI3b(c2*weight, A.GetData());
1050}
1051
1053{
1054 ie.SetJacobian(Jpt.GetData());
1055
1056 const real_t I3b = ie.Get_I3b();
1057 real_t d = I3b - min_detT;
1058 if (d < 0.0 && min_detT == 0.0)
1059 {
1060 // The mesh has been untangled, but it's still possible to get negative
1061 // detJ in FD calculations, as they move the nodes around with some small
1062 // increments and can produce negative determinants. Thus we put a small
1063 // value in the denominator. Note that here I3b < 0.
1064 d = - I3b * 0.1;
1065 }
1066
1067 const real_t c = std::pow(d, -2.0/3.0);
1068
1069 return ie.Get_I1() * c / 3.0;
1070}
1071
1073{
1074 MFEM_ABORT("Metric not implemented yet.");
1075}
1076
1078 const DenseMatrix &DS,
1079 const real_t weight,
1080 DenseMatrix &A) const
1081{
1082 MFEM_ABORT("Metric not implemented yet.");
1083}
1084
1086{
1087 // mu_315 = mu_15_3D = (det(J) - 1)^2
1088 ie.SetJacobian(Jpt.GetData());
1089 const real_t c1 = ie.Get_I3b() - 1.0;
1090 return c1*c1;
1091}
1092
1094{
1095 // mu_315 = (I3b - 1)^2
1096 // P = 2*(I3b - 1)*dI3b
1097 ie.SetJacobian(Jpt.GetData());
1098 P.Set(2*(ie.Get_I3b() - 1.0), ie.Get_dI3b());
1099}
1100
1102 const DenseMatrix &DS,
1103 const real_t weight,
1104 DenseMatrix &A) const
1105{
1106 // P = 2*(I3b - 1)*dI3b
1107 // dP = 2*(dI3b x dI3b) + 2*(I3b - 1)*ddI3b
1108 ie.SetJacobian(Jpt.GetData());
1110 ie.Assemble_TProd(2*weight, ie.Get_dI3b(), A.GetData());
1111 ie.Assemble_ddI3b(2*weight*(ie.Get_I3b() - 1.0), A.GetData());
1112}
1113
1115{
1116 // mu_316 = 0.5 (det(J) + 1/det(J)) - 1.
1117 return 0.5 * (Jpt.Det() + 1.0 / Jpt.Det()) - 1.0;
1118}
1119
1121{
1122 // mu_316 = mu_16_3D = 0.5*(I3b + 1/I3b) - 1
1123 ie.SetJacobian(Jpt.GetData());
1124 const real_t I3b = ie.Get_I3b();
1125 return 0.5*(I3b + 1.0/I3b) - 1.0;
1126}
1127
1129{
1130 // mu_316 = mu_16_3D = 0.5*(I3b + 1/I3b) - 1
1131 // P = 0.5*(1 - 1/I3b^2)*dI3b = (0.5 - 0.5/I3)*dI3b
1132 ie.SetJacobian(Jpt.GetData());
1133 P.Set(0.5 - 0.5/ie.Get_I3(), ie.Get_dI3b());
1134}
1135
1137 const DenseMatrix &DS,
1138 const real_t weight,
1139 DenseMatrix &A) const
1140{
1141 // P = 0.5*(1 - 1/I3b^2)*dI3b = (0.5 - 0.5/I3)*dI3b
1142 // dP = (1/I3b^3)*(dI3b x dI3b) + (0.5 - 0.5/I3)*ddI3b
1143 ie.SetJacobian(Jpt.GetData());
1145 ie.Assemble_TProd(weight/(ie.Get_I3()*ie.Get_I3b()),
1146 ie.Get_dI3b(), A.GetData());
1147 ie.Assemble_ddI3b(weight*(0.5 - 0.5/ie.Get_I3()), A.GetData());
1148}
1149
1151{
1152 // mu_318 = 0.5 (det(J)^2 + 1/det(J)^2) - 1.
1153 real_t d = Jpt.Det();
1154 return 0.5 * (d*d + 1.0 / (d*d)) - 1.0;
1155}
1156
1158{
1159 // mu_318 = mu_77_3D = 0.5 * (I3 + 1/I3) - 1.
1160 ie.SetJacobian(Jpt.GetData());
1161 const real_t I3 = ie.Get_I3();
1162 return 0.5*(I3 + 1.0/I3) - 1.0;
1163}
1164
1166{
1167 // mu_318 = mu_77_3D = 0.5*(I3 + 1/I3) - 1.
1168 // P = 0.5*(1 - 1/I3^2)*dI3 = (0.5 - 0.5/I3^2)*dI3.
1169 ie.SetJacobian(Jpt.GetData());
1170 P.Set(0.5 - 0.5/(ie.Get_I3()*ie.Get_I3()), ie.Get_dI3());
1171}
1172
1174 const DenseMatrix &DS,
1175 const real_t weight,
1176 DenseMatrix &A) const
1177{
1178 // P = (0.5 - 0.5/I3^2)*dI3.
1179 // dP = (1/I3^3)*(dI3 x dI3) +(0.5 - 0.5/I3^2)*ddI3
1180 ie.SetJacobian(Jpt.GetData());
1182 const real_t i3 = ie.Get_I3();
1183 ie.Assemble_TProd(weight/(i3 * i3 * i3), ie.Get_dI3(), A.GetData());
1184 ie.Assemble_ddI3(weight*(0.5 - 0.5 / (i3 * i3)), A.GetData());
1185}
1186
1188{
1189 // mu_321 = |J - J^-t|^2.
1190 ie.SetJacobian(Jpt.GetData());
1191 DenseMatrix invt(3);
1192 CalcInverseTranspose(Jpt, invt);
1193 invt.Add(-1.0, Jpt);
1194 return invt.FNorm2();
1195}
1196
1198{
1199 // mu_321 = mu_21_3D = |J - J^{-t}|^2
1200 // = |J|^2 + |J^{-1}|^2 - 6
1201 // = |J|^2 + (l1^{-2} + l2^{-2} + l3^{-2}) - 6
1202 // = |J|^2 + (l2^2*l3^2 + l1^2*l3^2 + l1^2*l2^2)/det(J)^2 - 6
1203 // = I1 + I2/I3b^2 - 6 = I1 + I2/I3 - 6
1204 ie.SetJacobian(Jpt.GetData());
1205 return ie.Get_I1() + ie.Get_I2()/ie.Get_I3() - 6.0;
1206}
1207
1209{
1210 // mu_321 = I1 + I2/I3b^2 - 6 = I1 + I2/I3 - 6
1211 // P = dI1 + (1/I3)*dI2 - (2*I2/I3b^3)*dI3b
1212 ie.SetJacobian(Jpt.GetData());
1213 const real_t I3 = ie.Get_I3();
1214 Add(1.0/I3, ie.Get_dI2(),
1215 -2*ie.Get_I2()/(I3*ie.Get_I3b()), ie.Get_dI3b(), P);
1216 P += ie.Get_dI1();
1217}
1218
1220 const DenseMatrix &DS,
1221 const real_t weight,
1222 DenseMatrix &A) const
1223{
1224 // P = dI1 + (1/I3)*dI2 - (2*I2/I3b^3)*dI3b
1225 // dP = ddI1 + (-2/I3b^3)*(dI2 x dI3b) + (1/I3)*ddI2 + (dI3b x dz) + z*ddI3b
1226 //
1227 // z = -2*I2/I3b^3
1228 // dz = (-2/I3b^3)*dI2 + (2*I2)*(3/I3b^4)*dI3b
1229 //
1230 // dP = ddI1 + (-2/I3b^3)*(dI2 x dI3b + dI3b x dI2) + (1/I3)*ddI2
1231 // + (6*I2/I3b^4)*(dI3b x dI3b) + (-2*I2/I3b^3)*ddI3b
1232 ie.SetJacobian(Jpt.GetData());
1234 const real_t c0 = 1.0/ie.Get_I3b();
1235 const real_t c1 = weight*c0*c0;
1236 const real_t c2 = -2*c0*c1;
1237 const real_t c3 = c2*ie.Get_I2();
1238 ie.Assemble_ddI1(weight, A.GetData());
1239 ie.Assemble_ddI2(c1, A.GetData());
1240 ie.Assemble_ddI3b(c3, A.GetData());
1241 ie.Assemble_TProd(c2, ie.Get_dI2(), ie.Get_dI3b(), A.GetData());
1242 ie.Assemble_TProd(-3*c0*c3, ie.Get_dI3b(), A.GetData());
1243}
1244
1246{
1247 // mu_322 = 1 / (6 det(J)) |J - adj(J)^t|^2
1248 DenseMatrix adj_J_t(3);
1249 CalcAdjugateTranspose(Jpt, adj_J_t);
1250 adj_J_t *= -1.0;
1251 adj_J_t.Add(1.0, Jpt);
1252 return 1.0 / 6.0 / Jpt.Det() * adj_J_t.FNorm2();
1253}
1254
1256{
1257 // mu_322 = 1 / (6 det(J)) |J - adj(J)^t|^2
1258 // = 1 / (6 det(J)) |J|^2 + 1/6 det(J) |J^{-1}|^2 - 1
1259 // = I1b / (I3b^-1/3) / 6 + I2b (I3b^1/3) / 6 - 1
1260 ie.SetJacobian(Jpt.GetData());
1261
1262 return ie.Get_I1b() / pow(ie.Get_I3b(), 1.0/3.0) / 6.0 +
1263 ie.Get_I2b() * pow(ie.Get_I3b(), 1.0/3.0) / 6.0 - 1.0;
1264}
1265
1267{
1268 // mu_322 = I1b (I3b^-1/3) / 6 + I2b (I3b^1/3) / 6 - 1
1269 // P = 1/6 (I3b^-1/3) dI1b - 1/18 I1b (I3b^-4/3) dI3b
1270 // + 1/6 (I3b^1/3) dI2b + 1/18 I2b (I3b^-2/3) dI3b
1271 ie.SetJacobian(Jpt.GetData());
1272 P.Set(1.0/6.0 * pow(ie.Get_I3b(), -1.0/3.0),
1273 ie.Get_dI1b());
1274 P.Add(-1.0/18.0 * ie.Get_I1b() * pow(ie.Get_I3b(), -4.0/3.0),
1275 ie.Get_dI3b());
1276 P.Add(1.0/6.0 * pow(ie.Get_I3b(), 1.0/3.0),
1277 ie.Get_dI2b());
1278 P.Add(1.0/18.0 * ie.Get_I2b() * pow(ie.Get_I3b(), -2.0/3.0),
1279 ie.Get_dI3b());
1280}
1281
1283 const real_t weight, DenseMatrix &A) const
1284{
1285 // P = 1/6 (I3b^-1/3) dI1b - 1/18 I1b (I3b^-4/3) dI3b
1286 // + 1/6 (I3b^1/3) dI2b + 1/18 I2b (I3b^-2/3) dI3b
1287 // dP = 1/6 (I3b^-1/3) ddI1b - 1/18 (I3b^-4/3) (dI1b x dI3b)
1288 // - 1/18 I1b (I3b^-4/3) ddI3b
1289 // - 1/18 (I3b^-4/3) (dI3b x dI1b)
1290 // + 2/27 I1b (I3b^-7/3) (dI3b x dI3b)
1291 // + 1/6 (I3b^1/3) ddI2b + 1/18 (I3b^-2/3) (dI2b x dI3b)
1292 // + 1/18 I2b (I3b^-2/3) ddI3b
1293 // + 1/18 (I3b^-2/3) (dI3b x dI2b)
1294 // - 1/27 I2b (I3b^-5/3) (dI3b x dI3b)
1295 ie.SetJacobian(Jpt.GetData());
1297 const real_t p13 = weight * pow(ie.Get_I3b(), 1.0/3.0),
1298 m13 = weight * pow(ie.Get_I3b(), -1.0/3.0),
1299 m23 = weight * pow(ie.Get_I3b(), -2.0/3.0),
1300 m43 = weight * pow(ie.Get_I3b(), -4.0/3.0),
1301 m53 = weight * pow(ie.Get_I3b(), -5.0/3.0),
1302 m73 = weight * pow(ie.Get_I3b(), -7.0/3.0);
1303 ie.Assemble_ddI1b(1.0/6.0 * m13, A.GetData());
1304 // Combines - 1/18 (I3b^-4/3) (dI1b x dI3b) - 1/18 (I3b^-4/3) (dI3b x dI1b).
1305 ie.Assemble_TProd(-1.0/18.0 * m43,
1306 ie.Get_dI1b(), ie.Get_dI3b(), A.GetData());
1307 ie.Assemble_ddI3b(-1.0/18.0 * ie.Get_I1b() * m43, A.GetData());
1308 ie.Assemble_TProd(2.0/27.0 * ie.Get_I1b() * m73,
1309 ie.Get_dI3b(), A.GetData());
1310 ie.Assemble_ddI2b(1.0/6.0 * p13, A.GetData());
1311 // Combines + 1/18 (I3b^-2/3) (dI2b x dI3b) + 1/18 (I3b^-2/3) (dI3b x dI2b).
1312 ie.Assemble_TProd(1.0/18.0 * m23,
1313 ie.Get_dI2b(), ie.Get_dI3b(), A.GetData());
1314 ie.Assemble_ddI3b(1.0/18.0 * ie.Get_I2b() * m23, A.GetData());
1315 ie.Assemble_TProd(-1.0/27.0 * ie.Get_I2b() * m53,
1316 ie.Get_dI3b(), A.GetData());
1317}
1318
1320{
1321 // mu_323 = |J|^3 - 3 sqrt(3) ln(det(J)) - 3 sqrt(3).
1322 real_t fnorm = Jpt.FNorm();
1323 return fnorm * fnorm * fnorm - 3.0 * sqrt(3.0) * (log(Jpt.Det()) + 1.0);
1324}
1325
1327{
1328 // mu_323 = I1^3/2 - 3 sqrt(3) ln(I3b) - 3 sqrt(3).
1329 ie.SetJacobian(Jpt.GetData());
1330 return pow(ie.Get_I1(), 1.5) - 3.0 * sqrt(3.0) * (log(ie.Get_I3b()) + 1.0);
1331}
1332
1334{
1335 // mu_323 = I1^3/2 - 3 sqrt(3) ln(I3b) - 3 sqrt(3).
1336 // P = 3/2 (I1^1/2) dI1 - 3 sqrt(3) (I3b^-1) dI3b.
1337 ie.SetJacobian(Jpt.GetData());
1338 P.Set(1.5 * sqrt(ie.Get_I1()), ie.Get_dI1());
1339 P.Add(- 3.0 * sqrt(3.0) / ie.Get_I3b(), ie.Get_dI3b());
1340}
1341
1343 const real_t weight, DenseMatrix &A) const
1344{
1345 // P = 3/2 (I1^1/2) dI1 - 3 sqrt(3) (I3b^-1) dI3b
1346 // dP = 3/2 (I1^1/2) ddI1 + 3/4 (I1^-1/2) (dI1 x dI1)
1347 // - 3 sqrt(3) (I3b^-1) ddI3b + 3 sqrt(3) (I3b^-2) (dI3b x dI3b)
1348 ie.SetJacobian(Jpt.GetData());
1350 ie.Assemble_ddI1(weight * 1.5 * sqrt(ie.Get_I1()), A.GetData());
1351 ie.Assemble_TProd(weight * 0.75 / sqrt(ie.Get_I1()),
1352 ie.Get_dI1(), A.GetData());
1353 ie.Assemble_ddI3b(- weight * 3.0 * sqrt(3.0) / ie.Get_I3b(), A.GetData());
1354 ie.Assemble_TProd(weight * 3.0 * sqrt(3.0) / ie.Get_I3b() / ie.Get_I3b(),
1355 ie.Get_dI3b(), A.GetData());
1356}
1357
1359{
1360 // mu_352 = 0.5*(det(J) - 1)^2 / (det(J) - tau0)
1361 ie.SetJacobian(Jpt.GetData());
1362 const real_t I3b = ie.Get_I3b();
1363 return 0.5*(I3b - 1.0)*(I3b - 1.0)/(I3b - tau0);
1364}
1365
1367{
1368 // mu_352 = 0.5*(det(J) - 1)^2 / (det(J) - tau0)
1369 // P = (I3b - 1)/(I3b - tau0)*dI3b + 0.5*(I3b - 1)^2*(-1/(I3b - tau0)^2)*dI3b
1370 // = [ (I3b - 1)/(I3b - tau0) - 0.5*(I3b - 1)^2/(I3b - tau0)^2 ] * dI3b
1371 // = (c - 0.5*c*c) * dI3b
1372 ie.SetJacobian(Jpt.GetData());
1373 const real_t I3b = ie.Get_I3b();
1374 const real_t c = (I3b - 1.0)/(I3b - tau0);
1375 P.Set(c - 0.5*c*c, ie.Get_dI3b());
1376}
1377
1379 const DenseMatrix &DS,
1380 const real_t weight,
1381 DenseMatrix &A) const
1382{
1383 // c = (I3b - 1)/(I3b - tau0)
1384 //
1385 // P = (c - 0.5*c*c) * dI3b
1386 // dP = (1 - c)*(dI3b x dc) + (c - 0.5*c*c)*ddI3b
1387 //
1388 // dc = 1/(I3b - tau0)*dI3b - (I3b - 1)/(I3b - tau)^2*dI3b =
1389 // = (1 - c)/(I3b - tau0)*dI3b
1390 //
1391 // dP = (1 - c)^2/(I3b - tau0)*(dI3b x dI3b) + (c - 0.5*c*c)*ddI3b
1392 ie.SetJacobian(Jpt.GetData());
1394 const real_t I3b = ie.Get_I3b();
1395 const real_t c0 = 1.0/(I3b - tau0);
1396 const real_t c = c0*(I3b - 1.0);
1397 ie.Assemble_TProd(weight*c0*(1.0 - c)*(1.0 - c), ie.Get_dI3b(), A.GetData());
1398 ie.Assemble_ddI3b(weight*(c - 0.5*c*c), A.GetData());
1399}
1400
1401
1402
1403
1405{
1406 // mu_360 = |J|^3 / 3^(3/2) - det(J)
1407 const real_t fnorm = Jpt.FNorm();
1408 return fnorm * fnorm * fnorm / pow(3.0, 1.5) - Jpt.Det();
1409}
1410
1412{
1413 // mu_360 = (I1/3)^(3/2) - I3b.
1414 ie.SetJacobian(Jpt.GetData());
1415 return pow(ie.Get_I1()/3.0, 1.5) - ie.Get_I3b();
1416}
1417
1419{
1420 // mu_360 = (I1/3)^(3/2) - I3b.
1421 // P = 3/2 * (I1/3)^1/2 * dI1 / 3 - dI3b
1422 // = 1/2 * (I1/3)^1/2 * dI1 - dI3b.
1423 ie.SetJacobian(Jpt.GetData());
1424 Add(0.5 * sqrt(ie.Get_I1()/3.0), ie.Get_dI1(), -1.0, ie.Get_dI3b(), P);
1425}
1426
1428 const real_t weight, DenseMatrix &A) const
1429{
1430 // P = 1/2 * (I1/3)^1/2 * dI1 - dI3b.
1431 // dP = 1/12 * (I1/3)^(-1/2) * (dI1 x dI1) + 1/2 * (I1/3)^1/2 * ddI1 - ddI3b
1432 ie.SetJacobian(Jpt.GetData());
1434 ie.Assemble_TProd(weight / 12.0 / sqrt(ie.Get_I1()/3.0),
1435 ie.Get_dI1(), A.GetData());
1436 ie.Assemble_ddI1(weight / 2.0 * sqrt(ie.Get_I1()/3.0), A.GetData());
1437 ie.Assemble_ddI3b(-weight, A.GetData());
1438}
1439
1441{
1442 MFEM_VERIFY(Jtr != NULL,
1443 "Requires a target Jacobian, use SetTargetJacobian().");
1444
1445 int dim = Jpt.Size();
1446
1447 DenseMatrix Jpr(dim, dim);
1448 Mult(Jpt, *Jtr, Jpr);
1449
1450 real_t alpha = Jpr.Det(),
1451 omega = Jtr->Det();
1452
1453 DenseMatrix AdjAt(dim), WtW(dim), WRK(dim), Jtrt(dim);
1454 CalcAdjugateTranspose(Jpr, AdjAt);
1455 Jtrt.Transpose(*Jtr);
1456 MultAAt(Jtrt, WtW);
1457 WtW *= 1./omega;
1458 Mult(AdjAt, WtW, WRK);
1459
1460 WRK -= Jpr;
1461 WRK *= -1.;
1462
1463 return (0.25/alpha)*WRK.FNorm2();
1464}
1465
1467{
1468 MFEM_VERIFY(Jtr != NULL,
1469 "Requires a target Jacobian, use SetTargetJacobian().");
1470
1471 int dim = Jpt.Size();
1472
1473 DenseMatrix Jpr(dim, dim);
1474 Mult(Jpt, *Jtr, Jpr);
1475
1476 real_t sqalpha = pow(Jpr.Det(), 0.5),
1477 sqomega = pow(Jtr->Det(), 0.5);
1478
1479 return 0.5*pow(sqalpha/sqomega - sqomega/sqalpha, 2.);
1480}
1481
1483{
1484 MFEM_VERIFY(Jtr != NULL,
1485 "Requires a target Jacobian, use SetTargetJacobian().");
1486
1487 int dim = Jpt.Size();
1488
1489 DenseMatrix Jpr(dim, dim);
1490 Mult(Jpt, *Jtr, Jpr); // T*W = A
1491
1492 real_t alpha = Jpr.Det(); // det(A)
1493 Jpr -= *Jtr; // A-W
1494
1495 return (1./alpha)*(Jpr.FNorm2()); //(1/alpha)*(|A-W|^2)
1496}
1497
1499{
1500 MFEM_VERIFY(Jtr != NULL,
1501 "Requires a target Jacobian, use SetTargetJacobian().");
1502
1503 int dim = Jpt.Size();
1504
1505 DenseMatrix Jpr(dim, dim);
1506 Mult(Jpt, *Jtr, Jpr);
1507
1508 real_t alpha = Jpr.Det(),
1509 aw = Jpr.FNorm()/Jtr->FNorm();
1510
1511 DenseMatrix W = *Jtr;
1512 W *= aw;
1513 Jpr -= W;
1514
1515 return (0.5/alpha)*Jpr.FNorm2();
1516}
1517
1518
1520{
1521 MFEM_VERIFY(nodes, "Nodes are not given!");
1522 MFEM_ASSERT(avg_volume == 0.0, "The average volume is already computed!");
1523
1524 Mesh *mesh = nodes->FESpace()->GetMesh();
1525 const int NE = mesh->GetNE();
1527 real_t volume = 0.0;
1528
1529 for (int i = 0; i < NE; i++)
1530 {
1531 mesh->GetElementTransformation(i, *nodes, &Tr);
1532 const IntegrationRule &ir =
1533 IntRules.Get(mesh->GetElementBaseGeometry(i), Tr.OrderJ());
1534 for (int j = 0; j < ir.GetNPoints(); j++)
1535 {
1536 const IntegrationPoint &ip = ir.IntPoint(j);
1537 Tr.SetIntPoint(&ip);
1538 volume += ip.weight * Tr.Weight();
1539 }
1540 }
1541
1542 NCMesh *ncmesh = mesh->ncmesh;
1543 if (Parallel() == false)
1544 {
1545 avg_volume = (ncmesh == NULL) ?
1546 volume / NE : volume / ncmesh->GetNumRootElements();
1547
1548 }
1549#ifdef MFEM_USE_MPI
1550 else
1551 {
1552 real_t area_NE[4];
1553 area_NE[0] = volume; area_NE[1] = NE;
1554 MPI_Allreduce(area_NE, area_NE + 2, 2, MPITypeMap<real_t>::mpi_type, MPI_SUM,
1555 comm);
1556 avg_volume = (ncmesh == NULL) ?
1557 area_NE[2] / area_NE[3] : area_NE[2] / ncmesh->GetNumRootElements();
1558 }
1559#endif
1560}
1561
1563 const FiniteElementSpace &fes,
1564 const IntegrationRule &ir,
1565 const Vector &xe,
1566 DenseTensor &Jtr) const
1567{
1568 // Fallback to the 1-element method, ComputeElementTargets()
1569
1570 // When UsesPhysicalCoordinates() == true, we assume 'xe' uses
1571 // ElementDofOrdering::LEXICOGRAPHIC iff 'fe' is a TensorFiniteElement.
1572
1573 const Mesh *mesh = fes.GetMesh();
1574 const int NE = mesh->GetNE();
1575 // Quick return for empty processors:
1576 if (NE == 0) { return; }
1577 const int dim = mesh->Dimension();
1578 MFEM_VERIFY(mesh->GetNumGeometries(dim) <= 1,
1579 "mixed meshes are not supported");
1580 MFEM_VERIFY(!fes.IsVariableOrder(), "variable orders are not supported");
1581 const FiniteElement &fe = *fes.GetFE(0);
1582 const int sdim = fes.GetVDim();
1583 const int nvdofs = sdim*fe.GetDof();
1584 MFEM_VERIFY(!UsesPhysicalCoordinates() ||
1585 xe.Size() == NE*nvdofs, "invalid input Vector 'xe'!");
1586 const int NQ = ir.GetNPoints();
1587 const Array<int> *dof_map = nullptr;
1589 {
1590 const TensorBasisElement *tfe =
1591 dynamic_cast<const TensorBasisElement *>(&fe);
1592 if (tfe)
1593 {
1594 dof_map = &tfe->GetDofMap();
1595 if (dof_map->Size() == 0) { dof_map = nullptr; }
1596 }
1597 }
1598
1599 Vector elfun_lex, elfun_nat;
1600 DenseTensor J;
1601 xe.HostRead();
1602 Jtr.HostWrite();
1603 if (UsesPhysicalCoordinates() && dof_map != nullptr)
1604 {
1605 elfun_nat.SetSize(nvdofs);
1606 }
1607 for (int e = 0; e < NE; e++)
1608 {
1610 {
1611 if (!dof_map)
1612 {
1613 elfun_nat.SetDataAndSize(xe.GetData()+e*nvdofs, nvdofs);
1614 }
1615 else
1616 {
1617 elfun_lex.SetDataAndSize(xe.GetData()+e*nvdofs, nvdofs);
1618 const int ndofs = fe.GetDof();
1619 for (int d = 0; d < sdim; d++)
1620 {
1621 for (int i_lex = 0; i_lex < ndofs; i_lex++)
1622 {
1623 elfun_nat[(*dof_map)[i_lex]+d*ndofs] =
1624 elfun_lex[i_lex+d*ndofs];
1625 }
1626 }
1627 }
1628 }
1629 J.UseExternalData(Jtr(e*NQ).Data(), sdim, dim, NQ);
1630 ComputeElementTargets(e, fe, ir, elfun_nat, J);
1631 }
1632}
1633
1635{
1636 switch (target_type)
1637 {
1638 case IDEAL_SHAPE_UNIT_SIZE: return false;
1642 case GIVEN_FULL: return true;
1643 default: MFEM_ABORT("TargetType not added to ContainsVolumeInfo.");
1644 }
1645 return false;
1646}
1647
1649 const IntegrationRule &ir,
1650 const Vector &elfun,
1651 DenseTensor &Jtr) const
1652{
1653 MFEM_CONTRACT_VAR(elfun);
1654 MFEM_ASSERT(target_type == IDEAL_SHAPE_UNIT_SIZE || nodes != NULL, "");
1655
1657 nodes->FESpace()->GetFE(e_id) : NULL;
1658 const DenseMatrix &Wideal =
1660 MFEM_ASSERT(Wideal.Height() == Jtr.SizeI(), "");
1661 MFEM_ASSERT(Wideal.Width() == Jtr.SizeJ(), "");
1662
1663 switch (target_type)
1664 {
1666 {
1667 for (int i = 0; i < ir.GetNPoints(); i++) { Jtr(i) = Wideal; }
1668 break;
1669 }
1671 {
1672 if (avg_volume == 0.0) { ComputeAvgVolume(); }
1673 DenseMatrix W(Wideal.Height());
1674
1675 NCMesh *ncmesh = nodes->FESpace()->GetMesh()->ncmesh;
1676 real_t el_volume = avg_volume;
1677 if (ncmesh)
1678 {
1679 el_volume = avg_volume / ncmesh->GetElementSizeReduction(e_id);
1680 }
1681
1682 W.Set(std::pow(volume_scale * el_volume / Wideal.Det(),
1683 1./W.Height()), Wideal);
1684 for (int i = 0; i < ir.GetNPoints(); i++) { Jtr(i) = W; }
1685 break;
1686 }
1689 {
1690 const int dim = nfe->GetDim(), dof = nfe->GetDof();
1691 MFEM_ASSERT(dim == nodes->FESpace()->GetVDim(), "");
1692 DenseMatrix dshape(dof, dim), pos(dof, dim);
1693 Array<int> xdofs(dof * dim);
1694 Vector posV(pos.Data(), dof * dim);
1695 real_t detW;
1696
1697 // always initialize detW to suppress a warning:
1698 detW = (target_type == IDEAL_SHAPE_GIVEN_SIZE) ? Wideal.Det() : 0.0;
1699 nodes->FESpace()->GetElementVDofs(e_id, xdofs);
1700 nodes->GetSubVector(xdofs, posV);
1701 for (int i = 0; i < ir.GetNPoints(); i++)
1702 {
1703 nfe->CalcDShape(ir.IntPoint(i), dshape);
1704 MultAtB(pos, dshape, Jtr(i));
1706 {
1707 const real_t det = Jtr(i).Det();
1708 MFEM_VERIFY(det > 0.0, "The given mesh is inverted!");
1709 Jtr(i).Set(std::pow(det / detW, 1./dim), Wideal);
1710 }
1711 }
1712 break;
1713 }
1714 default:
1715 MFEM_ABORT("invalid target type!");
1716 }
1717}
1718
1720 const IntegrationRule &ir,
1721 const Vector &elfun,
1723 DenseTensor &dJtr) const
1724{
1725 MFEM_CONTRACT_VAR(elfun);
1726 MFEM_ASSERT(target_type == IDEAL_SHAPE_UNIT_SIZE || nodes != NULL, "");
1727
1728 // TODO: Compute derivative for targets with GIVEN_SHAPE or/and GIVEN_SIZE
1729 for (int i = 0; i < Tpr.GetFE()->GetDim()*ir.GetNPoints(); i++)
1730 { dJtr(i) = 0.; }
1731}
1732
1734 VectorCoefficient *vspec,
1735 TMOPMatrixCoefficient *mspec)
1736{
1737 scalar_tspec = sspec;
1738 vector_tspec = vspec;
1739 matrix_tspec = mspec;
1740}
1741
1743 const IntegrationRule &ir,
1744 const Vector &elfun,
1745 DenseTensor &Jtr) const
1746{
1747 DenseMatrix point_mat;
1748 point_mat.UseExternalData(elfun.GetData(), fe.GetDof(), fe.GetDim());
1749
1750 switch (target_type)
1751 {
1752 case GIVEN_FULL:
1753 {
1754 MFEM_VERIFY(matrix_tspec != NULL,
1755 "Target type GIVEN_FULL requires a MatrixCoefficient.");
1756
1758 Tpr.SetFE(&fe);
1759 Tpr.ElementNo = e_id;
1761 Tpr.GetPointMat().Transpose(point_mat);
1762
1763 for (int i = 0; i < ir.GetNPoints(); i++)
1764 {
1765 const IntegrationPoint &ip = ir.IntPoint(i);
1766 Tpr.SetIntPoint(&ip);
1767 matrix_tspec->Eval(Jtr(i), Tpr, ip);
1768 }
1769 break;
1770 }
1771 default:
1772 MFEM_ABORT("Incompatible target type for analytic adaptation!");
1773 }
1774}
1775
1777 const Vector &elfun,
1779 DenseTensor &dJtr) const
1780{
1781 const FiniteElement *fe = Tpr.GetFE();
1782 DenseMatrix point_mat;
1783 point_mat.UseExternalData(elfun.GetData(), fe->GetDof(), fe->GetDim());
1784
1785 switch (target_type)
1786 {
1787 case GIVEN_FULL:
1788 {
1789 MFEM_VERIFY(matrix_tspec != NULL,
1790 "Target type GIVEN_FULL requires a TMOPMatrixCoefficient.");
1791
1792 for (int d = 0; d < fe->GetDim(); d++)
1793 {
1794 for (int i = 0; i < ir.GetNPoints(); i++)
1795 {
1796 const IntegrationPoint &ip = ir.IntPoint(i);
1797 Tpr.SetIntPoint(&ip);
1798 DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
1799 matrix_tspec->EvalGrad(dJtr_i, Tpr, ip, d);
1800 }
1801 }
1802 break;
1803 }
1804 default:
1805 MFEM_ABORT("Incompatible target type for analytic adaptation!");
1806 }
1807}
1808
1809namespace internal
1810{
1811
1812// mfem::forall-based copy kernel -- used by protected methods below.
1813// Needed as a workaround for the nvcc restriction that methods with mfem::forall
1814// in them must to be public.
1815static inline void device_copy(real_t *d_dest, const real_t *d_src, int size)
1816{
1817 mfem::forall(size, [=] MFEM_HOST_DEVICE (int i) { d_dest[i] = d_src[i]; });
1818}
1819
1820} // namespace internal
1821
1822#ifdef MFEM_USE_MPI
1824{
1825 MFEM_VERIFY(adapt_eval, "SetAdaptivityEvaluator() has not been called!")
1826 MFEM_VERIFY(ncomp > 0, "No target specifications have been set!");
1827
1828 ParFiniteElementSpace *ptspec_fes = t.ParFESpace();
1829
1830 tspec_sav = tspec;
1831
1832 delete tspec_fesv;
1833 tspec_fesv = new FiniteElementSpace(ptspec_fes->GetMesh(),
1834 ptspec_fes->FEColl(), ncomp);
1835
1836 delete ptspec_fesv;
1837 ptspec_fesv = new ParFiniteElementSpace(ptspec_fes->GetParMesh(),
1838 ptspec_fes->FEColl(), ncomp);
1839
1840 delete tspec_pgf;
1843
1845 adapt_eval->SetInitialField(*ptspec_fes->GetMesh()->GetNodes(), tspec);
1846}
1847
1865
1867{
1868 const int vdim = tspec_.FESpace()->GetVDim(),
1869 ndof = tspec_.FESpace()->GetNDofs();
1870 MFEM_VERIFY(ndof == tspec.Size()/ncomp, "Inconsistency in SetTspecAtIndex.");
1871
1872 const auto tspec__d = tspec_.Read();
1873 auto tspec_d = tspec.ReadWrite();
1874 const int offset = idx*ndof;
1875 internal::device_copy(tspec_d + offset, tspec__d, ndof*vdim);
1877}
1878
1880{
1881 MFEM_VERIFY(tspec_.FESpace()->GetOrdering() == Ordering::byNODES,
1882 "Discrete target size should be ordered byNodes.");
1883 if (sizeidx > -1) { SetTspecAtIndex(sizeidx, tspec_); return; }
1884 sizeidx = ncomp;
1885 SetDiscreteTargetBase(tspec_);
1887}
1888
1890{
1891 MFEM_VERIFY(tspec_.FESpace()->GetOrdering() == Ordering::byNODES,
1892 "Discrete target skewness should be ordered byNodes.");
1893 if (skewidx > -1) { SetTspecAtIndex(skewidx, tspec_); return; }
1894 skewidx = ncomp;
1895 SetDiscreteTargetBase(tspec_);
1897}
1898
1900{
1901 MFEM_VERIFY(ar.FESpace()->GetOrdering() == Ordering::byNODES,
1902 "Discrete target aspect ratio should be ordered byNodes.");
1903 if (aspectratioidx > -1) { SetTspecAtIndex(aspectratioidx, ar); return; }
1907}
1908
1910{
1911 MFEM_VERIFY(o.FESpace()->GetOrdering() == Ordering::byNODES,
1912 "Discrete target orientation should be ordered byNodes.");
1913 if (orientationidx > -1) { SetTspecAtIndex(orientationidx, o); return; }
1917}
1918
1923#endif // MFEM_USE_MPI
1924
1926{
1927 const int vdim = tspec_.FESpace()->GetVDim(),
1928 ndof = tspec_.FESpace()->GetNDofs();
1929
1930 ncomp += vdim;
1931
1932 // need to append data to tspec
1933 // make a copy of tspec->tspec_temp, increase its size, and
1934 // copy data from tspec_temp -> tspec, then add new entries
1935 Vector tspec_temp = tspec;
1936 tspec.UseDevice(true);
1937 tspec_sav.UseDevice(true);
1938 tspec.SetSize(ncomp*ndof);
1939
1940 const auto tspec_temp_d = tspec_temp.Read();
1941 auto tspec_d = tspec.ReadWrite();
1942 internal::device_copy(tspec_d, tspec_temp_d, tspec_temp.Size());
1943
1944 const auto tspec__d = tspec_.Read();
1945 const int offset = (ncomp-vdim)*ndof;
1946 internal::device_copy(tspec_d + offset, tspec__d, ndof*vdim);
1947}
1948
1950{
1951 const int vdim = tspec_.FESpace()->GetVDim(),
1952 ndof = tspec_.FESpace()->GetNDofs();
1953 MFEM_VERIFY(ndof == tspec.Size()/ncomp, "Inconsistency in SetTargetSpec.");
1954
1955 const auto tspec__d = tspec_.Read();
1956 auto tspec_d = tspec.ReadWrite();
1957 const int offset = idx*ndof;
1958 internal::device_copy(tspec_d + offset, tspec__d, ndof*vdim);
1960}
1961
1963{
1964 MFEM_VERIFY(tspec_.FESpace()->GetOrdering() == Ordering::byNODES,
1965 "Discrete target size should be ordered byNodes.");
1966 if (sizeidx > -1) { SetTspecAtIndex(sizeidx, tspec_); return; }
1967 sizeidx = ncomp;
1968 SetDiscreteTargetBase(tspec_);
1970}
1971
1973{
1974 MFEM_VERIFY(tspec_.FESpace()->GetOrdering() == Ordering::byNODES,
1975 "Discrete target skewness should be ordered byNodes.");
1976 if (skewidx > -1) { SetTspecAtIndex(skewidx, tspec_); return; }
1977 skewidx = ncomp;
1978 SetDiscreteTargetBase(tspec_);
1980}
1981
1983{
1984 MFEM_VERIFY(ar.FESpace()->GetOrdering() == Ordering::byNODES,
1985 "Discrete target aspect ratio should be ordered byNodes.");
1986 if (aspectratioidx > -1) { SetTspecAtIndex(aspectratioidx, ar); return; }
1990}
1991
1993{
1994 MFEM_VERIFY(o.FESpace()->GetOrdering() == Ordering::byNODES,
1995 "Discrete target orientation should be ordered byNodes.");
1996 if (orientationidx > -1) { SetTspecAtIndex(orientationidx, o); return; }
2000}
2001
2003{
2004 MFEM_VERIFY(adapt_eval, "SetAdaptivityEvaluator() has not been called!")
2005 MFEM_VERIFY(ncomp > 0, "No target specifications have been set!");
2006
2007 const FiniteElementSpace *tspec_fes = t.FESpace();
2008
2009 tspec_sav = tspec;
2010
2011 delete tspec_fesv;
2012 tspec_fesv = new FiniteElementSpace(tspec_fes->GetMesh(),
2013 tspec_fes->FEColl(), ncomp,
2015
2016 delete tspec_gf;
2018
2020 adapt_eval->SetInitialField(*tspec_fes->GetMesh()->GetNodes(), tspec);
2021}
2022
2024{
2025 if (idx < 0) { return; }
2026 const int ndof = tspec_.FESpace()->GetNDofs(),
2027 vdim = tspec_.FESpace()->GetVDim();
2028 MFEM_VERIFY(ndof == tspec.Size()/ncomp,
2029 "Inconsistency in GetSerialDiscreteTargetSpec.");
2030
2031 for (int i = 0; i < ndof*vdim; i++)
2032 {
2033 tspec_(i) = tspec(i + idx*ndof);
2034 }
2035}
2036
2047
2052
2053
2055 bool reuse_flag,
2056 int new_x_ordering)
2057{
2058 if (reuse_flag && good_tspec) { return; }
2059
2060 MFEM_VERIFY(tspec.Size() > 0, "Target specification is not set!");
2061 adapt_eval->ComputeAtNewPosition(new_x, tspec, new_x_ordering);
2062 tspec_sav = tspec;
2063
2064 good_tspec = reuse_flag;
2065}
2066
2068 Vector &IntData,
2069 int new_x_ordering)
2070{
2071 adapt_eval->ComputeAtNewPosition(new_x, IntData, new_x_ordering);
2072}
2073
2076 int dofidx, int dir,
2077 const Vector &IntData)
2078{
2079 MFEM_VERIFY(tspec.Size() > 0, "Target specification is not set!");
2080
2081 Array<int> dofs;
2083 const int cnt = tspec.Size()/ncomp; // dofs per scalar-field
2084
2085 for (int i = 0; i < ncomp; i++)
2086 {
2087 tspec(dofs[dofidx]+i*cnt) = IntData(dofs[dofidx] + i*cnt + dir*cnt*ncomp);
2088 }
2089}
2090
2092 int dofidx)
2093{
2094 MFEM_VERIFY(tspec.Size() > 0, "Target specification is not set!");
2095
2096 Array<int> dofs;
2098 const int cnt = tspec.Size()/ncomp;
2099 for (int i = 0; i < ncomp; i++)
2100 {
2101 tspec(dofs[dofidx] + i*cnt) = tspec_sav(dofs[dofidx] + i*cnt);
2102 }
2103}
2104
2106 const IntegrationRule &intrule)
2107{
2108 switch (target_type)
2109 {
2112 {
2113 const int ndofs = tspec_fesv->GetFE(e_id)->GetDof(),
2114 ntspec_dofs = ndofs*ncomp;
2115
2116 Vector tspec_vals(ntspec_dofs);
2117
2118 Array<int> dofs;
2119 tspec_fesv->GetElementVDofs(e_id, dofs);
2120 tspec.GetSubVector(dofs, tspec_vals);
2121 DenseMatrix tr;
2122 tspec_gf->GetVectorValues(e_id, intrule, tspec_refine, tr);
2124 break;
2125 }
2126 default:
2127 MFEM_ABORT("Incompatible target type for discrete adaptation!");
2128 }
2129}
2130
2138
2140 const IntegrationRule &ir,
2141 const Vector &elfun,
2142 DenseTensor &Jtr) const
2143{
2144 MFEM_VERIFY(tspec_fesv, "No target specifications have been set.");
2145 const int dim = fe.GetDim(),
2146 nqp = ir.GetNPoints();
2147 Jtrcomp.SetSize(dim, dim, 4*nqp);
2148
2149 FiniteElementSpace *src_fes = tspec_fesv;
2150
2151 switch (target_type)
2152 {
2155 {
2156 const DenseMatrix &Wideal =
2158 const int ndofs = tspec_fesv->GetFE(e_id)->GetDof(),
2159 ntspec_dofs = ndofs*ncomp;
2160
2161 Vector shape(ndofs), tspec_vals(ntspec_dofs), par_vals,
2162 par_vals_c1, par_vals_c2, par_vals_c3;
2163
2164 Array<int> dofs;
2165 DenseMatrix D_rho(dim), Q_phi(dim), R_theta(dim);
2166 tspec_fesv->GetElementVDofs(e_id, dofs);
2167 tspec.UseDevice(true);
2168 tspec.GetSubVector(dofs, tspec_vals);
2169 if (tspec_refine.NumCols() > 0) // Refinement
2170 {
2171 MFEM_VERIFY(amr_el >= 0, " Target being constructed for an AMR element.");
2172 for (int i = 0; i < ncomp; i++)
2173 {
2174 for (int j = 0; j < ndofs; j++)
2175 {
2176 tspec_vals(j + i*ndofs) = tspec_refine(j + amr_el*ndofs, i);
2177 }
2178 }
2179 }
2180 else if (tspec_derefine.Size() > 0) // Derefinement
2181 {
2182 dofs.SetSize(0);
2184 tspec_derefine.GetSubVector(dofs, tspec_vals);
2185 src_fes = coarse_tspec_fesv;
2186 }
2187
2188 for (int q = 0; q < nqp; q++)
2189 {
2190 const IntegrationPoint &ip = ir.IntPoint(q);
2191 src_fes->GetFE(e_id)->CalcShape(ip, shape);
2192 Jtr(q) = Wideal; // Initialize to identity
2193 for (int d = 0; d < 4; d++)
2194 {
2195 DenseMatrix Jtrcomp_q(Jtrcomp.GetData(d + 4*q), dim, dim);
2196 Jtrcomp_q = Wideal; // Initialize to identity
2197 }
2198
2199 if (sizeidx != -1) // Set size
2200 {
2201 par_vals.SetDataAndSize(tspec_vals.GetData()+sizeidx*ndofs, ndofs);
2202 real_t min_size = par_vals.Min();
2203 if (lim_min_size > 0.) { min_size = lim_min_size; }
2204 MFEM_VERIFY(min_size > 0.0,
2205 "Non-positive size propagated in the target definition.");
2206
2207 real_t size = std::max(shape * par_vals, min_size);
2208 NCMesh *ncmesh = tspec_fesv->GetMesh()->ncmesh;
2209 if (ncmesh)
2210 {
2211 size /= ncmesh->GetElementSizeReduction(e_id);
2212 }
2213 Jtr(q).Set(std::pow(size, 1.0/dim), Jtr(q));
2214 DenseMatrix Jtrcomp_q(Jtrcomp.GetData(0 + 4*q), dim, dim);
2215 Jtrcomp_q = Jtr(q);
2216 } // Done size
2217
2218 if (target_type == IDEAL_SHAPE_GIVEN_SIZE) { continue; }
2219
2220 if (aspectratioidx != -1) // Set aspect ratio
2221 {
2222 if (dim == 2)
2223 {
2224 par_vals.SetDataAndSize(tspec_vals.GetData()+
2225 aspectratioidx*ndofs, ndofs);
2226 const real_t min_size = par_vals.Min();
2227 MFEM_VERIFY(min_size > 0.0,
2228 "Non-positive aspect-ratio propagated in the target definition.");
2229
2230 const real_t aspectratio = shape * par_vals;
2231 D_rho = 0.;
2232 D_rho(0,0) = 1./pow(aspectratio,0.5);
2233 D_rho(1,1) = pow(aspectratio,0.5);
2234 }
2235 else
2236 {
2237 par_vals.SetDataAndSize(tspec_vals.GetData()+
2238 aspectratioidx*ndofs, ndofs*3);
2239 par_vals_c1.SetDataAndSize(par_vals.GetData(), ndofs);
2240 par_vals_c2.SetDataAndSize(par_vals.GetData()+ndofs, ndofs);
2241 par_vals_c3.SetDataAndSize(par_vals.GetData()+2*ndofs, ndofs);
2242
2243 const real_t rho1 = shape * par_vals_c1;
2244 const real_t rho2 = shape * par_vals_c2;
2245 const real_t rho3 = shape * par_vals_c3;
2246 D_rho = 0.;
2247 D_rho(0,0) = pow(rho1,2./3.);
2248 D_rho(1,1) = pow(rho2,2./3.);
2249 D_rho(2,2) = pow(rho3,2./3.);
2250 }
2251 DenseMatrix Jtrcomp_q(Jtrcomp.GetData(1 + 4*q), dim, dim);
2252 Jtrcomp_q = D_rho;
2253 DenseMatrix Temp = Jtr(q);
2254 Mult(D_rho, Temp, Jtr(q));
2255 } // Done aspect ratio
2256
2257 if (skewidx != -1) // Set skew
2258 {
2259 if (dim == 2)
2260 {
2261 par_vals.SetDataAndSize(tspec_vals.GetData()+
2262 skewidx*ndofs, ndofs);
2263
2264 const real_t skew = shape * par_vals;
2265
2266 Q_phi = 0.;
2267 Q_phi(0,0) = 1.;
2268 Q_phi(0,1) = cos(skew);
2269 Q_phi(1,1) = sin(skew);
2270 }
2271 else
2272 {
2273 par_vals.SetDataAndSize(tspec_vals.GetData()+
2274 skewidx*ndofs, ndofs*3);
2275 par_vals_c1.SetDataAndSize(par_vals.GetData(), ndofs);
2276 par_vals_c2.SetDataAndSize(par_vals.GetData()+ndofs, ndofs);
2277 par_vals_c3.SetDataAndSize(par_vals.GetData()+2*ndofs, ndofs);
2278
2279 const real_t phi12 = shape * par_vals_c1;
2280 const real_t phi13 = shape * par_vals_c2;
2281 const real_t chi = shape * par_vals_c3;
2282
2283 Q_phi = 0.;
2284 Q_phi(0,0) = 1.;
2285 Q_phi(0,1) = cos(phi12);
2286 Q_phi(0,2) = cos(phi13);
2287
2288 Q_phi(1,1) = sin(phi12);
2289 Q_phi(1,2) = sin(phi13)*cos(chi);
2290
2291 Q_phi(2,2) = sin(phi13)*sin(chi);
2292 }
2293 DenseMatrix Jtrcomp_q(Jtrcomp.GetData(2 + 4*q), dim, dim);
2294 Jtrcomp_q = Q_phi;
2295 DenseMatrix Temp = Jtr(q);
2296 Mult(Q_phi, Temp, Jtr(q));
2297 } // Done skew
2298
2299 if (orientationidx != -1) // Set orientation
2300 {
2301 if (dim == 2)
2302 {
2303 par_vals.SetDataAndSize(tspec_vals.GetData()+
2304 orientationidx*ndofs, ndofs);
2305
2306 const real_t theta = shape * par_vals;
2307 R_theta(0,0) = cos(theta);
2308 R_theta(0,1) = -sin(theta);
2309 R_theta(1,0) = sin(theta);
2310 R_theta(1,1) = cos(theta);
2311 }
2312 else
2313 {
2314 par_vals.SetDataAndSize(tspec_vals.GetData()+
2315 orientationidx*ndofs, ndofs*3);
2316 par_vals_c1.SetDataAndSize(par_vals.GetData(), ndofs);
2317 par_vals_c2.SetDataAndSize(par_vals.GetData()+ndofs, ndofs);
2318 par_vals_c3.SetDataAndSize(par_vals.GetData()+2*ndofs, ndofs);
2319
2320 const real_t theta = shape * par_vals_c1;
2321 const real_t psi = shape * par_vals_c2;
2322 const real_t beta = shape * par_vals_c3;
2323
2324 real_t ct = cos(theta), st = sin(theta),
2325 cp = cos(psi), sp = sin(psi),
2326 cb = cos(beta), sb = sin(beta);
2327
2328 R_theta = 0.;
2329 R_theta(0,0) = ct*sp;
2330 R_theta(1,0) = st*sp;
2331 R_theta(2,0) = cp;
2332
2333 R_theta(0,1) = -st*cb + ct*cp*sb;
2334 R_theta(1,1) = ct*cb + st*cp*sb;
2335 R_theta(2,1) = -sp*sb;
2336
2337 R_theta(0,0) = -st*sb - ct*cp*cb;
2338 R_theta(1,0) = ct*sb - st*cp*cb;
2339 R_theta(2,0) = sp*cb;
2340 }
2341 DenseMatrix Jtrcomp_q(Jtrcomp.GetData(3 + 4*q), dim, dim);
2342 Jtrcomp_q = R_theta;
2343 DenseMatrix Temp = Jtr(q);
2344 Mult(R_theta, Temp, Jtr(q));
2345 } // Done orientation
2346 }
2347 break;
2348 }
2349 default:
2350 MFEM_ABORT("Incompatible target type for discrete adaptation!");
2351 }
2352}
2353
2355 const Vector &elfun,
2357 DenseTensor &dJtr) const
2358{
2359 MFEM_ASSERT(target_type == IDEAL_SHAPE_UNIT_SIZE || nodes != NULL, "");
2360
2361 MFEM_VERIFY(tspec_fesv, "No target specifications have been set.");
2362
2363 dJtr = 0.;
2364 const int e_id = Tpr.ElementNo;
2365 const FiniteElement *fe = Tpr.GetFE();
2366
2367 switch (target_type)
2368 {
2371 {
2372 const DenseMatrix &Wideal =
2374 const int dim = Wideal.Height(),
2375 ndofs = fe->GetDof(),
2376 ntspec_dofs = ndofs*ncomp;
2377
2378 Vector shape(ndofs), tspec_vals(ntspec_dofs), par_vals,
2379 par_vals_c1(ndofs), par_vals_c2(ndofs), par_vals_c3(ndofs);
2380
2381 Array<int> dofs;
2382 DenseMatrix dD_rho(dim), dQ_phi(dim), dR_theta(dim);
2383 DenseMatrix dQ_phi13(dim), dQ_phichi(dim); // dQ_phi is used for dQ/dphi12 in 3D
2384 DenseMatrix dR_psi(dim), dR_beta(dim);
2385 tspec_fesv->GetElementVDofs(e_id, dofs);
2386 tspec.GetSubVector(dofs, tspec_vals);
2387
2388 DenseMatrix grad_e_c1(ndofs, dim),
2389 grad_e_c2(ndofs, dim),
2390 grad_e_c3(ndofs, dim);
2391 Vector grad_ptr_c1(grad_e_c1.GetData(), ndofs*dim),
2392 grad_ptr_c2(grad_e_c2.GetData(), ndofs*dim),
2393 grad_ptr_c3(grad_e_c3.GetData(), ndofs*dim);
2394
2395 DenseMatrix grad_phys; // This will be (dof x dim, dof).
2396 fe->ProjectGrad(*fe, Tpr, grad_phys);
2397
2398 for (int i = 0; i < ir.GetNPoints(); i++)
2399 {
2400 const IntegrationPoint &ip = ir.IntPoint(i);
2401 DenseMatrix Jtrcomp_s(Jtrcomp.GetData(0 + 4*i), dim, dim); // size
2402 DenseMatrix Jtrcomp_d(Jtrcomp.GetData(1 + 4*i), dim, dim); // aspect-ratio
2403 DenseMatrix Jtrcomp_q(Jtrcomp.GetData(2 + 4*i), dim, dim); // skew
2404 DenseMatrix Jtrcomp_r(Jtrcomp.GetData(3 + 4*i), dim, dim); // orientation
2405 DenseMatrix work1(dim), work2(dim), work3(dim);
2406
2407 if (sizeidx != -1) // Set size
2408 {
2409 par_vals.SetDataAndSize(tspec_vals.GetData()+sizeidx*ndofs, ndofs);
2410
2411 grad_phys.Mult(par_vals, grad_ptr_c1);
2412 Vector grad_q(dim);
2413 tspec_fesv->GetFE(e_id)->CalcShape(ip, shape);
2414 grad_e_c1.MultTranspose(shape, grad_q);
2415
2416 const real_t min_size = par_vals.Min();
2417 MFEM_VERIFY(min_size > 0.0,
2418 "Non-positive size propagated in the target definition.");
2419 const real_t size = std::max(shape * par_vals, min_size);
2420 real_t dz_dsize = (1./dim)*pow(size, 1./dim - 1.);
2421
2422 Mult(Jtrcomp_q, Jtrcomp_d, work1); // Q*D
2423 Mult(Jtrcomp_r, work1, work2); // R*Q*D
2424
2425 for (int d = 0; d < dim; d++)
2426 {
2427 DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
2428 work1 = Wideal;
2429 work1.Set(dz_dsize, work1); // dz/dsize
2430 work1 *= grad_q(d); // dz/dsize*dsize/dx
2431 AddMult(work1, work2, dJtr_i); // dz/dx*R*Q*D
2432 }
2433 } // Done size
2434
2435 if (target_type == IDEAL_SHAPE_GIVEN_SIZE) { continue; }
2436
2437 if (aspectratioidx != -1) // Set aspect ratio
2438 {
2439 if (dim == 2)
2440 {
2441 par_vals.SetDataAndSize(tspec_vals.GetData()+
2442 aspectratioidx*ndofs, ndofs);
2443
2444 grad_phys.Mult(par_vals, grad_ptr_c1);
2445 Vector grad_q(dim);
2446 tspec_fesv->GetFE(e_id)->CalcShape(ip, shape);
2447 grad_e_c1.MultTranspose(shape, grad_q);
2448
2449 const real_t aspectratio = shape * par_vals;
2450 dD_rho = 0.;
2451 dD_rho(0,0) = -0.5*pow(aspectratio,-1.5);
2452 dD_rho(1,1) = 0.5*pow(aspectratio,-0.5);
2453
2454 Mult(Jtrcomp_s, Jtrcomp_r, work1); // z*R
2455 Mult(work1, Jtrcomp_q, work2); // z*R*Q
2456
2457 for (int d = 0; d < dim; d++)
2458 {
2459 DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
2460 work1 = dD_rho;
2461 work1 *= grad_q(d); // work1 = dD/drho*drho/dx
2462 AddMult(work2, work1, dJtr_i); // z*R*Q*dD/dx
2463 }
2464 }
2465 else // 3D
2466 {
2467 par_vals.SetDataAndSize(tspec_vals.GetData()+
2468 aspectratioidx*ndofs, ndofs*3);
2469 par_vals_c1.SetData(par_vals.GetData());
2470 par_vals_c2.SetData(par_vals.GetData()+ndofs);
2471 par_vals_c3.SetData(par_vals.GetData()+2*ndofs);
2472
2473 grad_phys.Mult(par_vals_c1, grad_ptr_c1);
2474 grad_phys.Mult(par_vals_c2, grad_ptr_c2);
2475 grad_phys.Mult(par_vals_c3, grad_ptr_c3);
2476 Vector grad_q1(dim), grad_q2(dim), grad_q3(dim);
2477 tspec_fesv->GetFE(e_id)->CalcShape(ip, shape);
2478 grad_e_c1.MultTranspose(shape, grad_q1);
2479 grad_e_c2.MultTranspose(shape, grad_q2);
2480 grad_e_c3.MultTranspose(shape, grad_q3);
2481
2482 const real_t rho1 = shape * par_vals_c1;
2483 const real_t rho2 = shape * par_vals_c2;
2484 const real_t rho3 = shape * par_vals_c3;
2485 dD_rho = 0.;
2486 dD_rho(0,0) = (2./3.)*pow(rho1,-1./3.);
2487 dD_rho(1,1) = (2./3.)*pow(rho2,-1./3.);
2488 dD_rho(2,2) = (2./3.)*pow(rho3,-1./3.);
2489
2490 Mult(Jtrcomp_s, Jtrcomp_r, work1); // z*R
2491 Mult(work1, Jtrcomp_q, work2); // z*R*Q
2492
2493
2494 for (int d = 0; d < dim; d++)
2495 {
2496 DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
2497 work1 = dD_rho;
2498 work1(0,0) *= grad_q1(d);
2499 work1(1,2) *= grad_q2(d);
2500 work1(2,2) *= grad_q3(d);
2501 // work1 = dD/dx = dD/drho1*drho1/dx + dD/drho2*drho2/dx
2502 AddMult(work2, work1, dJtr_i); // z*R*Q*dD/dx
2503 }
2504 }
2505 } // Done aspect ratio
2506
2507 if (skewidx != -1) // Set skew
2508 {
2509 if (dim == 2)
2510 {
2511 par_vals.SetDataAndSize(tspec_vals.GetData()+
2512 skewidx*ndofs, ndofs);
2513
2514 grad_phys.Mult(par_vals, grad_ptr_c1);
2515 Vector grad_q(dim);
2516 tspec_fesv->GetFE(e_id)->CalcShape(ip, shape);
2517 grad_e_c1.MultTranspose(shape, grad_q);
2518
2519 const real_t skew = shape * par_vals;
2520
2521 dQ_phi = 0.;
2522 dQ_phi(0,0) = 1.;
2523 dQ_phi(0,1) = -sin(skew);
2524 dQ_phi(1,1) = cos(skew);
2525
2526 Mult(Jtrcomp_s, Jtrcomp_r, work2); // z*R
2527
2528 for (int d = 0; d < dim; d++)
2529 {
2530 DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
2531 work1 = dQ_phi;
2532 work1 *= grad_q(d); // work1 = dQ/dphi*dphi/dx
2533 Mult(work1, Jtrcomp_d, work3); // dQ/dx*D
2534 AddMult(work2, work3, dJtr_i); // z*R*dQ/dx*D
2535 }
2536 }
2537 else
2538 {
2539 par_vals.SetDataAndSize(tspec_vals.GetData()+
2540 skewidx*ndofs, ndofs*3);
2541 par_vals_c1.SetData(par_vals.GetData());
2542 par_vals_c2.SetData(par_vals.GetData()+ndofs);
2543 par_vals_c3.SetData(par_vals.GetData()+2*ndofs);
2544
2545 grad_phys.Mult(par_vals_c1, grad_ptr_c1);
2546 grad_phys.Mult(par_vals_c2, grad_ptr_c2);
2547 grad_phys.Mult(par_vals_c3, grad_ptr_c3);
2548 Vector grad_q1(dim), grad_q2(dim), grad_q3(dim);
2549 tspec_fesv->GetFE(e_id)->CalcShape(ip, shape);
2550 grad_e_c1.MultTranspose(shape, grad_q1);
2551 grad_e_c2.MultTranspose(shape, grad_q2);
2552 grad_e_c3.MultTranspose(shape, grad_q3);
2553
2554 const real_t phi12 = shape * par_vals_c1;
2555 const real_t phi13 = shape * par_vals_c2;
2556 const real_t chi = shape * par_vals_c3;
2557
2558 dQ_phi = 0.;
2559 dQ_phi(0,0) = 1.;
2560 dQ_phi(0,1) = -sin(phi12);
2561 dQ_phi(1,1) = cos(phi12);
2562
2563 dQ_phi13 = 0.;
2564 dQ_phi13(0,2) = -sin(phi13);
2565 dQ_phi13(1,2) = cos(phi13)*cos(chi);
2566 dQ_phi13(2,2) = cos(phi13)*sin(chi);
2567
2568 dQ_phichi = 0.;
2569 dQ_phichi(1,2) = -sin(phi13)*sin(chi);
2570 dQ_phichi(2,2) = sin(phi13)*cos(chi);
2571
2572 Mult(Jtrcomp_s, Jtrcomp_r, work2); // z*R
2573
2574 for (int d = 0; d < dim; d++)
2575 {
2576 DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
2577 work1 = dQ_phi;
2578 work1 *= grad_q1(d); // work1 = dQ/dphi12*dphi12/dx
2579 work1.Add(grad_q2(d), dQ_phi13); // + dQ/dphi13*dphi13/dx
2580 work1.Add(grad_q3(d), dQ_phichi); // + dQ/dchi*dchi/dx
2581 Mult(work1, Jtrcomp_d, work3); // dQ/dx*D
2582 AddMult(work2, work3, dJtr_i); // z*R*dQ/dx*D
2583 }
2584 }
2585 } // Done skew
2586
2587 if (orientationidx != -1) // Set orientation
2588 {
2589 if (dim == 2)
2590 {
2591 par_vals.SetDataAndSize(tspec_vals.GetData()+
2592 orientationidx*ndofs, ndofs);
2593
2594 grad_phys.Mult(par_vals, grad_ptr_c1);
2595 Vector grad_q(dim);
2596 tspec_fesv->GetFE(e_id)->CalcShape(ip, shape);
2597 grad_e_c1.MultTranspose(shape, grad_q);
2598
2599 const real_t theta = shape * par_vals;
2600 dR_theta(0,0) = -sin(theta);
2601 dR_theta(0,1) = -cos(theta);
2602 dR_theta(1,0) = cos(theta);
2603 dR_theta(1,1) = -sin(theta);
2604
2605 Mult(Jtrcomp_q, Jtrcomp_d, work1); // Q*D
2606 Mult(Jtrcomp_s, work1, work2); // z*Q*D
2607 for (int d = 0; d < dim; d++)
2608 {
2609 DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
2610 work1 = dR_theta;
2611 work1 *= grad_q(d); // work1 = dR/dtheta*dtheta/dx
2612 AddMult(work1, work2, dJtr_i); // z*dR/dx*Q*D
2613 }
2614 }
2615 else
2616 {
2617 par_vals.SetDataAndSize(tspec_vals.GetData()+
2618 orientationidx*ndofs, ndofs*3);
2619 par_vals_c1.SetData(par_vals.GetData());
2620 par_vals_c2.SetData(par_vals.GetData()+ndofs);
2621 par_vals_c3.SetData(par_vals.GetData()+2*ndofs);
2622
2623 grad_phys.Mult(par_vals_c1, grad_ptr_c1);
2624 grad_phys.Mult(par_vals_c2, grad_ptr_c2);
2625 grad_phys.Mult(par_vals_c3, grad_ptr_c3);
2626 Vector grad_q1(dim), grad_q2(dim), grad_q3(dim);
2627 tspec_fesv->GetFE(e_id)->CalcShape(ip, shape);
2628 grad_e_c1.MultTranspose(shape, grad_q1);
2629 grad_e_c2.MultTranspose(shape, grad_q2);
2630 grad_e_c3.MultTranspose(shape, grad_q3);
2631
2632 const real_t theta = shape * par_vals_c1;
2633 const real_t psi = shape * par_vals_c2;
2634 const real_t beta = shape * par_vals_c3;
2635
2636 const real_t ct = cos(theta), st = sin(theta),
2637 cp = cos(psi), sp = sin(psi),
2638 cb = cos(beta), sb = sin(beta);
2639
2640 dR_theta = 0.;
2641 dR_theta(0,0) = -st*sp;
2642 dR_theta(1,0) = ct*sp;
2643 dR_theta(2,0) = 0;
2644
2645 dR_theta(0,1) = -ct*cb - st*cp*sb;
2646 dR_theta(1,1) = -st*cb + ct*cp*sb;
2647 dR_theta(2,1) = 0.;
2648
2649 dR_theta(0,0) = -ct*sb + st*cp*cb;
2650 dR_theta(1,0) = -st*sb - ct*cp*cb;
2651 dR_theta(2,0) = 0.;
2652
2653 dR_beta = 0.;
2654 dR_beta(0,0) = 0.;
2655 dR_beta(1,0) = 0.;
2656 dR_beta(2,0) = 0.;
2657
2658 dR_beta(0,1) = st*sb + ct*cp*cb;
2659 dR_beta(1,1) = -ct*sb + st*cp*cb;
2660 dR_beta(2,1) = -sp*cb;
2661
2662 dR_beta(0,0) = -st*cb + ct*cp*sb;
2663 dR_beta(1,0) = ct*cb + st*cp*sb;
2664 dR_beta(2,0) = 0.;
2665
2666 dR_psi = 0.;
2667 dR_psi(0,0) = ct*cp;
2668 dR_psi(1,0) = st*cp;
2669 dR_psi(2,0) = -sp;
2670
2671 dR_psi(0,1) = 0. - ct*sp*sb;
2672 dR_psi(1,1) = 0. + st*sp*sb;
2673 dR_psi(2,1) = -cp*sb;
2674
2675 dR_psi(0,0) = 0. + ct*sp*cb;
2676 dR_psi(1,0) = 0. + st*sp*cb;
2677 dR_psi(2,0) = cp*cb;
2678
2679 Mult(Jtrcomp_q, Jtrcomp_d, work1); // Q*D
2680 Mult(Jtrcomp_s, work1, work2); // z*Q*D
2681 for (int d = 0; d < dim; d++)
2682 {
2683 DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
2684 work1 = dR_theta;
2685 work1 *= grad_q1(d); // work1 = dR/dtheta*dtheta/dx
2686 work1.Add(grad_q2(d), dR_psi); // +dR/dpsi*dpsi/dx
2687 work1.Add(grad_q3(d), dR_beta); // +dR/dbeta*dbeta/dx
2688 AddMult(work1, work2, dJtr_i); // z*dR/dx*Q*D
2689 }
2690 }
2691 } // Done orientation
2692 }
2693 break;
2694 }
2695 default:
2696 MFEM_ABORT("Incompatible target type for discrete adaptation!");
2697 }
2698 Jtrcomp.Clear();
2699}
2700
2702 const real_t dx,
2703 bool reuse_flag,
2704 int x_ordering)
2705{
2706 if (reuse_flag && good_tspec_grad) { return; }
2707
2708 const int dim = tspec_fesv->GetFE(0)->GetDim(),
2709 cnt = x.Size()/dim;
2710
2712
2713 Vector TSpecTemp;
2714 Vector xtemp = x;
2715 for (int j = 0; j < dim; j++)
2716 {
2717 for (int i = 0; i < cnt; i++)
2718 {
2719 int idx = x_ordering == Ordering::byNODES ? j*cnt + i : i*dim + j;
2720 xtemp(idx) += dx;
2721 }
2722
2723 TSpecTemp.NewDataAndSize(tspec_pert1h.GetData() + j*cnt*ncomp, cnt*ncomp);
2724 UpdateTargetSpecification(xtemp, TSpecTemp, x_ordering);
2725
2726 for (int i = 0; i < cnt; i++)
2727 {
2728 int idx = x_ordering == Ordering::byNODES ? j*cnt + i : i*dim + j;
2729 xtemp(idx) -= dx;
2730 }
2731 }
2732
2733 good_tspec_grad = reuse_flag;
2734}
2735
2738 bool reuse_flag, int x_ordering)
2739{
2740
2741 if (reuse_flag && good_tspec_hess) { return; }
2742
2743 const int dim = tspec_fesv->GetFE(0)->GetDim(),
2744 cnt = x.Size()/dim,
2745 totmix = 1+2*(dim-2);
2746
2748 tspec_pertmix.SetSize(cnt*totmix*ncomp);
2749
2750 Vector TSpecTemp;
2751 Vector xtemp = x;
2752
2753 // T(x+2h)
2754 for (int j = 0; j < dim; j++)
2755 {
2756 for (int i = 0; i < cnt; i++)
2757 {
2758 int idx = x_ordering == Ordering::byNODES ? j*cnt + i : i*dim + j;
2759 xtemp(idx) += 2*dx;
2760 }
2761
2762 TSpecTemp.NewDataAndSize(tspec_pert2h.GetData() + j*cnt*ncomp, cnt*ncomp);
2763 UpdateTargetSpecification(xtemp, TSpecTemp, x_ordering);
2764
2765 for (int i = 0; i < cnt; i++)
2766 {
2767 int idx = x_ordering == Ordering::byNODES ? j*cnt + i : i*dim + j;
2768 xtemp(idx) -= 2*dx;
2769 }
2770 }
2771
2772 // T(x+h,y+h)
2773 int j = 0;
2774 for (int k1 = 0; k1 < dim; k1++)
2775 {
2776 for (int k2 = 0; (k1 != k2) && (k2 < dim); k2++)
2777 {
2778 for (int i = 0; i < cnt; i++)
2779 {
2780 int idx1 = x_ordering == Ordering::byNODES ? k1*cnt+i : i*dim + k1;
2781 int idx2 = x_ordering == Ordering::byNODES ? k2*cnt+i : i*dim + k2;
2782 xtemp(idx1) += dx;
2783 xtemp(idx2) += dx;
2784 }
2785
2786 TSpecTemp.NewDataAndSize(tspec_pertmix.GetData() + j*cnt*ncomp, cnt*ncomp);
2787 UpdateTargetSpecification(xtemp, TSpecTemp, x_ordering);
2788
2789 for (int i = 0; i < cnt; i++)
2790 {
2791 int idx1 = x_ordering == Ordering::byNODES ? k1*cnt+i : i*dim + k1;
2792 int idx2 = x_ordering == Ordering::byNODES ? k2*cnt+i : i*dim + k2;
2793 xtemp(idx1) -= dx;
2794 xtemp(idx2) -= dx;
2795 }
2796 j++;
2797 }
2798 }
2799
2800 good_tspec_hess = reuse_flag;
2801}
2802
2804{
2805 delete tspec_gf;
2806 delete adapt_eval;
2807 delete tspec_fesv;
2808#ifdef MFEM_USE_MPI
2809 delete ptspec_fesv;
2810#endif
2811}
2812
2814 const FiniteElementSpace &f)
2815{
2816 delete fes;
2817 delete mesh;
2818 mesh = new Mesh(m, true);
2819 fes = new FiniteElementSpace(mesh, f.FEColl(),
2820 f.GetVDim(), f.GetOrdering());
2821}
2822
2823#ifdef MFEM_USE_MPI
2825 const ParFiniteElementSpace &f)
2826{
2827 delete pfes;
2828 delete pmesh;
2829 pmesh = new ParMesh(m, true);
2830 pfes = new ParFiniteElementSpace(pmesh, f.FEColl(),
2831 f.GetVDim(), f.GetOrdering());
2832}
2833#endif
2834
2836{
2837#ifdef MFEM_USE_MPI
2839#else
2840 if (mesh) { mesh->DeleteGeometricFactors(); }
2841#endif
2842}
2843
2845{
2846 delete fes;
2847 delete mesh;
2848#ifdef MFEM_USE_MPI
2849 delete pfes;
2850 delete pmesh;
2851#endif
2852}
2853
2855{
2856 if (PA.enabled)
2857 {
2858 PA.H.GetMemory().DeleteDevice(copy_to_host);
2859 PA.H0.GetMemory().DeleteDevice(copy_to_host);
2860 if (!copy_to_host && !PA.Jtr.GetMemory().HostIsValid())
2861 {
2862 PA.Jtr_needs_update = true;
2863 }
2864 PA.Jtr.GetMemory().DeleteDevice(copy_to_host);
2865 }
2866}
2867
2869{
2870 delete lim_func;
2871 delete adapt_lim_gf;
2872 delete surf_fit_gf;
2873 delete surf_fit_limiter;
2874 delete surf_fit_grad;
2875 delete surf_fit_hess;
2876 for (int i = 0; i < ElemDer.Size(); i++)
2877 {
2878 delete ElemDer[i];
2879 delete ElemPertEnergy[i];
2880 }
2881}
2882
2884 const GridFunction &dist, Coefficient &w0,
2885 TMOP_LimiterFunction *lfunc)
2886{
2887 lim_nodes0 = &n0;
2888 lim_coeff = &w0;
2889 lim_dist = &dist;
2890 MFEM_VERIFY(lim_dist->FESpace()->GetVDim() == 1,
2891 "'dist' must be a scalar GridFunction!");
2892
2893 delete lim_func;
2894 lim_func = (lfunc) ? lfunc : new TMOP_QuadraticLimiter;
2895}
2896
2898 TMOP_LimiterFunction *lfunc)
2899{
2900 lim_nodes0 = &n0;
2901 lim_coeff = &w0;
2902 lim_dist = NULL;
2903
2904 delete lim_func;
2905 lim_func = (lfunc) ? lfunc : new TMOP_QuadraticLimiter;
2906}
2907
2909 Coefficient &coeff,
2911{
2912 adapt_lim_gf0 = &z0;
2913 delete adapt_lim_gf;
2914 adapt_lim_gf = new GridFunction(z0);
2915 adapt_lim_coeff = &coeff;
2916 adapt_lim_eval = &ae;
2917
2919 *z0.FESpace());
2922}
2923
2924#ifdef MFEM_USE_MPI
2926 Coefficient &coeff,
2928{
2929 adapt_lim_gf0 = &z0;
2930 adapt_lim_pgf0 = &z0;
2931 delete adapt_lim_gf;
2932 adapt_lim_gf = new GridFunction(z0);
2933 adapt_lim_coeff = &coeff;
2934 adapt_lim_eval = &ae;
2935
2937 *z0.ParFESpace());
2940}
2941#endif
2942
2944 const Array<bool> &smarker,
2945 Coefficient &coeff,
2947{
2948 // To have both we must duplicate the markers.
2949 MFEM_VERIFY(surf_fit_pos == NULL,
2950 "Using both fitting approaches is not supported.");
2951
2952 delete surf_fit_gf;
2953 surf_fit_gf = new GridFunction(s0);
2955 surf_fit_marker = &smarker;
2956 surf_fit_coeff = &coeff;
2957 surf_fit_eval = &ae;
2958
2960 *s0.FESpace());
2963}
2964
2966 const Array<bool> &smarker,
2967 Coefficient &coeff)
2968{
2969 // To have both we must duplicate the markers.
2970 MFEM_VERIFY(surf_fit_gf == NULL,
2971 "Using both fitting approaches is not supported.");
2972 MFEM_VERIFY(pos.FESpace()->GetMesh()->GetNodes(),
2973 "Positions on a mesh without Nodes is not supported.");
2974 MFEM_VERIFY(pos.FESpace()->GetOrdering() ==
2975 pos.FESpace()->GetMesh()->GetNodes()->FESpace()->GetOrdering(),
2976 "Incompatible ordering of spaces!");
2977
2978 surf_fit_pos = &pos;
2980 surf_fit_marker = &smarker;
2981 surf_fit_coeff = &coeff;
2982 delete surf_fit_limiter;
2984}
2985
2986#ifdef MFEM_USE_MPI
2988 const Array<bool> &smarker,
2989 Coefficient &coeff,
2991{
2992 // To have both we must duplicate the markers.
2993 MFEM_VERIFY(surf_fit_pos == NULL,
2994 "Using both fitting approaches is not supported.");
2995
2996 delete surf_fit_gf;
2997 surf_fit_gf = new GridFunction(s0);
2999 surf_fit_marker = &smarker;
3000 surf_fit_coeff = &coeff;
3001 surf_fit_eval = &ae;
3002
3004 *s0.ParFESpace());
3007 surf_fit_gf_bg = false;
3008}
3009
3011 const ParGridFunction &s_bg, ParGridFunction &s0,
3012 const Array<bool> &smarker, Coefficient &coeff, AdaptivityEvaluator &ae,
3013 const ParGridFunction &s_bg_grad,
3014 ParGridFunction &s0_grad, AdaptivityEvaluator &age,
3015 const ParGridFunction &s_bg_hess,
3016 ParGridFunction &s0_hess, AdaptivityEvaluator &ahe)
3017{
3018#ifndef MFEM_USE_GSLIB
3019 MFEM_ABORT("Surface fitting from source requires GSLIB!");
3020#endif
3021
3022 // Setup for level set function
3023 delete surf_fit_gf;
3024 surf_fit_gf = new GridFunction(s0);
3025 *surf_fit_gf = 0.0;
3026 surf_fit_marker = &smarker;
3027 surf_fit_coeff = &coeff;
3028 surf_fit_eval = &ae;
3029
3030 surf_fit_gf_bg = true;
3032 *s_bg.ParFESpace());
3034 (*s_bg.FESpace()->GetMesh()->GetNodes(), s_bg);
3035
3036 // Setup for gradient on background mesh
3037 MFEM_VERIFY(s_bg_grad.ParFESpace()->GetOrdering() ==
3038 s0_grad.ParFESpace()->GetOrdering(),
3039 "Nodal ordering for gridfunction on source mesh and current mesh"
3040 "should be the same.");
3041 delete surf_fit_grad;
3042 surf_fit_grad = new GridFunction(s0_grad);
3043 *surf_fit_grad = 0.0;
3044 surf_fit_eval_bg_grad = &age;
3045 surf_fit_eval_bg_hess = &ahe;
3047 *s_bg_grad.ParFESpace());
3049 (*s_bg_grad.FESpace()->GetMesh()->GetNodes(), s_bg_grad);
3050
3051 // Setup for Hessian on background mesh
3052 MFEM_VERIFY(s_bg_hess.ParFESpace()->GetOrdering() ==
3053 s0_hess.ParFESpace()->GetOrdering(),
3054 "Nodal ordering for gridfunction on source mesh and current mesh"
3055 "should be the same.");
3056 delete surf_fit_hess;
3057 surf_fit_hess = new GridFunction(s0_hess);
3058 *surf_fit_hess = 0.0;
3060 *s_bg_hess.ParFESpace());
3062 (*s_bg_hess.FESpace()->GetMesh()->GetNodes(), s_bg_hess);
3063
3064 // Count number of zones that share each of the DOFs
3066 // Store DOF indices that are marked for fitting. Used to reduce work for
3067 // transferring information between source/background and current mesh.
3069 for (int i = 0; i < surf_fit_marker->Size(); i++)
3070 {
3071 if ((*surf_fit_marker)[i] == true)
3072 {
3074 }
3075 }
3076}
3077#endif
3078
3080 real_t &err_avg, real_t &err_max)
3081{
3082 MFEM_VERIFY(surf_fit_marker, "Surface fitting has not been enabled.");
3083
3084 const FiniteElementSpace *fes =
3086#ifdef MFEM_USE_MPI
3087 auto pfes = dynamic_cast<const ParFiniteElementSpace *>(fes);
3088 bool parallel = (pfes) ? true : false;
3089#endif
3090
3091 int dim = fes->GetMesh()->Dimension();
3092 const int node_cnt = surf_fit_marker->Size();
3093 err_max = 0.0;
3094 int dof_cnt = 0;
3095 real_t err_sum = 0.0;
3096 for (int i = 0; i < node_cnt; i++)
3097 {
3098 if ((*surf_fit_marker)[i] == false) { continue; }
3099
3100#ifdef MFEM_USE_MPI
3101 // Don't count the overlapping DOFs in parallel.
3102 // The pfes might be ordered byVDIM, while the loop goes consecutively.
3103 const int dof_i = pfes->DofToVDof(i, 0);
3104 if (parallel && pfes->GetLocalTDofNumber(dof_i) < 0) { continue; }
3105#endif
3106
3107 dof_cnt++;
3108 real_t sigma_s = 0.0;
3109 if (surf_fit_gf) { sigma_s = fabs((*surf_fit_gf)(i)); }
3110 if (surf_fit_pos)
3111 {
3112 Vector pos_s(dim), pos_s_target(dim);
3113 for (int d = 0; d < dim; d++)
3114 {
3115 pos_s(d) = (fes->GetOrdering() == Ordering::byNODES) ?
3116 pos(d*node_cnt + i) : pos(i*dim + d);
3117 pos_s_target(d) = (fes->GetOrdering() == Ordering::byNODES)
3118 ? (*surf_fit_pos)(d*node_cnt + i)
3119 : (*surf_fit_pos)(i*dim + d);
3120 }
3121 sigma_s = pos_s.DistanceTo(pos_s_target);
3122 }
3123
3124 err_max = std::max(err_max, sigma_s);
3125 err_sum += sigma_s;
3126 }
3127
3128#ifdef MFEM_USE_MPI
3129 if (parallel)
3130 {
3131 MPI_Comm comm = pfes->GetComm();
3132 MPI_Allreduce(MPI_IN_PLACE, &err_max, 1, MPITypeMap<real_t>::mpi_type, MPI_MAX,
3133 comm);
3134 MPI_Allreduce(MPI_IN_PLACE, &dof_cnt, 1, MPI_INT, MPI_SUM, comm);
3135 MPI_Allreduce(MPI_IN_PLACE, &err_sum, 1, MPITypeMap<real_t>::mpi_type, MPI_SUM,
3136 comm);
3137 }
3138#endif
3139
3140 err_avg = (dof_cnt > 0) ? err_sum / dof_cnt : 0.0;
3141}
3142
3154
3155#ifdef MFEM_USE_MPI
3167#endif
3168
3171 const Vector &elfun)
3172{
3173 const int dof = el.GetDof(), dim = el.GetDim();
3174 const int el_id = T.ElementNo;
3175 real_t energy;
3176
3177 // No adaptive limiting / surface fitting terms if the function is called
3178 // as part of a FD derivative computation (because we include the exact
3179 // derivatives of these terms in FD computations).
3180 const bool adaptive_limiting = (adapt_lim_gf && fd_call_flag == false);
3181 const bool surface_fit = (surf_fit_marker && fd_call_flag == false);
3182
3183 DSh.SetSize(dof, dim);
3184 Jrt.SetSize(dim);
3185 Jpr.SetSize(dim);
3186 Jpt.SetSize(dim);
3187 PMatI.UseExternalData(elfun.GetData(), dof, dim);
3188
3190
3191 energy = 0.0;
3193 targetC->ComputeElementTargets(el_id, el, ir, elfun, Jtr);
3194
3195 // Limited case.
3196 Vector shape, p, p0, d_vals;
3197 DenseMatrix pos0;
3198 if (lim_coeff)
3199 {
3200 shape.SetSize(dof);
3201 p.SetSize(dim);
3202 p0.SetSize(dim);
3203 pos0.SetSize(dof, dim);
3204 Vector pos0V(pos0.Data(), dof * dim);
3205 Array<int> pos_dofs;
3206 lim_nodes0->FESpace()->GetElementVDofs(el_id, pos_dofs);
3207 lim_nodes0->GetSubVector(pos_dofs, pos0V);
3208 if (lim_dist)
3209 {
3210 lim_dist->GetValues(el_id, ir, d_vals);
3211 }
3212 else
3213 {
3214 d_vals.SetSize(ir.GetNPoints()); d_vals = 1.0;
3215 }
3216 }
3217
3218 // Define ref->physical transformation, when a Coefficient is specified.
3219 IsoparametricTransformation *Tpr = NULL;
3220 if (metric_coeff || lim_coeff || adaptive_limiting || surface_fit)
3221 {
3223 Tpr->SetFE(&el);
3224 Tpr->ElementNo = el_id;
3226 Tpr->Attribute = T.Attribute;
3227 Tpr->mesh = T.mesh;
3228 Tpr->GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
3229 }
3230 // TODO: computing the coefficients 'metric_coeff' and 'lim_coeff' in physical
3231 // coordinates means that, generally, the gradient and Hessian of the
3232 // TMOP_Integrator will depend on the derivatives of the coefficients.
3233 //
3234 // In some cases the coefficients are independent of any movement of
3235 // the physical coordinates (i.e. changes in 'elfun'), e.g. when the
3236 // coefficient is a ConstantCoefficient or a GridFunctionCoefficient.
3237
3238 Vector adapt_lim_gf_q, adapt_lim_gf0_q;
3239 if (adaptive_limiting)
3240 {
3241 adapt_lim_gf->GetValues(el_id, ir, adapt_lim_gf_q);
3242 adapt_lim_gf0->GetValues(el_id, ir, adapt_lim_gf0_q);
3243 }
3244
3245 for (int i = 0; i < ir.GetNPoints(); i++)
3246 {
3247 const IntegrationPoint &ip = ir.IntPoint(i);
3248
3250 CalcInverse(Jtr(i), Jrt);
3251 const real_t weight =
3252 (integ_over_target) ? ip.weight * Jtr(i).Det() : ip.weight;
3253
3254 el.CalcDShape(ip, DSh);
3255 MultAtB(PMatI, DSh, Jpr);
3256 Mult(Jpr, Jrt, Jpt);
3257
3259 if (metric_coeff) { val *= metric_coeff->Eval(*Tpr, ip); }
3260
3261 if (lim_coeff)
3262 {
3263 el.CalcShape(ip, shape);
3264 PMatI.MultTranspose(shape, p);
3265 pos0.MultTranspose(shape, p0);
3266 val += lim_normal *
3267 lim_func->Eval(p, p0, d_vals(i)) *
3268 lim_coeff->Eval(*Tpr, ip);
3269 }
3270
3271 // Contribution from the adaptive limiting term.
3272 if (adaptive_limiting)
3273 {
3274 const real_t diff = adapt_lim_gf_q(i) - adapt_lim_gf0_q(i);
3275 val += adapt_lim_coeff->Eval(*Tpr, ip) * lim_normal * diff * diff;
3276 }
3277
3278 energy += weight * val;
3279 }
3280
3281 // Contribution from the surface fitting term.
3282 if (surface_fit)
3283 {
3284 // Scalar for surf_fit_gf, vector for surf_fit_pos, but that's ok.
3285 const FiniteElementSpace *fes_fit =
3287 const IntegrationRule *ir_s = &fes_fit->GetFE(el_id)->GetNodes();
3288 Array<int> vdofs;
3289 fes_fit->GetElementVDofs(el_id, vdofs);
3290
3291 Vector sigma_e(dof);
3292 if (surf_fit_gf) { surf_fit_gf->GetSubVector(vdofs, sigma_e); }
3293
3294 for (int s = 0; s < dof; s++)
3295 {
3296 // Because surf_fit_pos.fes might be ordered byVDIM.
3297 const int scalar_dof_id = fes_fit->VDofToDof(vdofs[s]);
3298 if ((*surf_fit_marker)[scalar_dof_id] == false) { continue; }
3299
3300 const IntegrationPoint &ip_s = ir_s->IntPoint(s);
3301 Tpr->SetIntPoint(&ip_s);
3302
3303 if (surf_fit_gf)
3304 {
3305 energy += surf_fit_coeff->Eval(*Tpr, ip_s) * surf_fit_normal *
3306 sigma_e(s) * sigma_e(s);
3307 }
3308 if (surf_fit_pos)
3309 {
3310 // Fitting to exact positions.
3311 Vector pos(dim), pos_target(dim);
3312 for (int d = 0; d < dim; d++)
3313 {
3314 pos(d) = PMatI(s, d);
3315 pos_target(d) = (*surf_fit_pos)(vdofs[d*dof + s]);
3316 }
3317 energy += surf_fit_coeff->Eval(*Tpr, ip_s) * surf_fit_normal *
3318 surf_fit_limiter->Eval(pos, pos_target, 1.0);
3319 }
3320 }
3321 }
3322
3323 delete Tpr;
3324 return energy;
3325}
3326
3329 const Vector &elfun,
3330 const IntegrationRule &irule)
3331{
3332 int dof = el.GetDof(), dim = el.GetDim(),
3333 NEsplit = elfun.Size() / (dof*dim), el_id = T.ElementNo;
3334 real_t energy = 0.;
3335
3336 TargetConstructor *tc = const_cast<TargetConstructor *>(targetC);
3337 DiscreteAdaptTC *dtc = dynamic_cast<DiscreteAdaptTC *>(tc);
3338 // For DiscreteAdaptTC the GridFunctions used to set the targets must be
3339 // mapped onto the fine elements.
3340 if (dtc) { dtc->SetTspecFromIntRule(el_id, irule); }
3341
3342 for (int e = 0; e < NEsplit; e++)
3343 {
3344 DSh.SetSize(dof, dim);
3345 Jrt.SetSize(dim);
3346 Jpr.SetSize(dim);
3347 Jpt.SetSize(dim);
3348 Vector elfun_child(dof*dim);
3349 for (int i = 0; i < dof; i++)
3350 {
3351 for (int d = 0; d < dim; d++)
3352 {
3353 // elfun is (xe1,xe2,...xen,ye1,ye2...yen) and has nodal coordinates
3354 // for all the children element of the parent element being considered.
3355 // So we must index and get (xek, yek) i.e. nodal coordinates for
3356 // the fine element being considered.
3357 elfun_child(i + d*dof) = elfun(i + e*dof + d*dof*NEsplit);
3358 }
3359 }
3360 PMatI.UseExternalData(elfun_child.GetData(), dof, dim);
3361
3363
3364 real_t el_energy = 0;
3366 if (dtc)
3367 {
3368 // This is used to index into the tspec vector inside DiscreteAdaptTC.
3370 }
3371 targetC->ComputeElementTargets(el_id, el, ir, elfun_child, Jtr);
3372
3373 // Define ref->physical transformation, wn a Coefficient is specified.
3374 IsoparametricTransformation *Tpr = NULL;
3375 if (metric_coeff || lim_coeff)
3376 {
3378 Tpr->SetFE(&el);
3379 Tpr->ElementNo = T.ElementNo;
3381 Tpr->Attribute = T.Attribute;
3382 Tpr->mesh = T.mesh;
3383 Tpr->GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
3384 }
3385
3386 for (int i = 0; i < ir.GetNPoints(); i++)
3387 {
3388 const IntegrationPoint &ip = ir.IntPoint(i);
3390 CalcInverse(Jtr(i), Jrt);
3391 const real_t weight =
3392 (integ_over_target) ? ip.weight * Jtr(i).Det() : ip.weight;
3393
3394 el.CalcDShape(ip, DSh);
3395 MultAtB(PMatI, DSh, Jpr);
3396 Mult(Jpr, Jrt, Jpt);
3397
3399 if (metric_coeff) { val *= metric_coeff->Eval(*Tpr, ip); }
3400
3401 el_energy += weight * val;
3402 delete Tpr;
3403 }
3404 energy += el_energy;
3405 }
3406 energy /= NEsplit;
3407
3408 if (dtc) { dtc->ResetRefinementTspecData(); }
3409
3410 return energy;
3411}
3412
3415 const Vector &elfun)
3416{
3417 int dof = el.GetDof(), dim = el.GetDim();
3418 real_t energy = 0.;
3419
3420 DSh.SetSize(dof, dim);
3421 Jrt.SetSize(dim);
3422 Jpr.SetSize(dim);
3423 Jpt.SetSize(dim);
3424 PMatI.UseExternalData(elfun.GetData(), dof, dim);
3425
3427
3428 energy = 0.0;
3430 targetC->ComputeElementTargets(T.ElementNo, el, ir, elfun, Jtr);
3431
3432 // Define ref->physical transformation, wn a Coefficient is specified.
3433 IsoparametricTransformation *Tpr = NULL;
3434 if (metric_coeff)
3435 {
3437 Tpr->SetFE(&el);
3438 Tpr->ElementNo = T.ElementNo;
3440 Tpr->Attribute = T.Attribute;
3441 Tpr->mesh = T.mesh;
3442 Tpr->GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
3443 }
3444
3445 for (int i = 0; i < ir.GetNPoints(); i++)
3446 {
3447 const IntegrationPoint &ip = ir.IntPoint(i);
3449 CalcInverse(Jtr(i), Jrt);
3450 const real_t weight =
3451 (integ_over_target) ? ip.weight * Jtr(i).Det() : ip.weight;
3452
3453 el.CalcDShape(ip, DSh);
3454 MultAtB(PMatI, DSh, Jpr);
3455 Mult(Jpr, Jrt, Jpt);
3456
3458 if (metric_coeff) { val *= metric_coeff->Eval(*Tpr, ip); }
3459
3460 energy += weight * val;
3461 }
3462
3463 delete Tpr;
3464 return energy;
3465}
3466
3469 const Vector &elfun, Vector &elvect)
3470{
3471 if (!fdflag)
3472 {
3473 AssembleElementVectorExact(el, T, elfun, elvect);
3474 }
3475 else
3476 {
3477 AssembleElementVectorFD(el, T, elfun, elvect);
3478 }
3479}
3480
3483 const Vector &elfun,
3484 DenseMatrix &elmat)
3485{
3486 if (!fdflag)
3487 {
3488 AssembleElementGradExact(el, T, elfun, elmat);
3489 }
3490 else
3491 {
3492 AssembleElementGradFD(el, T, elfun, elmat);
3493 }
3494}
3495
3498 const Vector &elfun,
3499 Vector &elvect)
3500{
3501 const int dof = el.GetDof(), dim = el.GetDim();
3502
3503 DenseMatrix Amat(dim), work1(dim), work2(dim);
3504 DSh.SetSize(dof, dim);
3505 DS.SetSize(dof, dim);
3506 Jrt.SetSize(dim);
3507 Jpt.SetSize(dim);
3508 P.SetSize(dim);
3509 PMatI.UseExternalData(elfun.GetData(), dof, dim);
3510 elvect.SetSize(dof*dim);
3511 PMatO.UseExternalData(elvect.GetData(), dof, dim);
3512
3514 const int nqp = ir.GetNPoints();
3515
3516 elvect = 0.0;
3517 Vector weights(nqp);
3518 DenseTensor Jtr(dim, dim, nqp);
3519 DenseTensor dJtr(dim, dim, dim*nqp);
3520 targetC->ComputeElementTargets(T.ElementNo, el, ir, elfun, Jtr);
3521
3522 // Limited case.
3523 DenseMatrix pos0;
3524 Vector shape, p, p0, d_vals, grad;
3525 shape.SetSize(dof);
3526 if (lim_coeff)
3527 {
3528 p.SetSize(dim);
3529 p0.SetSize(dim);
3530 pos0.SetSize(dof, dim);
3531 Vector pos0V(pos0.Data(), dof * dim);
3532 Array<int> pos_dofs;
3534 lim_nodes0->GetSubVector(pos_dofs, pos0V);
3535 if (lim_dist)
3536 {
3537 lim_dist->GetValues(T.ElementNo, ir, d_vals);
3538 }
3539 else
3540 {
3541 d_vals.SetSize(nqp); d_vals = 1.0;
3542 }
3543 }
3544
3545 // Define ref->physical transformation, when a Coefficient is specified.
3546 IsoparametricTransformation *Tpr = NULL;
3549 {
3551 Tpr->SetFE(&el);
3552 Tpr->ElementNo = T.ElementNo;
3554 Tpr->Attribute = T.Attribute;
3555 Tpr->mesh = T.mesh;
3556 Tpr->GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
3557 if (exact_action)
3558 {
3559 targetC->ComputeElementTargetsGradient(ir, elfun, *Tpr, dJtr);
3560 }
3561 }
3562
3563 Vector d_detW_dx(dim);
3564 Vector d_Winv_dx(dim);
3565
3566 for (int q = 0; q < nqp; q++)
3567 {
3568 const IntegrationPoint &ip = ir.IntPoint(q);
3570 CalcInverse(Jtr(q), Jrt);
3571 weights(q) = (integ_over_target) ? ip.weight * Jtr(q).Det() : ip.weight;
3572 real_t weight_m = weights(q) * metric_normal;
3573
3574 el.CalcDShape(ip, DSh);
3575 Mult(DSh, Jrt, DS);
3576 MultAtB(PMatI, DS, Jpt);
3577
3578 metric->EvalP(Jpt, P);
3579
3580 if (metric_coeff) { weight_m *= metric_coeff->Eval(*Tpr, ip); }
3581
3582 P *= weight_m;
3583 AddMultABt(DS, P, PMatO); // w_q det(W) dmu/dx : dA/dx Winv
3584
3585 if (exact_action)
3586 {
3587 el.CalcShape(ip, shape);
3588 // Derivatives of adaptivity-based targets.
3589 // First term: w_q d*(Det W)/dx * mu(T)
3590 // d(Det W)/dx = det(W)*Tr[Winv*dW/dx]
3591 DenseMatrix dwdx(dim);
3592 for (int d = 0; d < dim; d++)
3593 {
3594 const DenseMatrix &dJtr_q = dJtr(q + d * nqp);
3595 Mult(Jrt, dJtr_q, dwdx );
3596 d_detW_dx(d) = dwdx.Trace();
3597 }
3598 d_detW_dx *= weight_m*metric->EvalW(Jpt); // *[w_q*det(W)]*mu(T)
3599
3600 // Second term: w_q det(W) dmu/dx : AdWinv/dx
3601 // dWinv/dx = -Winv*dW/dx*Winv
3602 MultAtB(PMatI, DSh, Amat);
3603 for (int d = 0; d < dim; d++)
3604 {
3605 const DenseMatrix &dJtr_q = dJtr(q + d*nqp);
3606 Mult(Jrt, dJtr_q, work1); // Winv*dw/dx
3607 Mult(work1, Jrt, work2); // Winv*dw/dx*Winv
3608 Mult(Amat, work2, work1); // A*Winv*dw/dx*Winv
3609 MultAtB(P, work1, work2); // dmu/dT^T*A*Winv*dw/dx*Winv
3610 d_Winv_dx(d) = work2.Trace(); // Tr[dmu/dT : AWinv*dw/dx*Winv]
3611 }
3612 d_Winv_dx *= -weight_m; // Include (-) factor as well
3613
3614 d_detW_dx += d_Winv_dx;
3615 AddMultVWt(shape, d_detW_dx, PMatO);
3616 }
3617
3618 if (lim_coeff)
3619 {
3620 if (!exact_action) { el.CalcShape(ip, shape); }
3621 PMatI.MultTranspose(shape, p);
3622 pos0.MultTranspose(shape, p0);
3623 lim_func->Eval_d1(p, p0, d_vals(q), grad);
3624 grad *= weights(q) * lim_normal * lim_coeff->Eval(*Tpr, ip);
3625 AddMultVWt(shape, grad, PMatO);
3626 }
3627 }
3628
3629 if (adapt_lim_gf) { AssembleElemVecAdaptLim(el, *Tpr, ir, weights, PMatO); }
3631
3632 delete Tpr;
3633}
3634
3637 const Vector &elfun,
3638 DenseMatrix &elmat)
3639{
3640 const int dof = el.GetDof(), dim = el.GetDim();
3641
3642 DSh.SetSize(dof, dim);
3643 DS.SetSize(dof, dim);
3644 Jrt.SetSize(dim);
3645 Jpt.SetSize(dim);
3646 PMatI.UseExternalData(elfun.GetData(), dof, dim);
3647 elmat.SetSize(dof*dim);
3648
3650 const int nqp = ir.GetNPoints();
3651
3652 elmat = 0.0;
3653 Vector weights(nqp);
3654 DenseTensor Jtr(dim, dim, nqp);
3655 targetC->ComputeElementTargets(T.ElementNo, el, ir, elfun, Jtr);
3656
3657 // Limited case.
3658 DenseMatrix pos0, hess;
3659 Vector shape, p, p0, d_vals;
3660 if (lim_coeff)
3661 {
3662 shape.SetSize(dof);
3663 p.SetSize(dim);
3664 p0.SetSize(dim);
3665 pos0.SetSize(dof, dim);
3666 Vector pos0V(pos0.Data(), dof * dim);
3667 Array<int> pos_dofs;
3669 lim_nodes0->GetSubVector(pos_dofs, pos0V);
3670 if (lim_dist)
3671 {
3672 lim_dist->GetValues(T.ElementNo, ir, d_vals);
3673 }
3674 else
3675 {
3676 d_vals.SetSize(nqp); d_vals = 1.0;
3677 }
3678 }
3679
3680 // Define ref->physical transformation, when a Coefficient is specified.
3681 IsoparametricTransformation *Tpr = NULL;
3683 {
3685 Tpr->SetFE(&el);
3686 Tpr->ElementNo = T.ElementNo;
3688 Tpr->Attribute = T.Attribute;
3689 Tpr->mesh = T.mesh;
3690 Tpr->GetPointMat().Transpose(PMatI);
3691 }
3692
3693 for (int q = 0; q < nqp; q++)
3694 {
3695 const IntegrationPoint &ip = ir.IntPoint(q);
3696 const DenseMatrix &Jtr_q = Jtr(q);
3697 metric->SetTargetJacobian(Jtr_q);
3698 CalcInverse(Jtr_q, Jrt);
3699 weights(q) = (integ_over_target) ? ip.weight * Jtr_q.Det() : ip.weight;
3700 real_t weight_m = weights(q) * metric_normal;
3701
3702 el.CalcDShape(ip, DSh);
3703 Mult(DSh, Jrt, DS);
3704 MultAtB(PMatI, DS, Jpt);
3705
3706 if (metric_coeff) { weight_m *= metric_coeff->Eval(*Tpr, ip); }
3707
3708 metric->AssembleH(Jpt, DS, weight_m, elmat);
3709
3710 // TODO: derivatives of adaptivity-based targets.
3711
3712 if (lim_coeff)
3713 {
3714 el.CalcShape(ip, shape);
3715 PMatI.MultTranspose(shape, p);
3716 pos0.MultTranspose(shape, p0);
3717 weight_m = weights(q) * lim_normal * lim_coeff->Eval(*Tpr, ip);
3718 lim_func->Eval_d2(p, p0, d_vals(q), hess);
3719 for (int i = 0; i < dof; i++)
3720 {
3721 const real_t w_shape_i = weight_m * shape(i);
3722 for (int j = 0; j < dof; j++)
3723 {
3724 const real_t w = w_shape_i * shape(j);
3725 for (int d1 = 0; d1 < dim; d1++)
3726 {
3727 for (int d2 = 0; d2 < dim; d2++)
3728 {
3729 elmat(d1*dof + i, d2*dof + j) += w * hess(d1, d2);
3730 }
3731 }
3732 }
3733 }
3734 }
3735 }
3736
3737 if (adapt_lim_gf) { AssembleElemGradAdaptLim(el, *Tpr, ir, weights, elmat); }
3738 if (surf_fit_gf || surf_fit_pos) { AssembleElemGradSurfFit(el, *Tpr, elmat);}
3739
3740 delete Tpr;
3741}
3742
3745 const IntegrationRule &ir,
3746 const Vector &weights,
3747 DenseMatrix &mat)
3748{
3749 const int dof = el.GetDof(), dim = el.GetDim(), nqp = weights.Size();
3750 Vector shape(dof), adapt_lim_gf_e, adapt_lim_gf_q, adapt_lim_gf0_q(nqp);
3751
3752 Array<int> dofs;
3754 adapt_lim_gf->GetSubVector(dofs, adapt_lim_gf_e);
3755 adapt_lim_gf->GetValues(Tpr.ElementNo, ir, adapt_lim_gf_q);
3756 adapt_lim_gf0->GetValues(Tpr.ElementNo, ir, adapt_lim_gf0_q);
3757
3758 // Project the gradient of adapt_lim_gf in the same space.
3759 // The FE coefficients of the gradient go in adapt_lim_gf_grad_e.
3760 DenseMatrix adapt_lim_gf_grad_e(dof, dim);
3761 DenseMatrix grad_phys; // This will be (dof x dim, dof).
3762 el.ProjectGrad(el, Tpr, grad_phys);
3763 Vector grad_ptr(adapt_lim_gf_grad_e.GetData(), dof*dim);
3764 grad_phys.Mult(adapt_lim_gf_e, grad_ptr);
3765
3766 Vector adapt_lim_gf_grad_q(dim);
3767
3768 for (int q = 0; q < nqp; q++)
3769 {
3770 const IntegrationPoint &ip = ir.IntPoint(q);
3771 el.CalcShape(ip, shape);
3772 adapt_lim_gf_grad_e.MultTranspose(shape, adapt_lim_gf_grad_q);
3773 adapt_lim_gf_grad_q *= 2.0 * (adapt_lim_gf_q(q) - adapt_lim_gf0_q(q));
3774 adapt_lim_gf_grad_q *= weights(q) * lim_normal * adapt_lim_coeff->Eval(Tpr, ip);
3775 AddMultVWt(shape, adapt_lim_gf_grad_q, mat);
3776 }
3777}
3778
3781 const IntegrationRule &ir,
3782 const Vector &weights,
3783 DenseMatrix &mat)
3784{
3785 const int dof = el.GetDof(), dim = el.GetDim(), nqp = weights.Size();
3786 Vector shape(dof), adapt_lim_gf_e, adapt_lim_gf_q, adapt_lim_gf0_q(nqp);
3787
3788 Array<int> dofs;
3790 adapt_lim_gf->GetSubVector(dofs, adapt_lim_gf_e);
3791 adapt_lim_gf->GetValues(Tpr.ElementNo, ir, adapt_lim_gf_q);
3792 adapt_lim_gf0->GetValues(Tpr.ElementNo, ir, adapt_lim_gf0_q);
3793
3794 // Project the gradient of adapt_lim_gf in the same space.
3795 // The FE coefficients of the gradient go in adapt_lim_gf_grad_e.
3796 DenseMatrix adapt_lim_gf_grad_e(dof, dim);
3797 DenseMatrix grad_phys; // This will be (dof x dim, dof).
3798 el.ProjectGrad(el, Tpr, grad_phys);
3799 Vector grad_ptr(adapt_lim_gf_grad_e.GetData(), dof*dim);
3800 grad_phys.Mult(adapt_lim_gf_e, grad_ptr);
3801
3802 // Project the gradient of each gradient of adapt_lim_gf in the same space.
3803 // The FE coefficients of the second derivatives go in adapt_lim_gf_hess_e.
3804 DenseMatrix adapt_lim_gf_hess_e(dof*dim, dim);
3805 Mult(grad_phys, adapt_lim_gf_grad_e, adapt_lim_gf_hess_e);
3806 // Reshape to be more convenient later (no change in the data).
3807 adapt_lim_gf_hess_e.SetSize(dof, dim*dim);
3808
3809 Vector adapt_lim_gf_grad_q(dim);
3810 DenseMatrix adapt_lim_gf_hess_q(dim, dim);
3811
3812 for (int q = 0; q < nqp; q++)
3813 {
3814 const IntegrationPoint &ip = ir.IntPoint(q);
3815 el.CalcShape(ip, shape);
3816
3817 adapt_lim_gf_grad_e.MultTranspose(shape, adapt_lim_gf_grad_q);
3818 Vector gg_ptr(adapt_lim_gf_hess_q.GetData(), dim*dim);
3819 adapt_lim_gf_hess_e.MultTranspose(shape, gg_ptr);
3820
3821 const real_t w = weights(q) * lim_normal * adapt_lim_coeff->Eval(Tpr, ip);
3822 for (int i = 0; i < dof * dim; i++)
3823 {
3824 const int idof = i % dof, idim = i / dof;
3825 for (int j = 0; j <= i; j++)
3826 {
3827 const int jdof = j % dof, jdim = j / dof;
3828 const real_t entry =
3829 w * ( 2.0 * adapt_lim_gf_grad_q(idim) * shape(idof) *
3830 /* */ adapt_lim_gf_grad_q(jdim) * shape(jdof) +
3831 2.0 * (adapt_lim_gf_q(q) - adapt_lim_gf0_q(q)) *
3832 adapt_lim_gf_hess_q(idim, jdim) * shape(idof) * shape(jdof));
3833 mat(i, j) += entry;
3834 if (i != j) { mat(j, i) += entry; }
3835 }
3836 }
3837 }
3838}
3839
3842 DenseMatrix &mat)
3843{
3844 const int el_id = Tpr.ElementNo;
3845
3846 // Scalar for surf_fit_gf, vector for surf_fit_pos, but that's ok.
3847 const FiniteElementSpace *fes_fit =
3849 const FiniteElement &el_s = *fes_fit->GetFE(el_id);
3850 const int dof_s = el_s.GetDof(), dim = el_x.GetDim();
3851
3852 // Check if the element has any DOFs marked for surface fitting.
3853 Array<int> dofs, vdofs;
3854 fes_fit->GetElementVDofs(el_id, vdofs);
3855 int count = 0;
3856 for (int s = 0; s < dof_s; s++)
3857 {
3858 // Because surf_fit_pos.fes might be ordered byVDIM.
3859 const int scalar_dof_id = fes_fit->VDofToDof(vdofs[s]);
3860 count += ((*surf_fit_marker)[scalar_dof_id]) ? 1 : 0;
3861 }
3862 if (count == 0) { return; }
3863
3864 Vector sigma_e(dof_s);
3865 DenseMatrix surf_fit_grad_e(dof_s, dim);
3867 {
3868 surf_fit_gf->GetSubVector(vdofs, sigma_e);
3869
3870 // Project the gradient of sigma in the same space.
3871 // The FE coefficients of the gradient go in surf_fit_grad_e.
3872 Vector grad_ptr(surf_fit_grad_e.GetData(), dof_s * dim);
3873 DenseMatrix grad_phys; // This will be (dof x dim, dof).
3874 if (surf_fit_gf_bg)
3875 {
3876 surf_fit_grad->FESpace()->GetElementVDofs(el_id, dofs);
3877 surf_fit_grad->GetSubVector(dofs, grad_ptr);
3878 }
3879 else
3880 {
3881 el_s.ProjectGrad(el_s, Tpr, grad_phys);
3882 grad_phys.Mult(sigma_e, grad_ptr);
3883 }
3884 }
3885 else { Tpr.GetPointMat().Transpose(PMatI); }
3886
3887 const IntegrationRule &ir = el_s.GetNodes();
3888
3889 for (int s = 0; s < dof_s; s++)
3890 {
3891 // Because surf_fit_pos.fes might be ordered byVDIM.
3892 const int scalar_dof_id = fes_fit->VDofToDof(vdofs[s]);
3893 if ((*surf_fit_marker)[scalar_dof_id] == false) { continue; }
3894
3895 const IntegrationPoint &ip = ir.IntPoint(s);
3896 Tpr.SetIntPoint(&ip);
3897 real_t w = surf_fit_normal * surf_fit_coeff->Eval(Tpr, ip) *
3898 1.0 / surf_fit_dof_count[vdofs[s]];
3899
3900 if (surf_fit_gf) { w *= 2.0 * sigma_e(s); }
3901 if (surf_fit_pos)
3902 {
3903 Vector pos(dim), pos_target(dim);
3904 for (int d = 0; d < dim; d++)
3905 {
3906 pos(d) = PMatI(s, d);
3907 pos_target(d) = (*surf_fit_pos)(vdofs[d*dof_s + s]);
3908 }
3909 Vector grad_s(dim);
3910 surf_fit_limiter->Eval_d1(pos, pos_target, 1.0, grad_s);
3911 for (int d = 0; d < dim; d++) { surf_fit_grad_e(s, d) = grad_s(d); }
3912 }
3913
3914 for (int d = 0; d < dim; d++)
3915 {
3916 mat(s, d) += w * surf_fit_grad_e(s, d);
3917 }
3918 }
3919}
3920
3923 DenseMatrix &mat)
3924{
3925 const int el_id = Tpr.ElementNo;
3926
3927 // Scalar for surf_fit_gf, vector for surf_fit_pos, but that's ok.
3928 const FiniteElementSpace *fes_fit =
3930 const FiniteElement &el_s = *fes_fit->GetFE(el_id);
3931 const int dof_s = el_s.GetDof(), dim = el_x.GetDim();
3932
3933 // Check if the element has any DOFs marked for surface fitting.
3934 Array<int> dofs, vdofs;
3935 fes_fit->GetElementVDofs(el_id, vdofs);
3936 int count = 0;
3937 for (int s = 0; s < dof_s; s++)
3938 {
3939 // Because surf_fit_pos.fes might be ordered byVDIM.
3940 const int scalar_dof_id = fes_fit->VDofToDof(vdofs[s]);
3941 count += ((*surf_fit_marker)[scalar_dof_id]) ? 1 : 0;
3942 }
3943 if (count == 0) { return; }
3944
3945 Vector sigma_e(dof_s);
3946 DenseMatrix surf_fit_grad_e(dof_s, dim);
3947 DenseMatrix surf_fit_hess_e(dof_s, dim*dim);
3949 {
3950 surf_fit_gf->GetSubVector(vdofs, sigma_e);
3951
3952 // Project the gradient of sigma in the same space.
3953 // The FE coefficients of the gradient go in surf_fit_grad_e.
3954 Vector grad_ptr(surf_fit_grad_e.GetData(), dof_s * dim);
3955 DenseMatrix grad_phys; // This will be (dof x dim, dof).
3956 if (surf_fit_gf_bg)
3957 {
3958 surf_fit_grad->FESpace()->GetElementVDofs(el_id, dofs);
3959 surf_fit_grad->GetSubVector(dofs, grad_ptr);
3960 }
3961 else
3962 {
3963 el_s.ProjectGrad(el_s, Tpr, grad_phys);
3964 grad_phys.Mult(sigma_e, grad_ptr);
3965 }
3966
3967 // Project the Hessian of sigma in the same space.
3968 // The FE coefficients of the Hessian go in surf_fit_hess_e.
3969 Vector hess_ptr(surf_fit_hess_e.GetData(), dof_s*dim*dim);
3970 if (surf_fit_gf_bg)
3971 {
3972 surf_fit_hess->FESpace()->GetElementVDofs(el_id, dofs);
3973 surf_fit_hess->GetSubVector(dofs, hess_ptr);
3974 }
3975 else
3976 {
3977 surf_fit_hess_e.SetSize(dof_s*dim, dim);
3978 Mult(grad_phys, surf_fit_grad_e, surf_fit_hess_e);
3979 surf_fit_hess_e.SetSize(dof_s, dim * dim);
3980 }
3981 }
3982 else { Tpr.GetPointMat().Transpose(PMatI); }
3983
3984 const IntegrationRule &ir = el_s.GetNodes();
3985
3986 DenseMatrix surf_fit_hess_s(dim, dim);
3987 for (int s = 0; s < dof_s; s++)
3988 {
3989 // Because surf_fit_pos.fes might be ordered byVDIM.
3990 const int scalar_dof_id = fes_fit->VDofToDof(vdofs[s]);
3991 if ((*surf_fit_marker)[scalar_dof_id] == false) { continue; }
3992
3993 const IntegrationPoint &ip = ir.IntPoint(s);
3994 Tpr.SetIntPoint(&ip);
3995 real_t w = surf_fit_normal * surf_fit_coeff->Eval(Tpr, ip);
3996
3998 {
3999 Vector gg_ptr(surf_fit_hess_s.GetData(), dim * dim);
4000 surf_fit_hess_e.GetRow(s, gg_ptr);
4001 w *= 2.0;
4002 }
4003 if (surf_fit_pos)
4004 {
4005 Vector pos(dim), pos_target(dim);
4006 for (int d = 0; d < dim; d++)
4007 {
4008 pos(d) = PMatI(s, d);
4009 pos_target(d) = (*surf_fit_pos)(vdofs[d*dof_s + s]);
4010 }
4011 // Eval_d2 returns the full Hessian, but we still use the general
4012 // computation that's in the dim x dim loop below.
4013 sigma_e(s) = 1.0;
4014 for (int d = 0; d < dim; d++) { surf_fit_grad_e(s, d) = 0.0; }
4015 surf_fit_limiter->Eval_d2(pos, pos_target, 1.0, surf_fit_hess_s);
4016 }
4017
4018 // Loops over the local matrix.
4019 for (int idim = 0; idim < dim; idim++)
4020 {
4021 for (int jdim = 0; jdim <= idim; jdim++)
4022 {
4023 real_t entry = w * ( surf_fit_grad_e(s, idim) *
4024 surf_fit_grad_e(s, jdim) +
4025 sigma_e(s) * surf_fit_hess_s(idim, jdim));
4026 entry *= 1.0 / surf_fit_dof_count[vdofs[s]];
4027 int idx = s + idim*dof_s;
4028 int jdx = s + jdim*dof_s;
4029 mat(idx, jdx) += entry;
4030 if (idx != jdx) { mat(jdx, idx) += entry; }
4031 }
4032 }
4033 }
4034}
4035
4038 Vector &elfun, const int dofidx,
4039 const int dir, const real_t e_fx,
4040 bool update_stored)
4041{
4042 int dof = el.GetDof();
4043 int idx = dir*dof+dofidx;
4044 elfun[idx] += dx;
4045 real_t e_fxph = GetElementEnergy(el, T, elfun);
4046 elfun[idx] -= dx;
4047 real_t dfdx = (e_fxph-e_fx)/dx;
4048
4049 if (update_stored)
4050 {
4051 (*(ElemPertEnergy[T.ElementNo]))(idx) = e_fxph;
4052 (*(ElemDer[T.ElementNo]))(idx) = dfdx;
4053 }
4054
4055 return dfdx;
4056}
4057
4060 const Vector &elfun,
4061 Vector &elvect)
4062{
4063 const int dof = el.GetDof(), dim = el.GetDim(), elnum = T.ElementNo;
4064 if (elnum>=ElemDer.Size())
4065 {
4066 ElemDer.Append(new Vector);
4067 ElemPertEnergy.Append(new Vector);
4068 ElemDer[elnum]->SetSize(dof*dim);
4069 ElemPertEnergy[elnum]->SetSize(dof*dim);
4070 }
4071
4072 elvect.SetSize(dof*dim);
4073 Vector elfunmod(elfun);
4074
4075 // In GetElementEnergy(), skip terms that have exact derivative calculations.
4076 fd_call_flag = true;
4077
4078 // Energy for unperturbed configuration.
4079 const real_t e_fx = GetElementEnergy(el, T, elfun);
4080
4081 for (int j = 0; j < dim; j++)
4082 {
4083 for (int i = 0; i < dof; i++)
4084 {
4085 if (discr_tc)
4086 {
4088 el, T, i, j, discr_tc->GetTspecPert1H());
4089 }
4090 elvect(j*dof+i) = GetFDDerivative(el, T, elfunmod, i, j, e_fx, true);
4092 }
4093 }
4094 fd_call_flag = false;
4095
4096 // Contributions from adaptive limiting, surface fitting (exact derivatives).
4098 {
4100 const int nqp = ir.GetNPoints();
4101 DenseTensor Jtr(dim, dim, nqp);
4102 targetC->ComputeElementTargets(T.ElementNo, el, ir, elfun, Jtr);
4103
4105 Tpr.SetFE(&el);
4106 Tpr.ElementNo = T.ElementNo;
4107 Tpr.Attribute = T.Attribute;
4108 Tpr.mesh = T.mesh;
4109 PMatI.UseExternalData(elfun.GetData(), dof, dim);
4110 Tpr.GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
4111
4112 Vector weights(nqp);
4113 for (int q = 0; q < nqp; q++)
4114 {
4115 weights(q) = (integ_over_target) ?
4116 ir.IntPoint(q).weight * Jtr(q).Det() :
4117 ir.IntPoint(q).weight;
4118 }
4119
4120 PMatO.UseExternalData(elvect.GetData(), dof, dim);
4121 if (adapt_lim_gf) { AssembleElemVecAdaptLim(el, Tpr, ir, weights, PMatO); }
4123 }
4124}
4125
4128 const Vector &elfun,
4129 DenseMatrix &elmat)
4130{
4131 const int dof = el.GetDof(), dim = el.GetDim();
4132
4133 elmat.SetSize(dof*dim);
4134 Vector elfunmod(elfun);
4135
4136 const Vector &ElemDerLoc = *(ElemDer[T.ElementNo]);
4137 const Vector &ElemPertLoc = *(ElemPertEnergy[T.ElementNo]);
4138
4139 // In GetElementEnergy(), skip terms that have exact derivative calculations.
4140 fd_call_flag = true;
4141 for (int i = 0; i < dof; i++)
4142 {
4143 for (int j = 0; j < i+1; j++)
4144 {
4145 for (int k1 = 0; k1 < dim; k1++)
4146 {
4147 for (int k2 = 0; k2 < dim; k2++)
4148 {
4149 elfunmod(k2*dof+j) += dx;
4150
4151 if (discr_tc)
4152 {
4154 el, T, j, k2, discr_tc->GetTspecPert1H());
4155 if (j != i)
4156 {
4158 el, T, i, k1, discr_tc->GetTspecPert1H());
4159 }
4160 else // j==i
4161 {
4162 if (k1 != k2)
4163 {
4164 int idx = k1+k2-1;
4166 el, T, i, idx, discr_tc->GetTspecPertMixH());
4167 }
4168 else // j==i && k1==k2
4169 {
4171 el, T, i, k1, discr_tc->GetTspecPert2H());
4172 }
4173 }
4174 }
4175
4176 real_t e_fx = ElemPertLoc(k2*dof+j);
4177 real_t e_fpxph = GetFDDerivative(el, T, elfunmod, i, k1, e_fx,
4178 false);
4179 elfunmod(k2*dof+j) -= dx;
4180 real_t e_fpx = ElemDerLoc(k1*dof+i);
4181
4182 elmat(k1*dof+i, k2*dof+j) = (e_fpxph - e_fpx) / dx;
4183 elmat(k2*dof+j, k1*dof+i) = (e_fpxph - e_fpx) / dx;
4184
4185 if (discr_tc)
4186 {
4189 }
4190 }
4191 }
4192 }
4193 }
4194 fd_call_flag = false;
4195
4196 // Contributions from adaptive limiting.
4198 {
4200 const int nqp = ir.GetNPoints();
4201 DenseTensor Jtr(dim, dim, nqp);
4202 targetC->ComputeElementTargets(T.ElementNo, el, ir, elfun, Jtr);
4203
4205 Tpr.SetFE(&el);
4206 Tpr.ElementNo = T.ElementNo;
4207 Tpr.Attribute = T.Attribute;
4208 Tpr.mesh = T.mesh;
4209 PMatI.UseExternalData(elfun.GetData(), dof, dim);
4210 Tpr.GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
4211
4212 Vector weights(nqp);
4213 for (int q = 0; q < nqp; q++)
4214 {
4215 weights(q) = (integ_over_target) ?
4216 ir.IntPoint(q).weight * Jtr(q).Det() :
4217 ir.IntPoint(q).weight;
4218 }
4219
4220 if (adapt_lim_gf) { AssembleElemGradAdaptLim(el, Tpr, ir, weights, elmat); }
4221 if (surf_fit_gf || surf_fit_pos) { AssembleElemGradSurfFit(el, Tpr, elmat); }
4222 }
4223}
4224
4226{
4227 if (!surf_fit_coeff) { return; }
4228
4229 if (surf_fit_coeff)
4230 {
4231 auto cf = dynamic_cast<ConstantCoefficient *>(surf_fit_coeff);
4232 MFEM_VERIFY(cf, "Dynamic weight works only with a ConstantCoefficient.");
4233 cf->constant *= factor;
4234 }
4235}
4236
4238{
4239 if (surf_fit_coeff)
4240 {
4241 auto cf = dynamic_cast<ConstantCoefficient *>(surf_fit_coeff);
4242 MFEM_VERIFY(cf, "Dynamic weight works only with a ConstantCoefficient.");
4243 return cf->constant;
4244 }
4245 return 0.0;
4246}
4247
4249{
4252 lim_normal = 1.0 / lim_normal;
4253 //if (surf_fit_gf) { surf_fit_normal = 1.0 / surf_fit_normal; }
4255}
4256
4257#ifdef MFEM_USE_MPI
4259{
4260 real_t loc[3];
4261 ComputeNormalizationEnergies(x, loc[0], loc[1], loc[2]);
4262 real_t rdc[3];
4263 MPI_Allreduce(loc, rdc, 3, MPITypeMap<real_t>::mpi_type, MPI_SUM,
4264 x.ParFESpace()->GetComm());
4265 metric_normal = 1.0 / rdc[0];
4266 lim_normal = 1.0 / rdc[1];
4267 // if (surf_fit_gf) { surf_fit_normal = 1.0 / rdc[2]; }
4269}
4270#endif
4271
4273 real_t &metric_energy,
4274 real_t &lim_energy,
4275 real_t &surf_fit_gf_energy)
4276{
4277 Array<int> vdofs;
4278 Vector x_vals;
4279 const FiniteElementSpace* const fes = x.FESpace();
4280
4281 const int dim = fes->GetMesh()->Dimension();
4282 Jrt.SetSize(dim);
4283 Jpr.SetSize(dim);
4284 Jpt.SetSize(dim);
4285
4286 metric_energy = 0.0;
4287 lim_energy = 0.0;
4288 surf_fit_gf_energy = 0.0;
4289 for (int i = 0; i < fes->GetNE(); i++)
4290 {
4291 const FiniteElement *fe = fes->GetFE(i);
4293 const int nqp = ir.GetNPoints();
4294 DenseTensor Jtr(dim, dim, nqp);
4295 const int dof = fe->GetDof();
4296 DSh.SetSize(dof, dim);
4297
4298 fes->GetElementVDofs(i, vdofs);
4299 x.GetSubVector(vdofs, x_vals);
4300 PMatI.UseExternalData(x_vals.GetData(), dof, dim);
4301
4302 targetC->ComputeElementTargets(i, *fe, ir, x_vals, Jtr);
4303
4304 for (int q = 0; q < nqp; q++)
4305 {
4306 const IntegrationPoint &ip = ir.IntPoint(q);
4308 CalcInverse(Jtr(q), Jrt);
4309 const real_t weight =
4310 (integ_over_target) ? ip.weight * Jtr(q).Det() : ip.weight;
4311
4312 fe->CalcDShape(ip, DSh);
4313 MultAtB(PMatI, DSh, Jpr);
4314 Mult(Jpr, Jrt, Jpt);
4315
4316 metric_energy += weight * metric->EvalW(Jpt);
4317 lim_energy += weight;
4318 }
4319
4320 // Normalization of the surface fitting term.
4321 if (surf_fit_gf)
4322 {
4323 Array<int> dofs;
4324 Vector sigma_e;
4325 surf_fit_gf->FESpace()->GetElementDofs(i, dofs);
4326 surf_fit_gf->GetSubVector(dofs, sigma_e);
4327 for (int s = 0; s < dofs.Size(); s++)
4328 {
4329 if ((*surf_fit_marker)[dofs[s]] == true)
4330 {
4331 surf_fit_gf_energy += sigma_e(s) * sigma_e(s);
4332 }
4333 }
4334 }
4335 }
4336
4337 // Cases when integration is not over the target element, or when the
4338 // targets don't contain volumetric information.
4339 if (integ_over_target == false || targetC->ContainsVolumeInfo() == false)
4340 {
4341 lim_energy = fes->GetNE();
4342 }
4343}
4344
4346 const FiniteElementSpace &fes)
4347{
4348 const FiniteElement *fe = fes.GetFE(0);
4350 const int NE = fes.GetMesh()->GetNE(), dim = fe->GetDim(),
4351 dof = fe->GetDof(), nsp = ir.GetNPoints();
4352
4353 Array<int> xdofs(dof * dim);
4354 DenseMatrix dshape(dof, dim), pos(dof, dim);
4355 Vector posV(pos.Data(), dof * dim);
4356 Jpr.SetSize(dim);
4357
4358 dx = std::numeric_limits<float>::max();
4359
4360 real_t detv_sum;
4361 real_t detv_avg_min = std::numeric_limits<float>::max();
4362 for (int i = 0; i < NE; i++)
4363 {
4364 fes.GetElementVDofs(i, xdofs);
4365 x.GetSubVector(xdofs, posV);
4366 detv_sum = 0.;
4367 for (int j = 0; j < nsp; j++)
4368 {
4369 fes.GetFE(i)->CalcDShape(ir.IntPoint(j), dshape);
4370 MultAtB(pos, dshape, Jpr);
4371 detv_sum += std::fabs(Jpr.Det());
4372 }
4373 real_t detv_avg = pow(detv_sum/nsp, 1./dim);
4374 detv_avg_min = std::min(detv_avg, detv_avg_min);
4375 }
4376 dx = detv_avg_min / dxscale;
4377}
4378
4381 const FiniteElementSpace &x_fes)
4382{
4383 if (discr_tc) { PA.Jtr_needs_update = true; }
4384
4385 if (PA.enabled) { UpdateCoefficientsPA(x_new); }
4386
4387 Ordering::Type ordering = x_fes.GetOrdering();
4388
4389 // Update the finite difference delta if FD are used.
4390 if (fdflag) { ComputeFDh(x_new, x_fes); }
4391
4392 // Update the target constructor if it's a discrete one.
4393 if (discr_tc)
4394 {
4395 discr_tc->UpdateTargetSpecification(x_new, true, ordering);
4396 if (fdflag)
4397 {
4398 discr_tc->UpdateGradientTargetSpecification(x_new, dx, true, ordering);
4399 discr_tc->UpdateHessianTargetSpecification(x_new, dx, true, ordering);
4400 }
4401 }
4402
4403 // Update adapt_lim_gf if adaptive limiting is enabled.
4404 if (adapt_lim_gf)
4405 {
4407 }
4408
4409 // Update surf_fit_gf if surface fitting is enabled.
4410 if (surf_fit_gf)
4411 {
4412 if (surf_fit_gf_bg)
4413 {
4414 // Interpolate information for only DOFs marked for fitting.
4415 const int dim = surf_fit_gf->FESpace()->GetMesh()->Dimension();
4416 const int cnt = surf_fit_marker_dof_index.Size();
4417 const int total_cnt = x_new.Size()/dim;
4418 Vector new_x_sorted(cnt*dim);
4419 if (ordering == 0)
4420 {
4421 for (int d = 0; d < dim; d++)
4422 {
4423 for (int i = 0; i < cnt; i++)
4424 {
4425 int dof_index = surf_fit_marker_dof_index[i];
4426 new_x_sorted(i + d*cnt) = x_new(dof_index + d*total_cnt);
4427 }
4428 }
4429 }
4430 else
4431 {
4432 for (int i = 0; i < cnt; i++)
4433 {
4434 int dof_index = surf_fit_marker_dof_index[i];
4435 for (int d = 0; d < dim; d++)
4436 {
4437 new_x_sorted(d + i*dim) = x_new(d + dof_index*dim);
4438 }
4439 }
4440 }
4441
4442 Vector surf_fit_gf_int, surf_fit_grad_int, surf_fit_hess_int;
4444 new_x_sorted, surf_fit_gf_int, ordering);
4445 for (int i = 0; i < cnt; i++)
4446 {
4447 int dof_index = surf_fit_marker_dof_index[i];
4448 (*surf_fit_gf)[dof_index] = surf_fit_gf_int(i);
4449 }
4450
4452 new_x_sorted, surf_fit_grad_int, ordering);
4453 // Assumes surf_fit_grad and surf_fit_gf share the same space
4454 const int grad_dim = surf_fit_grad->VectorDim();
4455 const int grad_cnt = surf_fit_grad->Size()/grad_dim;
4457 {
4458 for (int d = 0; d < grad_dim; d++)
4459 {
4460 for (int i = 0; i < cnt; i++)
4461 {
4462 int dof_index = surf_fit_marker_dof_index[i];
4463 (*surf_fit_grad)[dof_index + d*grad_cnt] =
4464 surf_fit_grad_int(i + d*cnt);
4465 }
4466 }
4467 }
4468 else
4469 {
4470 for (int i = 0; i < cnt; i++)
4471 {
4472 int dof_index = surf_fit_marker_dof_index[i];
4473 for (int d = 0; d < grad_dim; d++)
4474 {
4475 (*surf_fit_grad)[dof_index*dim + d] =
4476 surf_fit_grad_int(i*dim + d);
4477 }
4478 }
4479 }
4480
4482 new_x_sorted, surf_fit_hess_int, ordering);
4483 // Assumes surf_fit_hess and surf_fit_gf share the same space
4484 const int hess_dim = surf_fit_hess->VectorDim();
4485 const int hess_cnt = surf_fit_hess->Size()/hess_dim;
4487 {
4488 for (int d = 0; d < hess_dim; d++)
4489 {
4490 for (int i = 0; i < cnt; i++)
4491 {
4492 int dof_index = surf_fit_marker_dof_index[i];
4493 (*surf_fit_hess)[dof_index + d*hess_cnt] =
4494 surf_fit_hess_int(i + d*cnt);
4495 }
4496 }
4497 }
4498 else
4499 {
4500 for (int i = 0; i < cnt; i++)
4501 {
4502 int dof_index = surf_fit_marker_dof_index[i];
4503 for (int d = 0; d < hess_dim; d++)
4504 {
4505 (*surf_fit_hess)[dof_index*dim + d] =
4506 surf_fit_hess_int(i*dim + d);
4507 }
4508 }
4509 }
4510 }
4511 else
4512 {
4514 }
4515 }
4516}
4517
4519{
4520 if (!fdflag) { return; }
4521 ComputeMinJac(x, fes);
4522#ifdef MFEM_USE_MPI
4523 const ParFiniteElementSpace *pfes =
4524 dynamic_cast<const ParFiniteElementSpace *>(&fes);
4525 if (pfes)
4526 {
4527 real_t min_jac_all;
4528 MPI_Allreduce(&dx, &min_jac_all, 1, MPITypeMap<real_t>::mpi_type, MPI_MIN,
4529 pfes->GetComm());
4530 dx = min_jac_all;
4531 }
4532#endif
4533}
4534
4536{
4537 fdflag = true;
4538 const FiniteElementSpace *fes = x.FESpace();
4539 ComputeFDh(x,*fes);
4540 if (discr_tc)
4541 {
4542#ifdef MFEM_USE_GSLIB
4544 if (dynamic_cast<const InterpolatorFP *>(ae))
4545 {
4546 MFEM_ABORT("Using GSLIB-based interpolation with finite differences"
4547 "requires careful consideration. Contact TMOP team.");
4548 }
4549#endif
4553 }
4554}
4555
4556#ifdef MFEM_USE_MPI
4558{
4559 fdflag = true;
4560 const ParFiniteElementSpace *pfes = x.ParFESpace();
4561 ComputeFDh(x,*pfes);
4562 if (discr_tc)
4563 {
4564#ifdef MFEM_USE_GSLIB
4566 if (dynamic_cast<const InterpolatorFP *>(ae))
4567 {
4568 MFEM_ABORT("Using GSLIB-based interpolation with finite differences"
4569 "requires careful consideration. Contact TMOP team.");
4570 }
4571#endif
4575 }
4576}
4577#endif
4578
4580 const FiniteElementSpace &fes)
4581{
4582 real_t min_detT = std::numeric_limits<real_t>::infinity();
4583 const int NE = fes.GetMesh()->GetNE();
4584 const int dim = fes.GetMesh()->Dimension();
4585 Array<int> xdofs;
4586 Jpr.SetSize(dim);
4587 Jpt.SetSize(dim);
4588 Jrt.SetSize(dim);
4589
4590 for (int i = 0; i < NE; i++)
4591 {
4592 const FiniteElement *fe = fes.GetFE(i);
4594 const int dof = fe->GetDof(), nsp = ir.GetNPoints();
4595
4596 DSh.SetSize(dof, dim);
4597 Vector posV(dof * dim);
4598 PMatI.UseExternalData(posV.GetData(), dof, dim);
4599
4600 fes.GetElementVDofs(i, xdofs);
4601 x.GetSubVector(xdofs, posV);
4602
4604 targetC->ComputeElementTargets(i, *fe, ir, posV, Jtr);
4605
4606 for (int q = 0; q < nsp; q++)
4607 {
4608 const IntegrationPoint &ip = ir.IntPoint(q);
4609 const DenseMatrix &Jtr_q = Jtr(q);
4610 CalcInverse(Jtr_q, Jrt);
4611 fe->CalcDShape(ip, DSh);
4612 MultAtB(PMatI, DSh, Jpr);
4613 Mult(Jpr, Jrt, Jpt);
4614 real_t detT = Jpt.Det();
4615 min_detT = std::min(min_detT, detT);
4616 }
4617 }
4618 return min_detT;
4619}
4620
4622 const FiniteElementSpace &fes)
4623{
4624 real_t max_muT = -std::numeric_limits<real_t>::infinity();
4625 const int NE = fes.GetMesh()->GetNE();
4626 const int dim = fes.GetMesh()->Dimension();
4627 Array<int> xdofs;
4628 Jpr.SetSize(dim);
4629 Jpt.SetSize(dim);
4630 Jrt.SetSize(dim);
4631
4634
4635 if (!wcuo || wcuo->GetWorstCaseType() !=
4637 {
4638 return 0.0;
4639 }
4640
4641 for (int i = 0; i < NE; i++)
4642 {
4643 const FiniteElement *fe = fes.GetFE(i);
4645 const int dof = fe->GetDof(), nsp = ir.GetNPoints();
4646 Jpr.SetSize(dim);
4647 Jrt.SetSize(dim);
4648 Jpt.SetSize(dim);
4649
4650 DSh.SetSize(dof, dim);
4651 Vector posV(dof * dim);
4652 PMatI.UseExternalData(posV.GetData(), dof, dim);
4653
4654 fes.GetElementVDofs(i, xdofs);
4655 x.GetSubVector(xdofs, posV);
4656
4658 targetC->ComputeElementTargets(i, *fe, ir, posV, Jtr);
4659
4660 for (int q = 0; q < nsp; q++)
4661 {
4662 const IntegrationPoint &ip = ir.IntPoint(q);
4663 const DenseMatrix &Jtr_q = Jtr(q);
4664 CalcInverse(Jtr_q, Jrt);
4665
4666 fe->CalcDShape(ip, DSh);
4667 MultAtB(PMatI, DSh, Jpr);
4668 Mult(Jpr, Jrt, Jpt);
4669
4670 real_t metric_val = 0.0;
4671 if (wcuo)
4672 {
4673 wcuo->SetTargetJacobian(Jtr_q);
4674 metric_val = wcuo->EvalWBarrier(Jpt);
4675 }
4676
4677 max_muT = std::max(max_muT, metric_val);
4678 }
4679 }
4680 return max_muT;
4681}
4682
4684 const FiniteElementSpace &fes)
4685{
4688
4689 if (!wcuo) { return; }
4690
4691#ifdef MFEM_USE_MPI
4692 const ParFiniteElementSpace *pfes =
4693 dynamic_cast<const ParFiniteElementSpace *>(&fes);
4694#endif
4695
4696 if (wcuo && wcuo->GetBarrierType() ==
4698 {
4699 real_t min_detT = ComputeMinDetT(x, fes);
4700 real_t min_detT_all = min_detT;
4701#ifdef MFEM_USE_MPI
4702 if (pfes)
4703 {
4704 MPI_Allreduce(&min_detT, &min_detT_all, 1, MPITypeMap<real_t>::mpi_type,
4705 MPI_MIN,
4706 pfes->GetComm());
4707 }
4708#endif
4709 if (wcuo) { wcuo->SetMinDetT(min_detT_all); }
4710 }
4711
4713 real_t max_muT_all = max_muT;
4714#ifdef MFEM_USE_MPI
4715 if (pfes)
4716 {
4717 MPI_Allreduce(&max_muT, &max_muT_all, 1, MPITypeMap<real_t>::mpi_type, MPI_MAX,
4718 pfes->GetComm());
4719 }
4720#endif
4721 wcuo->SetMaxMuT(max_muT_all);
4722}
4723
4725 const GridFunction &dist,
4726 Coefficient &w0,
4727 TMOP_LimiterFunction *lfunc)
4728{
4729 MFEM_VERIFY(tmopi.Size() > 0, "No TMOP_Integrators were added.");
4730
4731 tmopi[0]->EnableLimiting(n0, dist, w0, lfunc);
4732 for (int i = 1; i < tmopi.Size(); i++) { tmopi[i]->DisableLimiting(); }
4733}
4734
4736 Coefficient &w0,
4737 TMOP_LimiterFunction *lfunc)
4738{
4739 MFEM_VERIFY(tmopi.Size() > 0, "No TMOP_Integrators were added.");
4740
4741 tmopi[0]->EnableLimiting(n0, w0, lfunc);
4742 for (int i = 1; i < tmopi.Size(); i++) { tmopi[i]->DisableLimiting(); }
4743}
4744
4746{
4747 MFEM_VERIFY(tmopi.Size() > 0, "No TMOP_Integrators were added.");
4748
4749 tmopi[0]->SetLimitingNodes(n0);
4750 for (int i = 1; i < tmopi.Size(); i++) { tmopi[i]->DisableLimiting(); }
4751}
4752
4755 const Vector &elfun)
4756{
4757 real_t energy= 0.0;
4758 for (int i = 0; i < tmopi.Size(); i++)
4759 {
4760 energy += tmopi[i]->GetElementEnergy(el, T, elfun);
4761 }
4762 return energy;
4763}
4764
4767 const Vector &elfun,
4768 Vector &elvect)
4769{
4770 MFEM_VERIFY(tmopi.Size() > 0, "No TMOP_Integrators were added.");
4771
4772 tmopi[0]->AssembleElementVector(el, T, elfun, elvect);
4773 for (int i = 1; i < tmopi.Size(); i++)
4774 {
4775 Vector elvect_i;
4776 tmopi[i]->AssembleElementVector(el, T, elfun, elvect_i);
4777 elvect += elvect_i;
4778 }
4779}
4780
4783 const Vector &elfun,
4784 DenseMatrix &elmat)
4785{
4786 MFEM_VERIFY(tmopi.Size() > 0, "No TMOP_Integrators were added.");
4787
4788 tmopi[0]->AssembleElementGrad(el, T, elfun, elmat);
4789 for (int i = 1; i < tmopi.Size(); i++)
4790 {
4791 DenseMatrix elmat_i;
4792 tmopi[i]->AssembleElementGrad(el, T, elfun, elmat_i);
4793 elmat += elmat_i;
4794 }
4795}
4796
4799 const Vector &elfun,
4800 const IntegrationRule &irule)
4801{
4802 real_t energy= 0.0;
4803 for (int i = 0; i < tmopi.Size(); i++)
4804 {
4805 energy += tmopi[i]->GetRefinementElementEnergy(el, T, elfun, irule);
4806 }
4807 return energy;
4808}
4809
4811 const FiniteElement &el,
4813 const Vector &elfun)
4814{
4815 real_t energy= 0.0;
4816 for (int i = 0; i < tmopi.Size(); i++)
4817 {
4818 energy += tmopi[i]->GetDerefinementElementEnergy(el, T, elfun);
4819 }
4820 return energy;
4821}
4822
4824{
4825 const int cnt = tmopi.Size();
4826 real_t total_integral = 0.0;
4827 for (int i = 0; i < cnt; i++)
4828 {
4829 tmopi[i]->EnableNormalization(x);
4830 total_integral += 1.0 / tmopi[i]->metric_normal;
4831 }
4832 for (int i = 0; i < cnt; i++)
4833 {
4834 tmopi[i]->metric_normal = 1.0 / total_integral;
4835 }
4836}
4837
4838#ifdef MFEM_USE_MPI
4840{
4841 const int cnt = tmopi.Size();
4842 real_t total_integral = 0.0;
4843 for (int i = 0; i < cnt; i++)
4844 {
4845 tmopi[i]->ParEnableNormalization(x);
4846 total_integral += 1.0 / tmopi[i]->metric_normal;
4847 }
4848 for (int i = 0; i < cnt; i++)
4849 {
4850 tmopi[i]->metric_normal = 1.0 / total_integral;
4851 }
4852}
4853#endif
4854
4856{
4857 for (int i = 0; i < tmopi.Size(); i++)
4858 {
4859 tmopi[i]->AssemblePA(fes);
4860 }
4861}
4862
4864 const FiniteElementSpace &fes)
4865{
4866 for (int i = 0; i < tmopi.Size(); i++)
4867 {
4868 tmopi[i]->AssembleGradPA(xe,fes);
4869 }
4870}
4871
4873{
4874 for (int i = 0; i < tmopi.Size(); i++)
4875 {
4876 tmopi[i]->AssembleGradDiagonalPA(de);
4877 }
4878}
4879
4881{
4882 for (int i = 0; i < tmopi.Size(); i++)
4883 {
4884 tmopi[i]->AddMultPA(xe, ye);
4885 }
4886}
4887
4889{
4890 for (int i = 0; i < tmopi.Size(); i++)
4891 {
4892 tmopi[i]->AddMultGradPA(re, ce);
4893 }
4894}
4895
4897{
4898 real_t energy = 0.0;
4899 for (int i = 0; i < tmopi.Size(); i++)
4900 {
4901 energy += tmopi[i]->GetLocalStateEnergyPA(xe);
4902 }
4903 return energy;
4904}
4905
4907 const TargetConstructor &tc,
4908 const Mesh &mesh, GridFunction &metric_gf)
4909{
4910 const int NE = mesh.GetNE();
4911 const GridFunction &nodes = *mesh.GetNodes();
4912 const int dim = mesh.Dimension();
4913 DenseMatrix Winv(dim), T(dim), A(dim), dshape, pos;
4914 Array<int> pos_dofs, gf_dofs;
4915 DenseTensor W;
4916 Vector posV;
4917
4918 for (int i = 0; i < NE; i++)
4919 {
4920 const FiniteElement &fe_pos = *nodes.FESpace()->GetFE(i);
4921 const IntegrationRule &ir = metric_gf.FESpace()->GetFE(i)->GetNodes();
4922 const int nsp = ir.GetNPoints(), dof = fe_pos.GetDof();
4923
4924 dshape.SetSize(dof, dim);
4925 pos.SetSize(dof, dim);
4926 posV.SetDataAndSize(pos.Data(), dof * dim);
4927
4928 metric_gf.FESpace()->GetElementDofs(i, gf_dofs);
4929 nodes.FESpace()->GetElementVDofs(i, pos_dofs);
4930 nodes.GetSubVector(pos_dofs, posV);
4931
4932 W.SetSize(dim, dim, nsp);
4933 tc.ComputeElementTargets(i, fe_pos, ir, posV, W);
4934
4935 for (int j = 0; j < nsp; j++)
4936 {
4937 const DenseMatrix &Wj = W(j);
4938 metric.SetTargetJacobian(Wj);
4939 CalcInverse(Wj, Winv);
4940
4941 const IntegrationPoint &ip = ir.IntPoint(j);
4942 fe_pos.CalcDShape(ip, dshape);
4943 MultAtB(pos, dshape, A);
4944 Mult(A, Winv, T);
4945
4946 metric_gf(gf_dofs[j]) = metric.EvalW(T);
4947 }
4948 }
4949}
4950
4951} // namespace mfem
virtual ~AdaptivityEvaluator()
Definition tmop.cpp:2844
virtual void SetInitialField(const Vector &init_nodes, const Vector &init_field)=0
virtual void ComputeAtNewPosition(const Vector &new_nodes, Vector &new_field, int new_nodes_ordering=Ordering::byNODES)=0
void SetSerialMetaInfo(const Mesh &m, const FiniteElementSpace &f)
Definition tmop.cpp:2813
FiniteElementSpace * fes
Definition tmop.hpp:1284
void SetParMetaInfo(const ParMesh &m, const ParFiniteElementSpace &f)
Parallel version of SetSerialMetaInfo.
Definition tmop.cpp:2824
ParFiniteElementSpace * pfes
Definition tmop.hpp:1289
virtual void ComputeElementTargets(int e_id, const FiniteElement &fe, const IntegrationRule &ir, const Vector &elfun, DenseTensor &Jtr) const
Given an element and quadrature rule, computes ref->target transformation Jacobians for each quadratu...
Definition tmop.cpp:1742
Coefficient * scalar_tspec
Definition tmop.hpp:1477
virtual void SetAnalyticTargetSpec(Coefficient *sspec, VectorCoefficient *vspec, TMOPMatrixCoefficient *mspec)
Definition tmop.cpp:1733
TMOPMatrixCoefficient * matrix_tspec
Definition tmop.hpp:1479
VectorCoefficient * vector_tspec
Definition tmop.hpp:1478
virtual void ComputeElementTargetsGradient(const IntegrationRule &ir, const Vector &elfun, IsoparametricTransformation &Tpr, DenseTensor &dJtr) const
Definition tmop.cpp:1776
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition array.hpp:697
int Size() const
Return the logical size of the array.
Definition array.hpp:144
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Definition array.hpp:769
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.
A coefficient that is constant across space and time.
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:220
void Set(real_t alpha, const real_t *A)
Set the matrix to alpha * A, assuming that A has the same dimensions as the matrix and uses column-ma...
Definition densemat.cpp:619
void MultTranspose(const real_t *x, real_t *y) const
Multiply a vector with the transpose matrix.
Definition densemat.cpp:262
void Transpose()
(*this) = (*this)^t
real_t * Data() const
Returns the matrix data array.
Definition densemat.hpp:111
real_t * GetData() const
Returns the matrix data array.
Definition densemat.hpp:115
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
Definition densemat.hpp:105
real_t Trace() const
Trace of a square matrix.
Definition densemat.cpp:511
void UseExternalData(real_t *d, int h, int w)
Change the data array and the size of the DenseMatrix.
Definition densemat.hpp:80
void Add(const real_t c, const DenseMatrix &A)
Adds the matrix A multiplied by the number c to the matrix.
Definition densemat.cpp:628
void GetColumn(int c, Vector &col) const
int Size() const
For backward compatibility define Size to be synonym of Width()
Definition densemat.hpp:102
real_t FNorm2() const
Compute the square of the Frobenius norm of the matrix.
Definition densemat.hpp:269
void GetRow(int r, Vector &row) const
real_t Det() const
Definition densemat.cpp:535
Rank 3 tensor (array of matrices)
real_t * HostWrite()
Shortcut for mfem::Write(GetMemory(), TotalSize(), false).
void SetSize(int i, int j, int k, MemoryType mt_=MemoryType::PRESERVE)
real_t * GetData(int k)
void UseExternalData(real_t *ext_data, int i, int j, int k)
int SizeJ() const
int SizeI() const
const Vector & GetTspecPert1H()
Definition tmop.hpp:1673
void UpdateTargetSpecification(const Vector &new_x, bool reuse_flag=false, int new_x_ordering=Ordering::byNODES)
Definition tmop.cpp:2054
virtual void SetSerialDiscreteTargetSkew(const GridFunction &tspec_)
Definition tmop.cpp:1972
virtual void SetParDiscreteTargetAspectRatio(const ParGridFunction &tspec_)
Definition tmop.cpp:1899
ParGridFunction * tspec_pgf
Definition tmop.hpp:1549
DenseTensor Jtrcomp
Definition tmop.hpp:1538
virtual void SetSerialDiscreteTargetAspectRatio(const GridFunction &tspec_)
Definition tmop.cpp:1982
const AdaptivityEvaluator * GetAdaptivityEvaluator() const
Definition tmop.hpp:1668
void SetTspecDataForDerefinement(FiniteElementSpace *fes)
Computes target specification data with respect to the coarse FE space.
Definition tmop.cpp:2131
const Vector & GetTspecPertMixH()
Definition tmop.hpp:1675
virtual void SetParDiscreteTargetSpec(const ParGridFunction &tspec_)
Definition tmop.cpp:1919
AdaptivityEvaluator * adapt_eval
Definition tmop.hpp:1561
void FinalizeSerialDiscreteTargetSpec(const GridFunction &tspec_)
Definition tmop.cpp:2002
void FinalizeParDiscreteTargetSpec(const ParGridFunction &tspec_)
Definition tmop.cpp:1823
virtual void ComputeElementTargetsGradient(const IntegrationRule &ir, const Vector &elfun, IsoparametricTransformation &Tpr, DenseTensor &dJtr) const
Definition tmop.cpp:2354
ParFiniteElementSpace * ptspec_fesv
Definition tmop.hpp:1547
GridFunction * tspec_gf
Definition tmop.hpp:1544
FiniteElementSpace * coarse_tspec_fesv
Definition tmop.hpp:1543
virtual ~DiscreteAdaptTC()
Definition tmop.cpp:2803
virtual void SetSerialDiscreteTargetSize(const GridFunction &tspec_)
Definition tmop.cpp:1962
virtual void SetParDiscreteTargetSize(const ParGridFunction &tspec_)
Definition tmop.cpp:1879
const Vector & GetTspecPert2H()
Definition tmop.hpp:1674
void UpdateAfterMeshTopologyChange()
Update all discrete fields based on tspec and update for AMR.
Definition tmop.cpp:2037
virtual void ComputeElementTargets(int e_id, const FiniteElement &fe, const IntegrationRule &ir, const Vector &elfun, DenseTensor &Jtr) const
Given an element and quadrature rule, computes ref->target transformation Jacobians for each quadratu...
Definition tmop.cpp:2139
virtual void SetSerialDiscreteTargetSpec(const GridFunction &tspec_)
Definition tmop.cpp:2048
virtual void SetParDiscreteTargetOrientation(const ParGridFunction &tspec_)
Definition tmop.cpp:1909
void ResetRefinementTspecData()
Definition tmop.hpp:1710
virtual void SetParDiscreteTargetSkew(const ParGridFunction &tspec_)
Definition tmop.cpp:1889
void ParUpdateAfterMeshTopologyChange()
Definition tmop.cpp:1848
void UpdateTargetSpecificationAtNode(const FiniteElement &el, ElementTransformation &T, int nodenum, int idir, const Vector &IntData)
Definition tmop.cpp:2074
void RestoreTargetSpecificationAtNode(ElementTransformation &T, int nodenum)
Definition tmop.cpp:2091
FiniteElementSpace * tspec_fesv
Definition tmop.hpp:1542
virtual void SetSerialDiscreteTargetOrientation(const GridFunction &tspec_)
Definition tmop.cpp:1992
void SetTspecAtIndex(int idx, const GridFunction &tspec_)
Definition tmop.cpp:1949
void SetRefinementSubElement(int amr_el_)
Definition tmop.hpp:1725
void GetDiscreteTargetSpec(GridFunction &tspec_, int idx)
Get one of the discrete fields from tspec.
Definition tmop.cpp:2023
void UpdateHessianTargetSpecification(const Vector &x, real_t dx, bool reuse_flag=false, int x_ordering=Ordering::byNODES)
Definition tmop.cpp:2737
void SetDiscreteTargetBase(const GridFunction &tspec_)
Definition tmop.cpp:1925
DenseMatrix tspec_refine
Definition tmop.hpp:1531
void UpdateGradientTargetSpecification(const Vector &x, real_t dx, bool reuse_flag=false, int x_ordering=Ordering::byNODES)
Definition tmop.cpp:2701
void SetTspecFromIntRule(int e_id, const IntegrationRule &intrule)
Definition tmop.cpp:2105
const Mesh * mesh
The Mesh object containing the element.
Definition eltrans.hpp:84
real_t Weight()
Return the weight of the Jacobian matrix of the transformation at the currently set IntegrationPoint....
Definition eltrans.hpp:131
void SetIntPoint(const IntegrationPoint *ip)
Set the integration point ip that weights and Jacobians will be evaluated at.
Definition eltrans.hpp:93
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:220
bool IsVariableOrder() const
Returns true if the space contains elements of varying polynomial orders.
Definition fespace.hpp:581
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:2846
int GetNDofs() const
Returns number of degrees of freedom. This is the number of Local Degrees of Freedom.
Definition fespace.hpp:710
int VDofToDof(int vdof) const
Compute the inverse of the Dof to VDof mapping for a single index vdof.
Definition fespace.hpp:995
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:287
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:3168
Ordering::Type GetOrdering() const
Return the ordering method.
Definition fespace.hpp:725
int GetNE() const
Returns number of elements in the mesh.
Definition fespace.hpp:740
virtual void Update(bool want_transform=true)
Reflect changes in the mesh: update number of DOFs, etc. Also, calculate GridFunction transformation ...
Definition fespace.cpp:3439
const FiniteElementCollection * FEColl() const
Definition fespace.hpp:727
Mesh * GetMesh() const
Returns the mesh.
Definition fespace.hpp:559
int GetVDim() const
Returns vector dimension.
Definition fespace.hpp:706
const Operator * GetUpdateOperator()
Get the GridFunction update operator.
Definition fespace.hpp:1285
Abstract class for all finite elements.
Definition fe_base.hpp:239
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...
Definition fe_base.hpp:333
virtual void ProjectGrad(const FiniteElement &fe, ElementTransformation &Trans, DenseMatrix &grad) const
Compute the discrete gradient matrix from the given FiniteElement onto 'this' FiniteElement....
Definition fe_base.cpp:161
int GetDim() const
Returns the reference space dimension for the finite element.
Definition fe_base.hpp:316
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
Definition fe_base.hpp:395
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:326
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...
int GetDof() const
Returns the number of degrees of freedom in the finite element.
Definition fe_base.hpp:329
const DenseMatrix & GetGeomToPerfGeomJac(int GeomType) const
Definition geom.hpp:98
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:31
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...
void GetValues(int i, const IntegrationRule &ir, Vector &vals, int vdim=1) const
Definition gridfunc.cpp:521
virtual void Update()
Transform by the Space UpdateMatrix (e.g., on Mesh change).
Definition gridfunc.cpp:164
FiniteElementSpace * FESpace()
Definition gridfunc.hpp:696
int VectorDim() const
Definition gridfunc.cpp:323
void GetVectorValues(int i, const IntegrationRule &ir, DenseMatrix &vals, DenseMatrix &tr) const
Definition gridfunc.cpp:714
Class for integration point with weight.
Definition intrules.hpp:35
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.
const scalar_t * Get_dI1b()
void Assemble_ddI1(scalar_t w, scalar_t *A)
void SetJacobian(const scalar_t *Jac)
The Jacobian should use column-major storage.
void Assemble_ddI1b(scalar_t w, scalar_t *A)
const scalar_t * Get_dI2()
void SetDerivativeMatrix(int height, const scalar_t *Deriv)
The Deriv matrix is dof x 2, using column-major storage.
void Assemble_ddI2b(scalar_t w, scalar_t *A)
const scalar_t * Get_dI2b()
void Assemble_TProd(scalar_t w, const scalar_t *X, const scalar_t *Y, scalar_t *A)
void Assemble_ddI2(scalar_t w, scalar_t *A)
const scalar_t * Get_dI1()
void SetJacobian(const scalar_t *Jac)
The Jacobian should use column-major storage.
const scalar_t * Get_dI2()
const scalar_t * Get_dI2b()
const scalar_t * Get_dI3()
void Assemble_TProd(scalar_t w, const scalar_t *X, const scalar_t *Y, scalar_t *A)
const scalar_t * Get_dI1()
void SetDerivativeMatrix(int height, const scalar_t *Deriv)
The Deriv matrix is dof x 3, using column-major storage.
const scalar_t * Get_dI3b()
void Assemble_ddI1(scalar_t w, scalar_t *A)
void Assemble_ddI2(scalar_t w, scalar_t *A)
const scalar_t * Get_dI1b()
void Assemble_ddI3(scalar_t w, scalar_t *A)
void Assemble_ddI2b(scalar_t w, scalar_t *A)
void Assemble_ddI3b(scalar_t w, scalar_t *A)
void Assemble_ddI1b(scalar_t w, scalar_t *A)
A standard isoparametric element transformation.
Definition eltrans.hpp:363
void SetFE(const FiniteElement *FE)
Set the element that will be used to compute the transformations.
Definition eltrans.hpp:382
virtual int OrderJ() const
Return the order of the elements of the Jacobian of the transformation.
Definition eltrans.cpp:439
const FiniteElement * GetFE() const
Get the current element used to compute the transformations.
Definition eltrans.hpp:390
const DenseMatrix & GetPointMat() const
Return the stored point matrix.
Definition eltrans.hpp:405
virtual void Eval(DenseMatrix &K, ElementTransformation &T, const IntegrationPoint &ip)=0
Evaluate the matrix coefficient in the element described by T at the point ip, storing the result in ...
Mesh data type.
Definition mesh.hpp:56
int GetNE() const
Returns number of elements.
Definition mesh.hpp:1226
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1160
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 GetNodes(Vector &node_coord) const
Definition mesh.cpp:8973
NCMesh * ncmesh
Optional nonconforming mesh extension.
Definition mesh.hpp:291
int GetNumGeometries(int dim) const
Return the number of geometries of the given dimension present in the mesh.
Definition mesh.cpp:6961
Geometry::Type GetElementBaseGeometry(int i) const
Definition mesh.hpp:1385
void DeleteGeometricFactors()
Destroy all GeometricFactors stored by the Mesh.
Definition mesh.cpp:898
A class for non-conforming AMR. The class is not used directly by the user, rather it is an extension...
Definition ncmesh.hpp:123
int GetElementSizeReduction(int i) const
Definition ncmesh.cpp:5229
int GetNumRootElements()
Return the number of root elements.
Definition ncmesh.hpp:429
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 NumCols() const
Get the number of columns (size of input) of the Operator. Synonym with Width().
Definition operator.hpp:75
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
Definition operator.hpp:72
Type
Ordering methods:
Definition fespace.hpp:34
Abstract parallel finite element space.
Definition pfespace.hpp:29
MPI_Comm GetComm() const
Definition pfespace.hpp:273
ParMesh * GetParMesh() const
Definition pfespace.hpp:277
void Update(bool want_transform=true) override
Class for parallel grid function.
Definition pgridfunc.hpp:33
void CountElementsPerVDof(Array< int > &elem_per_vdof) const override
For each vdof, counts how many elements contain the vdof, as containment is determined by FiniteEleme...
ParFiniteElementSpace * ParFESpace() const
void Update() override
Transform by the Space UpdateMatrix (e.g., on Mesh change).
Definition pgridfunc.cpp:90
Class for parallel meshes.
Definition pmesh.hpp:34
virtual real_t GetElementEnergy(const FiniteElement &el, ElementTransformation &T, const Vector &elfun)
Compute the local energy.
Definition tmop.cpp:4753
virtual void AddMultGradPA(const Vector &, Vector &) const
Method for partially assembled gradient action.
Definition tmop.cpp:4888
virtual real_t GetDerefinementElementEnergy(const FiniteElement &el, ElementTransformation &T, const Vector &elfun)
Definition tmop.cpp:4810
virtual void AssemblePA(const FiniteElementSpace &)
Method defining partial assembly.
Definition tmop.cpp:4855
virtual real_t GetLocalStateEnergyPA(const Vector &) const
Compute the local (to the MPI rank) energy with partial assembly.
Definition tmop.cpp:4896
virtual void AssembleGradDiagonalPA(Vector &) const
Method for computing the diagonal of the gradient with partial assembly.
Definition tmop.cpp:4872
virtual void AssembleElementGrad(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, DenseMatrix &elmat)
Assemble the local gradient matrix.
Definition tmop.cpp:4781
void ParEnableNormalization(const ParGridFunction &x)
Definition tmop.cpp:4839
void EnableLimiting(const GridFunction &n0, const GridFunction &dist, Coefficient &w0, TMOP_LimiterFunction *lfunc=NULL)
Adds the limiting term to the first integrator. Disables it for the rest.
Definition tmop.cpp:4724
virtual void AssembleElementVector(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, Vector &elvect)
Perform the local action of the NonlinearFormIntegrator.
Definition tmop.cpp:4765
virtual real_t GetRefinementElementEnergy(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, const IntegrationRule &irule)
Definition tmop.cpp:4797
virtual void AssembleGradPA(const Vector &, const FiniteElementSpace &)
Prepare the integrator for partial assembly (PA) gradient evaluations on the given FE space fes at th...
Definition tmop.cpp:4863
virtual void AddMultPA(const Vector &, Vector &) const
Method for partially assembled action.
Definition tmop.cpp:4880
Array< TMOP_Integrator * > tmopi
Definition tmop.hpp:2260
void EnableNormalization(const GridFunction &x)
Normalization factor that considers all integrators in the combination.
Definition tmop.cpp:4823
void SetLimitingNodes(const GridFunction &n0)
Update the original/reference nodes used for limiting.
Definition tmop.cpp:4745
virtual void EvalGrad(DenseMatrix &K, ElementTransformation &T, const IntegrationPoint &ip, int comp)=0
Evaluate the derivative of the matrix coefficient with respect to comp in the element described by T ...
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1440
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1466
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1482
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1498
void ComputeAvgMetrics(const GridFunction &nodes, const TargetConstructor &tc, Vector &averages) const
Definition tmop.cpp:99
virtual real_t EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:23
Array< real_t > wt_arr
Definition tmop.hpp:89
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:55
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:33
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:43
Array< TMOP_QualityMetric * > tmop_q_arr
Definition tmop.hpp:88
void ComputeBalancedWeights(const GridFunction &nodes, const TargetConstructor &tc, Vector &weights) const
Definition tmop.cpp:70
real_t ComputeUntanglerMaxMuBarrier(const Vector &x, const FiniteElementSpace &fes)
Definition tmop.cpp:4621
virtual void AssembleElementGrad(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, DenseMatrix &elmat)
Assemble the local gradient matrix.
Definition tmop.cpp:3481
DenseMatrix Jpr
Definition tmop.hpp:1820
void AssembleElemVecAdaptLim(const FiniteElement &el, IsoparametricTransformation &Tpr, const IntegrationRule &ir, const Vector &weights, DenseMatrix &mat)
Definition tmop.cpp:3743
void AssembleElemGradAdaptLim(const FiniteElement &el, IsoparametricTransformation &Tpr, const IntegrationRule &ir, const Vector &weights, DenseMatrix &m)
Definition tmop.cpp:3779
real_t GetFDDerivative(const FiniteElement &el, ElementTransformation &T, Vector &elfun, const int nodenum, const int idir, const real_t baseenergy, bool update_stored)
Definition tmop.cpp:4036
void ComputeUntangleMetricQuantiles(const Vector &x, const FiniteElementSpace &fes)
Definition tmop.cpp:4683
TMOP_LimiterFunction * lim_func
Definition tmop.hpp:1765
virtual void AssembleElementVector(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, Vector &elvect)
Perform the local action of the NonlinearFormIntegrator.
Definition tmop.cpp:3467
void ParUpdateAfterMeshTopologyChange()
Definition tmop.cpp:3156
DenseMatrix PMatO
Definition tmop.hpp:1820
TMOP_QualityMetric * metric
Definition tmop.hpp:1744
virtual real_t GetElementEnergy(const FiniteElement &el, ElementTransformation &T, const Vector &elfun)
Computes the integral of W(Jacobian(Trt)) over a target zone.
Definition tmop.cpp:3169
const ParGridFunction * adapt_lim_pgf0
Definition tmop.hpp:1772
real_t ComputeMinDetT(const Vector &x, const FiniteElementSpace &fes)
Definition tmop.cpp:4579
AdaptivityEvaluator * surf_fit_eval_bg_hess
Definition tmop.hpp:1790
AdaptivityEvaluator * surf_fit_eval_bg_grad
Definition tmop.hpp:1790
AdaptivityEvaluator * surf_fit_eval
Definition tmop.hpp:1783
void EnableNormalization(const GridFunction &x)
Computes the normalization factors of the metric and limiting integrals using the mesh position given...
Definition tmop.cpp:4248
void ComputeMinJac(const Vector &x, const FiniteElementSpace &fes)
Definition tmop.cpp:4345
void AssembleElementVectorFD(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, Vector &elvect)
Definition tmop.cpp:4058
TMOP_QualityMetric * h_metric
Definition tmop.hpp:1743
DiscreteAdaptTC * discr_tc
Definition tmop.hpp:1794
void ComputeFDh(const Vector &x, const FiniteElementSpace &fes)
Determines the perturbation, h, for FD-based approximation.
Definition tmop.cpp:4518
Coefficient * lim_coeff
Definition tmop.hpp:1761
GridFunction * surf_fit_gf
Definition tmop.hpp:1782
const GridFunction * lim_dist
Definition tmop.hpp:1763
void AssembleElementVectorExact(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, Vector &elvect)
Definition tmop.cpp:3496
void AssembleElementGradExact(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, DenseMatrix &elmat)
Definition tmop.cpp:3635
Array< Vector * > ElemPertEnergy
Definition tmop.hpp:1808
const GridFunction * adapt_lim_gf0
Definition tmop.hpp:1770
void EnableSurfaceFittingFromSource(const ParGridFunction &s_bg, ParGridFunction &s0, const Array< bool > &smarker, Coefficient &coeff, AdaptivityEvaluator &ae, const ParGridFunction &s_bg_grad, ParGridFunction &s0_grad, AdaptivityEvaluator &age, const ParGridFunction &s_bg_hess, ParGridFunction &s0_hess, AdaptivityEvaluator &ahe)
Fitting of certain DOFs in the current mesh to the zero level set of a function defined on another (f...
Definition tmop.cpp:3010
const TargetConstructor * targetC
Definition tmop.hpp:1745
void ComputeNormalizationEnergies(const GridFunction &x, real_t &metric_energy, real_t &lim_energy, real_t &surf_fit_gf_energy)
Definition tmop.cpp:4272
const GridFunction * lim_nodes0
Definition tmop.hpp:1760
const IntegrationRule * ir
Definition tmop.hpp:1868
TMOP_QuadraticLimiter * surf_fit_limiter
Definition tmop.hpp:1785
void EnableFiniteDifferences(const GridFunction &x)
Enables FD-based approximation and computes dx.
Definition tmop.cpp:4535
virtual real_t GetRefinementElementEnergy(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, const IntegrationRule &irule)
Computes the mean of the energies of the given element's children.
Definition tmop.cpp:3327
real_t GetSurfaceFittingWeight()
Get the surface fitting weight.
Definition tmop.cpp:4237
DenseMatrix DSh
Definition tmop.hpp:1820
const GridFunction * surf_fit_pos
Definition tmop.hpp:1786
Array< int > surf_fit_marker_dof_index
Definition tmop.hpp:1792
DenseTensor Jtr
Definition tmop.hpp:1860
void ParEnableNormalization(const ParGridFunction &x)
Definition tmop.cpp:4258
Coefficient * adapt_lim_coeff
Definition tmop.hpp:1775
const FiniteElementSpace * fes
Definition tmop.hpp:1867
const IntegrationRule & EnergyIntegrationRule(const FiniteElement &el) const
Definition tmop.hpp:1929
void UpdateAfterMeshPositionChange(const Vector &x_new, const FiniteElementSpace &x_fes)
Definition tmop.cpp:4380
GridFunction * surf_fit_grad
Definition tmop.hpp:1789
GridFunction * surf_fit_hess
Definition tmop.hpp:1789
void ReleasePADeviceMemory(bool copy_to_host=true)
Definition tmop.cpp:2854
struct mfem::TMOP_Integrator::@23 PA
virtual real_t GetDerefinementElementEnergy(const FiniteElement &el, ElementTransformation &T, const Vector &elfun)
Definition tmop.cpp:3413
void UpdateCoefficientsPA(const Vector &x_loc)
Definition tmop_pa.cpp:179
DenseMatrix PMatI
Definition tmop.hpp:1820
void GetSurfaceFittingErrors(const Vector &pos, real_t &err_avg, real_t &err_max)
Definition tmop.cpp:3079
const IntegrationRule & GradientIntegrationRule(const FiniteElement &el) const
Definition tmop.hpp:1943
void EnableAdaptiveLimiting(const GridFunction &z0, Coefficient &coeff, AdaptivityEvaluator &ae)
Restriction of the node positions to certain regions.
Definition tmop.cpp:2908
Coefficient * metric_coeff
Definition tmop.hpp:1753
GridFunction * adapt_lim_gf
Definition tmop.hpp:1774
void UpdateAfterMeshTopologyChange()
Definition tmop.cpp:3143
DenseMatrix Jrt
Definition tmop.hpp:1820
Coefficient * surf_fit_coeff
Definition tmop.hpp:1780
Array< int > surf_fit_dof_count
Definition tmop.hpp:1791
DenseMatrix Jpt
Definition tmop.hpp:1820
void EnableSurfaceFitting(const GridFunction &s0, const Array< bool > &smarker, Coefficient &coeff, AdaptivityEvaluator &ae)
Fitting of certain DOFs to the zero level set of a function.
Definition tmop.cpp:2943
void AssembleElemGradSurfFit(const FiniteElement &el_x, IsoparametricTransformation &Tpr, DenseMatrix &mat)
Definition tmop.cpp:3921
void UpdateSurfaceFittingWeight(real_t factor)
Update the surface fitting weight as surf_fit_coeff *= factor;.
Definition tmop.cpp:4225
Array< Vector * > ElemDer
Definition tmop.hpp:1807
const Array< bool > * surf_fit_marker
Definition tmop.hpp:1779
const IntegrationRule & ActionIntegrationRule(const FiniteElement &el) const
Definition tmop.hpp:1938
AdaptivityEvaluator * adapt_lim_eval
Definition tmop.hpp:1776
void AssembleElemVecSurfFit(const FiniteElement &el_x, IsoparametricTransformation &Tpr, DenseMatrix &mat)
Definition tmop.cpp:3840
void EnableLimiting(const GridFunction &n0, const GridFunction &dist, Coefficient &w0, TMOP_LimiterFunction *lfunc=NULL)
Limiting of the mesh displacements (general version).
Definition tmop.cpp:2883
void AssembleElementGradFD(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, DenseMatrix &elmat)
Definition tmop.cpp:4126
Base class for limiting functions to be used in class TMOP_Integrator.
Definition tmop.hpp:1172
virtual real_t Eval(const Vector &x, const Vector &x0, real_t d) const =0
Returns the limiting function, f(x, x0, d).
virtual void Eval_d1(const Vector &x, const Vector &x0, real_t dist, Vector &d1) const =0
Returns the gradient of the limiting function f(x, x0, d) with respect to x.
virtual void Eval_d2(const Vector &x, const Vector &x0, real_t dist, DenseMatrix &d2) const =0
Returns the Hessian of the limiting function f(x, x0, d) with respect to x.
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:224
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:206
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:212
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:200
virtual real_t EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:341
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:303
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:346
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:358
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:352
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:380
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:374
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:368
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:325
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:407
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:392
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:343
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:399
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:449
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:432
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:361
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:440
virtual real_t EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:465
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:474
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:497
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:377
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:485
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:543
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:533
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:397
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:513
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:600
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:581
virtual real_t EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:570
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:416
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:592
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:436
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:613
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:629
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:621
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:665
virtual real_t EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:642
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:649
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:454
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:657
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:690
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:473
virtual real_t EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:679
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:706
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:698
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:515
virtual real_t EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:719
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:725
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:733
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:742
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:755
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:773
const real_t eps
Definition tmop.hpp:631
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:798
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:803
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:632
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:789
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:831
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:651
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:811
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:819
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:858
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:865
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:670
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:874
virtual real_t EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:849
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:928
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:936
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:689
virtual real_t EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:909
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:918
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:974
virtual real_t EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:952
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:710
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:966
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:959
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:993
virtual real_t EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:986
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:731
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1008
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1000
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1037
const real_t eps
Definition tmop.hpp:752
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1029
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1020
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:753
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1077
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1072
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:772
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1052
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1093
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:792
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1101
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1085
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1136
virtual real_t EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:1114
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1120
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:810
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1128
virtual real_t EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:1150
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1157
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:829
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1173
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1165
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1219
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:850
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1197
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1208
virtual real_t EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:1187
virtual real_t EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:1245
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1255
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:871
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1266
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1282
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1326
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1333
virtual real_t EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:1319
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1342
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:892
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1358
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1378
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:1040
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1366
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1411
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1427
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:1058
virtual real_t EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:1404
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1418
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:286
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:306
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:222
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:246
Default limiter function in TMOP_Integrator.
Definition tmop.hpp:1193
virtual void Eval_d2(const Vector &x, const Vector &x0, real_t dist, DenseMatrix &d2) const
Returns the Hessian of the limiting function f(x, x0, d) with respect to x.
Definition tmop.hpp:1211
virtual real_t Eval(const Vector &x, const Vector &x0, real_t dist) const
Returns the limiting function, f(x, x0, d).
Definition tmop.hpp:1195
virtual void Eval_d1(const Vector &x, const Vector &x0, real_t dist, Vector &d1) const
Returns the gradient of the limiting function f(x, x0, d) with respect to x.
Definition tmop.hpp:1202
Abstract class for local mesh quality metrics in the target-matrix optimization paradigm (TMOP) by P....
Definition tmop.hpp:24
const DenseMatrix * Jtr
Definition tmop.hpp:26
virtual void SetTargetJacobian(const DenseMatrix &Jtr_)
Specify the reference-element -> target-element Jacobian matrix for the point of interest.
Definition tmop.hpp:43
virtual int Id() const
Return the metric ID.
Definition tmop.hpp:78
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const =0
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const =0
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
virtual real_t EvalW(const DenseMatrix &Jpt) const =0
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
virtual void SetMaxMuT(real_t max_muT_)
Definition tmop.hpp:213
virtual real_t EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:167
virtual WorstCaseType GetWorstCaseType()
Definition tmop.hpp:217
virtual void SetMinDetT(real_t min_detT_)
Definition tmop.hpp:211
virtual real_t EvalWBarrier(const DenseMatrix &Jpt) const
Definition tmop.cpp:184
Base class representing target-matrix construction algorithms for mesh optimization via the target-ma...
Definition tmop.hpp:1334
const TargetType target_type
Definition tmop.hpp:1360
bool Parallel() const
Definition tmop.hpp:1402
void ComputeAvgVolume() const
Definition tmop.cpp:1519
virtual void ComputeElementTargetsGradient(const IntegrationRule &ir, const Vector &elfun, IsoparametricTransformation &Tpr, DenseTensor &dJtr) const
Definition tmop.cpp:1719
virtual void ComputeElementTargets(int e_id, const FiniteElement &fe, const IntegrationRule &ir, const Vector &elfun, DenseTensor &Jtr) const
Given an element and quadrature rule, computes ref->target transformation Jacobians for each quadratu...
Definition tmop.cpp:1648
bool UsesPhysicalCoordinates() const
Return true if the methods ComputeElementTargets(), ComputeAllElementTargets(), and ComputeElementTar...
Definition tmop.hpp:1426
const GridFunction * nodes
Definition tmop.hpp:1357
virtual bool ContainsVolumeInfo() const
Checks if the target matrices contain non-trivial size specification.
Definition tmop.cpp:1634
void ComputeAllElementTargets_Fallback(const FiniteElementSpace &fes, const IntegrationRule &ir, const Vector &xe, DenseTensor &Jtr) const
Definition tmop.cpp:1562
const Array< int > & GetDofMap() const
Get an Array<int> that maps lexicographically ordered indices to the indices of the respective nodes/...
Definition fe_base.hpp:1222
Base class for vector Coefficients that optionally depend on time and space.
Vector data type.
Definition vector.hpp:80
virtual const real_t * HostRead() const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), false).
Definition vector.hpp:478
virtual const real_t * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
Definition vector.hpp:474
virtual real_t * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
Definition vector.hpp:490
void SetDataAndSize(real_t *d, int s)
Set the Vector data and size.
Definition vector.hpp:175
real_t Norml2() const
Returns the l2 norm of the vector.
Definition vector.cpp:832
int Size() const
Returns the size of the vector.
Definition vector.hpp:218
virtual void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
Definition vector.hpp:136
real_t Sum() const
Return the sum of the vector entries.
Definition vector.cpp:1283
void SetSize(int s)
Resize the vector to size s.
Definition vector.hpp:538
void NewDataAndSize(real_t *d, int s)
Set the Vector data and size, deleting the old data, if owned.
Definition vector.hpp:181
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
Definition vector.hpp:227
void SetData(real_t *d)
Definition vector.hpp:168
real_t Min() const
Returns the minimal element of the vector.
Definition vector.cpp:1212
void GetSubVector(const Array< int > &dofs, Vector &elemvect) const
Extract entries listed in dofs to the output Vector elemvect.
Definition vector.cpp:578
Vector beta
const real_t alpha
Definition ex15.cpp:369
int dim
Definition ex24.cpp:53
real_t omega
Definition ex25.cpp:142
real_t a
Definition lissajous.cpp:41
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
Definition table.cpp:476
void CalcAdjugateTranspose(const DenseMatrix &a, DenseMatrix &adjat)
Calculate the transposed adjugate of a matrix (for NxN matrices, N=1,2,3)
Geometry Geometries
Definition fe.cpp:49
void CalcInverse(const DenseMatrix &a, DenseMatrix &inva)
void InterpolateTMOP_QualityMetric(TMOP_QualityMetric &metric, const TargetConstructor &tc, const Mesh &mesh, GridFunction &metric_gf)
Interpolates the metric's values at the nodes of metric_gf.
Definition tmop.cpp:4906
void AddMultVWt(const Vector &v, const Vector &w, DenseMatrix &VWt)
VWt += v w^t.
void AddMultABt(const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &ABt)
ABt += A * B^t.
void MultAAt(const DenseMatrix &a, DenseMatrix &aat)
Calculate the matrix A.At.
void CalcInverseTranspose(const DenseMatrix &a, DenseMatrix &inva)
Calculate the inverse transpose of a matrix (for NxN matrices, N=1,2,3)
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
void AddMult(const DenseMatrix &b, const DenseMatrix &c, DenseMatrix &a)
Matrix matrix multiplication. A += B * C.
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Definition lor_mms.hpp:30
void forall(int N, lambda &&body)
Definition forall.hpp:754
void Add(const DenseMatrix &A, const DenseMatrix &B, real_t alpha, DenseMatrix &C)
C = A + alpha*B.
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
Definition intrules.hpp:486
real_t p(const Vector &x, real_t t)
RefCoord t[3]
RefCoord s[3]
Helper struct to convert a C++ type to an MPI type.