MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
tmop.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2026, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#include "tmop.hpp"
13#include "linearform.hpp"
14#include "pgridfunc.hpp"
15#include "tmop_tools.hpp"
16#include "../general/forall.hpp"
17#include "../linalg/dual.hpp"
18
19namespace mfem
20{
21
22/* AD related definitions below ========================================*/
23
24/// MFEM native AD-type for first derivatives
26/// MFEM native AD-type for second derivatives
28
29/*
30Functions for 2x2 DenseMatrix cast as std::vector<type>, assuming column-major storage
31*/
32template <typename type>
33type fnorm2_2D(const std::vector<type> &u)
34{
35 return u[0]*u[0] + u[1]*u[1] + u[2]*u[2] + u[3]*u[3];
36}
37
38template <typename type>
39type fnorm2_3D(const std::vector<type> &u)
40{
41 return u[0]*u[0] + u[1]*u[1] + u[2]*u[2] + u[3]*u[3] + u[4]*u[4] +
42 u[5]*u[5] + u[6]*u[6] + u[7]*u[7] + u[8]*u[8];
43}
44
45template <typename type>
46type det_2D(const std::vector<type> &u)
47{
48 return u[0]*u[3] - u[1]*u[2];
49}
50
51template <typename type>
52type det_3D(const std::vector<type> &u)
53{
54 return u[0]*(u[4]*u[8] - u[5]*u[7]) -
55 u[1]*(u[3]*u[8] - u[5]*u[6]) +
56 u[2]*(u[3]*u[7] - u[4]*u[6]);
57}
58
59template <typename type>
60void mult_2D(const std::vector<type> &u, const std::vector<type> &M,
61 std::vector<type> &mat)
62{
63 mat.resize(u.size());
64
65 mat[0] = u[0]*M[0] + u[2]*M[1];
66 mat[1] = u[1]*M[0] + u[3]*M[1];
67 mat[2] = u[0]*M[2] + u[2]*M[3];
68 mat[3] = u[1]*M[2] + u[3]*M[3];
69}
70
71template <typename type>
72void mult_aTa_2D(const std::vector<type> &in, std::vector<type> &outm)
73{
74 outm.resize(in.size());
75 outm[0] = in[0]*in[0];
76 outm[1] = in[0]*in[2] + in[1]*in[3];
77 outm[2] = in[0]*in[2] + in[1]*in[3];
78 outm[3] = in[3]*in[3];
79}
80
81template <typename scalartype, typename type>
82void add_2D(const scalartype &scalar, const std::vector<type> &u,
83 const DenseMatrix *M, std::vector<type> &mat)
84{
85 mat.resize(u.size());
86 mat[0] = u[0] + scalar * M->Elem(0,0);
87 mat[1] = u[1] + scalar * M->Elem(1,0);
88 mat[2] = u[2] + scalar * M->Elem(0,1);
89 mat[3] = u[3] + scalar * M->Elem(1,1);
90}
91
92template <typename scalartype, typename type>
93void add_2D(const scalartype &scalar, const std::vector<type> &u,
94 const std::vector<type> &M, std::vector<type> &mat)
95{
96 mat.resize(M.size());
97 mat[0] = u[0] + scalar * M[0];
98 mat[1] = u[1] + scalar * M[1];
99 mat[2] = u[2] + scalar * M[2];
100 mat[3] = u[3] + scalar * M[3];
101}
102
103template <typename type>
104void adjoint_2D(const std::vector<type> &in, std::vector<type> &outm)
105{
106 outm.resize(in.size());
107 outm[0] = in[3];
108 outm[1] = -in[1];
109 outm[2] = -in[2];
110 outm[3] = in[0];
111}
112
113template <typename type>
114void transpose_2D(const std::vector<type> &in, std::vector<type> &outm)
115{
116 outm.resize(in.size());
117 outm[0] = in[0];
118 outm[1] = in[2];
119 outm[2] = in[1];
120 outm[3] = in[3];
121}
122
123template <typename scalartype, typename type>
124void add_3D(const scalartype &scalar, const std::vector<type> &u,
125 const DenseMatrix *M, std::vector<type> &mat)
126{
127 mat.resize(u.size());
128 mat[0] = u[0] + scalar * M->Elem(0,0);
129 mat[1] = u[1] + scalar * M->Elem(1,0);
130 mat[2] = u[2] + scalar * M->Elem(2,0);
131
132 mat[3] = u[3] + scalar * M->Elem(0,1);
133 mat[4] = u[4] + scalar * M->Elem(1,1);
134 mat[5] = u[5] + scalar * M->Elem(2,1);
135
136 mat[6] = u[6] + scalar * M->Elem(0,2);
137 mat[7] = u[7] + scalar * M->Elem(1,2);
138 mat[8] = u[8] + scalar * M->Elem(2,2);
139}
140
141/* Metric definitions */
142
143// W = ||T||^2 - 2*det(T).
144template <typename type>
145type mu4_ad(const std::vector<type> &T, const std::vector<type> &W)
146{
147 auto fnorm2 = fnorm2_2D(T);
148 auto det = det_2D(T);
149 return fnorm2 - 2*det;
150};
151
152// W = ||T-I||^2.
153template <typename type>
154type mu14_ad(const std::vector<type> &T, const std::vector<type> &W)
155{
156 DenseMatrix Id(2,2); Id = 0.0;
157 Id(0,0) = 1; Id(1,1) = 1;
158
159 std::vector<type> Mat;
160 add_2D(real_t{-1.0}, T, &Id, Mat);
161
162 return fnorm2_2D(Mat);
163};
164
165// W = (det(T)-1)^2.
166template <typename type>
167type mu55_ad(const std::vector<type> &T, const std::vector<type> &W)
168{
169 auto det = det_2D(T);
170 return pow(det-1.0, 2.0);
171};
172
173// W = |T-T'|^2, where T'= |T|*I/sqrt(2).
174template <typename type>
175type mu85_ad(const std::vector<type> &T, const std::vector<type> &W)
176{
177 auto fnorm = sqrt(fnorm2_2D(T));
178 return T[1]*T[1] + T[2]*T[2] +
179 (T[0] - fnorm/sqrt(2))*(T[0] - fnorm/sqrt(2)) +
180 (T[3] - fnorm/sqrt(2))*(T[3] - fnorm/sqrt(2));
181};
182
183// W = 1/tau |T-I|^2.
184template <typename type>
185type mu98_ad(const std::vector<type> &T, const std::vector<type> &W)
186{
187 DenseMatrix Id(2,2); Id = 0.0;
188 Id(0,0) = 1; Id(1,1) = 1;
189
190 std::vector<type> Mat;
191 add_2D(real_t{-1.0}, T, &Id, Mat);
192
193 return fnorm2_2D(Mat)/det_2D(T);
194};
195
196template <typename type>
198{
199 return 1.0;
200}
201// add specialization for AD1Type
202template <>
204{
205 return AD1Type{1.0, 0.0};
206}
207// add specialization for AD2Type
208template <>
210{
211 return AD2Type{AD1Type{1.0, 0.0}, AD1Type{0.0, 0.0}};
212}
213
215template <typename type>
216type wcuo_ad(type mu,
217 const std::vector<type> &T, const std::vector<type> &W,
218 real_t alpha, real_t min_detT, real_t detT_ep,
219 int exponent, real_t max_muT, real_t muT_ep,
222{
223 type one = make_one_type<type>();
224 type zero = 0.0*one;
225 type denom = one;
227 {
228 auto val1 = alpha*min_detT-detT_ep < 0.0 ?
229 (alpha*min_detT-detT_ep)*one :
230 zero;
231 denom = 2.0*(det_2D(T)-val1);
232 }
233 else if (bt == TWCUO::BarrierType::Pseudo)
234 {
235 auto detT = det_2D(T);
236 denom = detT + sqrt(detT*detT + detT_ep*detT_ep);
237 }
238 mu = mu/denom;
239
241 {
242 auto exp = exponent*one;
243 mu = pow(mu, exp);
244 }
245 else if (wct == TWCUO::WorstCaseType::Beta)
246 {
247 auto beta = (max_muT+muT_ep)*one;
248 mu = mu/(beta-mu);
249 }
250 return mu;
251}
252
253// W = 1/(tau^0.5) |T-I|^2.
254template <typename type>
255type mu342_ad(const std::vector<type> &T, const std::vector<type> &W)
256{
257 DenseMatrix Id(3,3); Id = 0.0;
258 Id(0,0) = 1; Id(1,1) = 1; Id(2,2) = 1;
259
260 std::vector<type> Mat;
261 add_3D(real_t{-1.0}, T, &Id, Mat);
262
263 return fnorm2_3D(Mat)/sqrt(det_3D(T));
264};
265
266// (1/4 alpha) | A - (adj A)^t W^t W / omega |^2
267template <typename type>
268type nu11_ad(const std::vector<type> &T, const std::vector<type> &W)
269{
270 std::vector<type> A; // T*W = A
271 std::vector<type> AdjA,AdjAt, WtW, WRK, WRK2;
272
273 mult_2D(T,W,A); // We assume that both A and W are nonsingular.
274
275 auto alpha = det_2D(A);
276 auto omega = det_2D(W);
277 adjoint_2D(A, AdjA);
278 transpose_2D(AdjA, AdjAt);
279
280 mult_aTa_2D(W, WtW);
281 mult_2D(AdjAt, WtW, WRK);
282
283 add_2D(-1.0/omega, A, WRK, WRK2);
284 auto fnorm = fnorm2_2D(WRK2);
285
286 return 0.25 / (alpha) * fnorm;
287};
288
289// 0.5 * ( sqrt(alpha/omega) - sqrt(omega/alpha) )^2
290template <typename type>
291type nu14_ad(const std::vector<type> &T, const std::vector<type> &W)
292{
293 std::vector<type> A; // T*W = A
294 mult_2D(T,W,A);
295
296 auto sqalpha = sqrt(det_2D(A));
297 auto sqomega = sqrt(det_2D(W));
298
299 return 0.5*pow(sqalpha/sqomega - sqomega/sqalpha, 2.0);
300};
301
302// (1/alpha) | A - W |^2
303template <typename type>
304type nu36_ad(const std::vector<type> &T, const std::vector<type> &W)
305{
306 std::vector<type> A; // T*W = A
307 std::vector<type> AminusW; // A-W
308
309 mult_2D(T,W,A);
310 add_2D(-1.0,A,W,AminusW);
311 auto fnorm = fnorm2_2D(AminusW);
312
313 return 1.0 / (det_2D(A)) * fnorm;
314};
315
316// [ 1.0 - cos( phi_A - phi_W ) ] / (sin phi_A * sin phi_W)
317template <typename type>
318type nu50_ad(const std::vector<type> &T, const std::vector<type> &W)
319{
320 // We assume that both A and W are nonsingular.
321 std::vector<type> A;
322 mult_2D(T,W,A);
323 auto l1_A = sqrt(A[0]*A[0] + A[1]*A[1]);
324 auto l2_A = sqrt(A[2]*A[2] + A[3]*A[3]);
325 auto prod_A = l1_A*l2_A;
326 auto det_A = A[0]*A[3] - A[1]*A[2];
327 auto sin_A = det_A/prod_A;
328 auto cos_A = (A[0]*A[2] + A[1]*A[3])/prod_A;
329
330 auto l1_W = sqrt(W[0]*W[0] + W[1]*W[1]);
331 auto l2_W = sqrt(W[2]*W[2] + W[3]*W[3]);
332 auto prod_W = l1_W*l2_W;
333 auto det_W = W[0]*W[3] - W[1]*W[2];
334 auto sin_W = det_W/prod_W;
335 auto cos_W = (W[0]*W[2] + W[1]*W[3])/prod_W;
336
337 return (1.0 - cos_A*cos_W - sin_A*sin_W)/(sin_A*sin_W);
338};
339
340// [ 0.5 * (ups_A / ups_W + ups_W / ups_A) - cos(phi_A - phi_W) ] /
341// (sin phi_A * sin phi_W), where ups = l_1 l_2 sin(phi)
342template <typename type>
343type nu51_ad(const std::vector<type> &T, const std::vector<type> &W)
344{
345 std::vector<type> A;
346 mult_2D(T,W,A);
347 // We assume that both A and W are nonsingular.
348 auto l1_A = sqrt(A[0]*A[0] + A[1]*A[1]);
349 auto l2_A = sqrt(A[2]*A[2] + A[3]*A[3]);
350 auto prod_A = l1_A*l2_A;
351 auto det_A = A[0]*A[3] - A[1]*A[2];
352 auto sin_A = det_A/prod_A;
353 auto cos_A = (A[0]*A[2] + A[1]*A[3])/prod_A;
354 auto ups_A = l1_A*l2_A*sin_A;
355
356 auto l1_W = sqrt(W[0]*W[0] + W[1]*W[1]);
357 auto l2_W = sqrt(W[2]*W[2] + W[3]*W[3]);
358 auto prod_W = l1_W*l2_W;
359 auto det_W = W[0]*W[3] - W[1]*W[2];
360 auto sin_W = det_W/prod_W;
361 auto cos_W = (W[0]*W[2] + W[1]*W[3])/prod_W;
362 auto ups_W = l1_W*l2_W*sin_W;
363
364 return (0.5 * (ups_A / ups_W + ups_W / ups_A) - cos_A*cos_W - sin_A*sin_W) /
365 (sin_A*sin_W);
366};
367
368// (1/2 alpha) | A - (|A|/|W|) W |^2
369template <typename type>
370type nu107_ad(const std::vector<type> &T, const std::vector<type> &W)
371{
372 std::vector<type> A; // T*W = A
373 std::vector<type> Mat; // A-W
374 mult_2D(T,W,A);
375
376 auto alpha = det_2D(A);
377 auto aw = sqrt(fnorm2_2D(A))/sqrt(fnorm2_2D(W));
378
379 add_2D(-aw, A, W, Mat);
380 return (0.5/alpha)*fnorm2_2D(Mat);
381};
382
383// 0.5[ 1.0 - cos( phi_A - phi_W ) ]
384template <typename type>
385type skew2D_ad(const std::vector<type> &T, const std::vector<type> &W)
386{
387 // We assume that both A and W are nonsingular.
388 std::vector<type> A;
389 mult_2D(T,W,A);
390 auto l1_A = sqrt(A[0]*A[0] + A[1]*A[1]);
391 auto l2_A = sqrt(A[2]*A[2] + A[3]*A[3]);
392 auto prod_A = l1_A*l2_A;
393 auto det_A = A[0]*A[3] - A[1]*A[2];
394 auto sin_A = det_A/prod_A;
395 auto cos_A = (A[0]*A[2] + A[1]*A[3])/prod_A;
396
397 auto l1_W = sqrt(W[0]*W[0] + W[1]*W[1]);
398 auto l2_W = sqrt(W[2]*W[2] + W[3]*W[3]);
399 auto prod_W = l1_W*l2_W;
400 auto det_W = W[0]*W[3] - W[1]*W[2];
401 auto sin_W = det_W/prod_W;
402 auto cos_W = (W[0]*W[2] + W[1]*W[3])/prod_W;
403
404 return 0.5*(1.0 - cos_A*cos_W - sin_A*sin_W);
405};
406
407// Given mu(X,Y), compute dmu/dX or dmu/dY. Y is an optional parameter when
408// computing dmu/dX.
409void ADGrad(std::function<AD1Type(std::vector<AD1Type>&,
410 std::vector<AD1Type>&)>mu_ad,
411 DenseMatrix &dmu, //output
412 const DenseMatrix &X, // parameter 1
413 const DenseMatrix *Y = nullptr, //parameter 2
414 const bool dX = true /*derivative with respect to X*/)
415{
416 int matsize = X.TotalSize();
417 std::vector<AD1Type> adX(matsize), adY(matsize);
418
419 for (int i=0; i<matsize; i++) { adX[i] = AD1Type{X.GetData()[i], 0.0}; }
420 if (Y)
421 {
422 for (int i=0; i<matsize; i++) { adY[i] = AD1Type{Y->GetData()[i], 0.0}; }
423 }
424
425 if (dX)
426 {
427 for (int i=0; i<matsize; i++)
428 {
429 adX[i] = AD1Type{X.GetData()[i], 1.0};
430 AD1Type rez = mu_ad(adX, adY);
431 dmu.GetData()[i] = rez.gradient;
432 adX[i] = AD1Type{X.GetData()[i], 0.0};
433 }
434 }
435 else
436 {
437 MFEM_VERIFY(Y, "Y cannot be nullptr when dX = false.");
438 for (int i=0; i<matsize; i++)
439 {
440 adY[i] = AD1Type{Y->GetData()[i], 1.0};
441 AD1Type rez = mu_ad(adX,adY);
442 dmu.GetData()[i] = rez.gradient;
443 adY[i] = AD1Type{Y->GetData()[i], 0.0};
444 }
445 }
446}
447
448// Given mu(X,Y), compute d2mu/dX2, where Y is an optional parameter.
449void ADHessian(std::function<AD2Type(std::vector<AD2Type>&,
450 std::vector<AD2Type>&)> mu_ad,
451 DenseTensor &d2mu_dX2,
452 const DenseMatrix &X,
453 const DenseMatrix *Y = nullptr)
454{
455 const int matsize = X.TotalSize();
456
457 //use forward-forward mode
458 std::vector<AD2Type> aduu(matsize), adY(matsize);
459 for (int ii = 0; ii < matsize; ii++)
460 {
461 aduu[ii].value = AD1Type{X.GetData()[ii], 0.0};
462 aduu[ii].gradient = AD1Type{0.0, 0.0};
463 }
464 if (Y)
465 {
466 for (int ii=0; ii<matsize; ii++)
467 {
468 adY[ii].value = AD1Type{Y->GetData()[ii], 0.0};
469 adY[ii].gradient = AD1Type{0.0, 0.0};
470 }
471 }
472
473 for (int ii = 0; ii < matsize; ii++)
474 {
475 aduu[ii].value = AD1Type{X.GetData()[ii], 1.0};
476 for (int jj = 0; jj < (ii + 1); jj++)
477 {
478 aduu[jj].gradient = AD1Type{1.0, 0.0};
479 AD2Type rez = mu_ad(aduu, adY);
480 d2mu_dX2(ii).GetData()[jj] = rez.gradient.gradient;
481 d2mu_dX2(jj).GetData()[ii] = rez.gradient.gradient;
482 aduu[jj].gradient = AD1Type{0.0, 0.0};
483 }
484 aduu[ii].value = AD1Type{X.GetData()[ii], 0.0};
485 }
486 return;
487}
488/* end AD related definitions ========================================*/
489
490// Target-matrix optimization paradigm (TMOP) mesh quality metrics.
491
493 const DenseMatrix &DS,
494 const real_t weight,
495 DenseMatrix &A) const
496{
497 const int dof = DS.Height(), dim = DS.Width();
498
499 // The first two go over the rows and cols of dP_dJ where P = dW_dJ.
500 for (int r = 0; r < dim; r++)
501 {
502 for (int c = 0; c < dim; c++)
503 {
504 DenseMatrix Hrc = H(r+c*dim);
505
506 // Compute each entry of d(Prc)_dJ.
507 for (int rr = 0; rr < dim; rr++)
508 {
509 for (int cc = 0; cc < dim; cc++)
510 {
511 const real_t entry_rr_cc = Hrc(rr, cc);
512
513 for (int i = 0; i < dof; i++)
514 {
515 for (int j = 0; j < dof; j++)
516 {
517 A(i+r*dof, j+rr*dof) +=
518 weight * DS(i, c) * DS(j, cc) * entry_rr_cc;
519 }
520 }
521 }
522 }
523 }
524 }
525}
526
528{
529 real_t metric = 0.;
530 for (int i = 0; i < tmop_q_arr.Size(); i++)
531 {
532 metric += wt_arr[i]*tmop_q_arr[i]->EvalWMatrixForm(Jpt);
533 }
534 return metric;
535}
536
538{
539 real_t metric = 0.;
540 for (int i = 0; i < tmop_q_arr.Size(); i++)
541 {
542 metric += wt_arr[i]*tmop_q_arr[i]->EvalW(Jpt);
543 }
544 return metric;
545}
546
548 DenseMatrix &P) const
549{
550 DenseMatrix Pt(P.Size());
551 P = 0.0;
552 for (int i = 0; i < tmop_q_arr.Size(); i++)
553 {
554 tmop_q_arr[i]->EvalP(Jpt, Pt);
555 P.Add(wt_arr[i], Pt);
556 }
557}
558
560 DenseMatrix &PW) const
561{
562 DenseMatrix Pt(PW.Size());
563 PW = 0.0;
564 for (int i = 0; i < tmop_q_arr.Size(); i++)
565 {
566 tmop_q_arr[i]->EvalPW(Jpt, Pt);
567 PW.Add(wt_arr[i], Pt);
568 }
569}
570
571AD1Type TMOP_Combo_QualityMetric::EvalW_AD1(const std::vector<AD1Type> &T,
572 const std::vector<AD1Type> &W)
573const
574{
575 AD1Type metric = {0., 0.};
576 for (int i = 0; i < tmop_q_arr.Size(); i++)
577 {
578 metric += wt_arr[i]*tmop_q_arr[i]->EvalW_AD1(T, W);
579 }
580 return metric;
581}
582
583AD2Type TMOP_Combo_QualityMetric::EvalW_AD2(const std::vector<AD2Type> &T,
584 const std::vector<AD2Type> &W)
585const
586{
587 AD2Type metric = {{0., 0.},{0., 0.}};
588 for (int i = 0; i < tmop_q_arr.Size(); i++)
589 {
590 metric += wt_arr[i]*tmop_q_arr[i]->EvalW_AD2(T, W);
591 }
592 return metric;
593}
594
596 const DenseMatrix &DS,
597 const real_t weight,
598 DenseMatrix &A) const
599{
600 DenseMatrix At(A.Size());
601 for (int i = 0; i < tmop_q_arr.Size(); i++)
602 {
603 At = 0.0;
604 tmop_q_arr[i]->AssembleH(Jpt, DS, weight * wt_arr[i], At);
605 A += At;
606 }
607}
608
610 const GridFunction &nodes, const TargetConstructor &tc,
611 Vector &weights, bool use_pa, const IntegrationRule *IntRule) const
612{
613 const int m_cnt = tmop_q_arr.Size();
614 Vector averages;
615 ComputeAvgMetrics(nodes, tc, averages, use_pa, IntRule);
616 weights.SetSize(m_cnt);
617
618 // For [ combo_A_B_C = a m_A + b m_B + c m_C ] we would have:
619 // a = BC / (AB + AC + BC), b = AC / (AB + AC + BC), c = AB / (AB + AC + BC),
620 // where A = avg_m_A, B = avg_m_B, C = avg_m_C.
621 // Nested loop to avoid division, as some avg may be 0.
622 Vector products_no_m(m_cnt); products_no_m = 1.0;
623 for (int m_p = 0; m_p < m_cnt; m_p++)
624 {
625 for (int m_a = 0; m_a < m_cnt; m_a++)
626 {
627 if (m_p != m_a) { products_no_m(m_p) *= averages(m_a); }
628 }
629 }
630 const real_t pnm_sum = products_no_m.Sum();
631
632 if (pnm_sum == 0.0) { weights = 1.0 / m_cnt; return; }
633 for (int m = 0; m < m_cnt; m++) { weights(m) = products_no_m(m) / pnm_sum; }
634
635 MFEM_ASSERT(fabs(weights.Sum() - 1.0) < 1e-14,
636 "Error: sum should be 1 always: " << weights.Sum());
637}
638
640 const GridFunction &nodes, const TargetConstructor &tc,
641 Vector &averages, bool use_pa, const IntegrationRule *IntRule) const
642{
643 const int m_cnt = tmop_q_arr.Size(),
644 NE = nodes.FESpace()->GetNE(),
645 dim = nodes.FESpace()->GetMesh()->Dimension();
646
647 averages.SetSize(m_cnt);
648
649 auto fe = nodes.FESpace()->GetTypicalFE();
650 const IntegrationRule &ir =
651 (IntRule) ? *IntRule : IntRules.Get(fe->GetGeomType(), 2*fe->GetOrder());
652
653 // Integrals of all metrics.
654 averages = 0.0;
655 real_t volume = 0.0;
656 if (use_pa)
657 {
658 for (int m = 0; m < m_cnt; m++)
659 {
660 if (dim == 2)
661 {
662 GetLocalEnergyPA_2D(nodes, tc, m, averages(m), volume, ir);
663 }
664 else
665 {
666 GetLocalEnergyPA_3D(nodes, tc, m, averages(m), volume, ir);
667 }
668 }
669 }
670 else
671 {
672 Array<int> pos_dofs;
673 for (int e = 0; e < NE; e++)
674 {
675 const FiniteElement &fe_pos = *nodes.FESpace()->GetFE(e);
676 const int nsp = ir.GetNPoints(), dof = fe_pos.GetDof();
677
678 DenseMatrix dshape(dof, dim);
679 DenseMatrix pos(dof, dim);
680 pos.SetSize(dof, dim);
681 Vector posV(pos.Data(), dof * dim);
682
683 nodes.FESpace()->GetElementVDofs(e, pos_dofs);
684 nodes.GetSubVector(pos_dofs, posV);
685
686 DenseTensor W(dim, dim, nsp);
687 DenseMatrix Winv(dim), T(dim), A(dim);
688 tc.ComputeElementTargets(e, fe_pos, ir, posV, W);
689
690 for (int q = 0; q < nsp; q++)
691 {
692 const DenseMatrix &Wj = W(q);
693 CalcInverse(Wj, Winv);
694
695 const IntegrationPoint &ip = ir.IntPoint(q);
696 fe_pos.CalcDShape(ip, dshape);
697 MultAtB(pos, dshape, A);
698 Mult(A, Winv, T);
699
700 const real_t w_detA = ip.weight * A.Det();
701 for (int m = 0; m < m_cnt; m++)
702 {
703 tmop_q_arr[m]->SetTargetJacobian(Wj);
704 averages(m) += tmop_q_arr[m]->EvalW(T) * w_detA;
705 }
706 volume += w_detA;
707 }
708 }
709 }
710
711 // Parallel case.
712#ifdef MFEM_USE_MPI
713 auto par_nodes = dynamic_cast<const ParGridFunction *>(&nodes);
714 if (par_nodes)
715 {
716 MPI_Allreduce(MPI_IN_PLACE, averages.GetData(), m_cnt,
717 MPITypeMap<real_t>::mpi_type, MPI_SUM, par_nodes->ParFESpace()->GetComm());
718 MPI_Allreduce(MPI_IN_PLACE, &volume, 1, MPITypeMap<real_t>::mpi_type, MPI_SUM,
719 par_nodes->ParFESpace()->GetComm());
720 }
721#endif
722
723 averages /= volume;
724}
725
727const
728{
729 real_t metric_tilde = EvalWBarrier(Jpt);
730 real_t metric = metric_tilde;
732 {
733 metric = std::pow(metric_tilde, exponent);
734 }
735 else if (wctype == WorstCaseType::Beta)
736 {
737 real_t beta = max_muT+muT_ep;
738 metric = metric_tilde/(beta-metric_tilde);
739 }
740 return metric;
741}
742
744 const DenseMatrix &Jpt) const
745{
746 real_t denominator = 1.0;
748 {
749 denominator = 2.0*(Jpt.Det()-std::min(alpha*min_detT-detT_ep, (real_t) 0.0));
750 }
751 else if (btype == BarrierType::Pseudo)
752 {
753 real_t detT = Jpt.Det();
754 denominator = detT + std::sqrt(detT*detT + detT_ep*detT_ep);
755 }
756 return tmop_metric.EvalW(Jpt)/denominator;
757}
758
760 const std::vector<AD1Type> &T,
761 const std::vector<AD1Type> &W) const
762{
763 return wcuo_ad(tmop_metric.EvalW_AD1(T,W), T, W, alpha, min_detT, detT_ep,
765}
766
768 const std::vector<AD2Type> &T,
769 const std::vector<AD2Type> &W) const
770{
771 return wcuo_ad(tmop_metric.EvalW_AD2(T,W), T, W, alpha, min_detT, detT_ep,
773}
774
776 DenseMatrix &P) const
777{
778 auto mu_ad_fn = [this](std::vector<AD1Type> &T, std::vector<AD1Type> &W)
779 {
780 return EvalW_AD1(T,W);
781 };
782 if (tmop_metric.Id() == 4 || tmop_metric.Id() == 14 ||
783 tmop_metric.Id() == 66)
784 {
785 ADGrad(mu_ad_fn, P, Jpt);
786 return;
787 }
788 MFEM_ABORT("EvalW_AD1 not implemented with this metric for "
789 "TMOP_WorstCaseUntangleOptimizer_Metric. "
790 "Please use metric 4/14/66.");
791}
792
794 const DenseMatrix &Jpt,
795 const DenseMatrix &DS,
796 const real_t weight,
797 DenseMatrix &A) const
798{
799 DenseTensor H(Jpt.Height(), Jpt.Height(), Jpt.TotalSize());
800 H = 0.0;
801 auto mu_ad_fn = [this](std::vector<AD2Type> &T, std::vector<AD2Type> &W)
802 {
803 return EvalW_AD2(T,W);
804 };
805 if (tmop_metric.Id() == 4 || tmop_metric.Id() == 14 ||
806 tmop_metric.Id() == 66)
807 {
808 ADHessian(mu_ad_fn, H, Jpt);
809 this->DefaultAssembleH(H,DS,weight,A);
810 return;
811 }
812 MFEM_ABORT("EvalW_AD1 not implemented with this metric for "
813 "TMOP_WorstCaseUntangleOptimizer_Metric. "
814 "Please use metric 4/14/66.");
815}
816
818{
819 ie.SetJacobian(Jpt.GetData());
820 return ie.Get_I1();
821}
822
824{
825 ie.SetJacobian(Jpt.GetData());
826 P = ie.Get_dI1();
827}
828
830 const DenseMatrix &DS,
831 const real_t weight,
832 DenseMatrix &A) const
833{
834 ie.SetJacobian(Jpt.GetData());
837}
838
840{
841 MFEM_VERIFY(Jtr != NULL,
842 "Requires a target Jacobian, use SetTargetJacobian().");
843 int matsize = Jpt.TotalSize();
844 std::vector<AD1Type> T(matsize), W(matsize);
845 for (int i=0; i<matsize; i++)
846 {
847 T[i] = AD1Type{Jpt.GetData()[i], 0.0};
848 W[i] = AD1Type{Jtr->GetData()[i], 0.0};
849 }
850 return skew2D_ad(T, W).value;
851}
852
854{
855 ADGrad(skew2D_ad<AD1Type>, P, Jpt, Jtr);
856 return;
857}
858
860{
861 ADGrad(skew2D_ad<AD1Type>, PW, Jpt, Jtr, false);
862 return;
863}
864
866 const DenseMatrix &DS,
867 const real_t weight,
868 DenseMatrix &A) const
869{
870 const int dim = Jpt.Height();
871 DenseTensor H(dim, dim, dim*dim); H = 0.0;
873 this->DefaultAssembleH(H,DS,weight,A);
874}
875
877{
878 MFEM_VERIFY(Jtr != NULL,
879 "Requires a target Jacobian, use SetTargetJacobian().");
880
881 DenseMatrix Jpr(3, 3);
882 Mult(Jpt, *Jtr, Jpr);
883
884 Vector col1, col2, col3;
885 Jpr.GetColumn(0, col1);
886 Jpr.GetColumn(1, col2);
887 Jpr.GetColumn(2, col3);
888 real_t norm_c1 = col1.Norml2(),
889 norm_c2 = col2.Norml2(),
890 norm_c3 = col3.Norml2();
891 real_t cos_Jpr_12 = (col1 * col2) / (norm_c1 * norm_c2),
892 cos_Jpr_13 = (col1 * col3) / (norm_c1 * norm_c3),
893 cos_Jpr_23 = (col2 * col3) / (norm_c2 * norm_c3);
894 real_t sin_Jpr_12 = std::sqrt(1.0 - cos_Jpr_12 * cos_Jpr_12),
895 sin_Jpr_13 = std::sqrt(1.0 - cos_Jpr_13 * cos_Jpr_13),
896 sin_Jpr_23 = std::sqrt(1.0 - cos_Jpr_23 * cos_Jpr_23);
897
898 Jtr->GetColumn(0, col1);
899 Jtr->GetColumn(1, col2);
900 Jtr->GetColumn(2, col3);
901 norm_c1 = col1.Norml2();
902 norm_c2 = col2.Norml2(),
903 norm_c3 = col3.Norml2();
904 real_t cos_Jtr_12 = (col1 * col2) / (norm_c1 * norm_c2),
905 cos_Jtr_13 = (col1 * col3) / (norm_c1 * norm_c3),
906 cos_Jtr_23 = (col2 * col3) / (norm_c2 * norm_c3);
907 real_t sin_Jtr_12 = std::sqrt(1.0 - cos_Jtr_12 * cos_Jtr_12),
908 sin_Jtr_13 = std::sqrt(1.0 - cos_Jtr_13 * cos_Jtr_13),
909 sin_Jtr_23 = std::sqrt(1.0 - cos_Jtr_23 * cos_Jtr_23);
910
911 return (3.0 - cos_Jpr_12 * cos_Jtr_12 - sin_Jpr_12 * sin_Jtr_12
912 - cos_Jpr_13 * cos_Jtr_13 - sin_Jpr_13 * sin_Jtr_13
913 - cos_Jpr_23 * cos_Jtr_23 - sin_Jpr_23 * sin_Jtr_23) / 6.0;
914}
915
917{
918 MFEM_VERIFY(Jtr != NULL,
919 "Requires a target Jacobian, use SetTargetJacobian().");
920
921 DenseMatrix Jpr(2, 2);
922 Mult(Jpt, *Jtr, Jpr);
923
924 Vector col1, col2;
925 Jpr.GetColumn(0, col1);
926 Jpr.GetColumn(1, col2);
927 const real_t ratio_Jpr = col2.Norml2() / col1.Norml2();
928
929 Jtr->GetColumn(0, col1);
930 Jtr->GetColumn(1, col2);
931 const real_t ratio_Jtr = col2.Norml2() / col1.Norml2();
932
933 return 0.5 * (ratio_Jpr / ratio_Jtr + ratio_Jtr / ratio_Jpr) - 1.0;
934}
935
937{
938 MFEM_VERIFY(Jtr != NULL,
939 "Requires a target Jacobian, use SetTargetJacobian().");
940
941 DenseMatrix Jpr(3, 3);
942 Mult(Jpt, *Jtr, Jpr);
943
944 Vector col1, col2, col3;
945 Jpr.GetColumn(0, col1);
946 Jpr.GetColumn(1, col2);
947 Jpr.GetColumn(2, col3);
948 real_t norm_c1 = col1.Norml2(),
949 norm_c2 = col2.Norml2(),
950 norm_c3 = col3.Norml2();
951 real_t ratio_Jpr_1 = norm_c1 / std::sqrt(norm_c2 * norm_c3),
952 ratio_Jpr_2 = norm_c2 / std::sqrt(norm_c1 * norm_c3),
953 ratio_Jpr_3 = norm_c3 / std::sqrt(norm_c1 * norm_c2);
954
955 Jtr->GetColumn(0, col1);
956 Jtr->GetColumn(1, col2);
957 Jtr->GetColumn(2, col3);
958 norm_c1 = col1.Norml2();
959 norm_c2 = col2.Norml2();
960 norm_c3 = col3.Norml2();
961 real_t ratio_Jtr_1 = norm_c1 / std::sqrt(norm_c2 * norm_c3),
962 ratio_Jtr_2 = norm_c2 / std::sqrt(norm_c1 * norm_c3),
963 ratio_Jtr_3 = norm_c3 / std::sqrt(norm_c1 * norm_c2);
964
965 return ( 0.5 * (ratio_Jpr_1 / ratio_Jtr_1 + ratio_Jtr_1 / ratio_Jpr_1) +
966 0.5 * (ratio_Jpr_2 / ratio_Jtr_2 + ratio_Jtr_2 / ratio_Jpr_2) +
967 0.5 * (ratio_Jpr_3 / ratio_Jtr_3 + ratio_Jtr_3 / ratio_Jpr_3) - 3.0
968 ) / 3.0;
969}
970
972{
973 return 0.5 * Jpt.FNorm2() / Jpt.Det() - 1.0;
974}
975
977{
978 ie.SetJacobian(Jpt.GetData());
979 return 0.5 * ie.Get_I1b() - 1.0;
980}
981
983{
984 ie.SetJacobian(Jpt.GetData());
985 P.Set(0.5, ie.Get_dI1b());
986}
987
989 const DenseMatrix &DS,
990 const real_t weight,
991 DenseMatrix &A) const
992{
993 ie.SetJacobian(Jpt.GetData());
996}
997
999{
1000 ie.SetJacobian(Jpt.GetData());
1001 return ie.Get_I1() - 2.0*ie.Get_I2b();
1002}
1003
1005{
1006 ie.SetJacobian(Jpt.GetData());
1007 Add(1.0, ie.Get_dI1(), -2.0, ie.Get_dI2b(), P);
1008}
1009
1011 const DenseMatrix &DS,
1012 const real_t weight,
1013 DenseMatrix &A) const
1014{
1015 ie.SetJacobian(Jpt.GetData());
1017
1019 ie.Assemble_ddI2b(-2.0*weight, A.GetData());
1020}
1021
1022template <typename type>
1023type TMOP_Metric_004::EvalW_AD_impl(const std::vector<type> &T,
1024 const std::vector<type> &W) const
1025{
1026 return mu4_ad(T, W);
1027}
1028
1029AD1Type TMOP_Metric_004::EvalW_AD1(const std::vector<AD1Type> &T,
1030 const std::vector<AD1Type> &W) const
1031{
1032 return EvalW_AD_impl<AD1Type>(T,W);
1033}
1034
1035AD2Type TMOP_Metric_004::EvalW_AD2(const std::vector<AD2Type> &T,
1036 const std::vector<AD2Type> &W) const
1037{
1038 return EvalW_AD_impl<AD2Type>(T,W);
1039}
1040
1042{
1043 // mu_7 = |J-J^{-t}|^2 = |J|^2 + |J^{-1}|^2 - 4
1044 ie.SetJacobian(Jpt.GetData());
1045 return ie.Get_I1()*(1. + 1./ie.Get_I2()) - 4.0;
1046}
1047
1049{
1050 // P = d(I1*(1 + 1/I2)) = (1 + 1/I2) dI1 - I1/I2^2 dI2
1051 ie.SetJacobian(Jpt.GetData());
1052 const real_t I2 = ie.Get_I2();
1053 Add(1. + 1./I2, ie.Get_dI1(), -ie.Get_I1()/(I2*I2), ie.Get_dI2(), P);
1054}
1055
1057 const DenseMatrix &DS,
1058 const real_t weight,
1059 DenseMatrix &A) const
1060{
1061 // P = d(I1*(1 + 1/I2))
1062 // = (1 + 1/I2) dI1 - I1/I2^2 dI2
1063 //
1064 // dP = (-1/I2^2) (dI1 x dI2) + (1 + 1/I2) ddI1 -
1065 // (dI2 x d(I1/I2^2)) - I1/I2^2 ddI2
1066 // = (-1/I2^2) (dI1 x dI2) + (1 + 1/I2) ddI1 +
1067 // (-1/I2^2) (dI2 x [dI1 - 2 I1/I2 dI2]) - I1/I2^2 ddI2
1068 // = (-1/I2^2) (dI1 x dI2 + dI2 x dI1) + (1 + 1/I2) ddI1 +
1069 // (2 I1/I2^3) (dI2 x dI2) - I1/I2^2 ddI2
1070 ie.SetJacobian(Jpt.GetData());
1072 const real_t c1 = 1./ie.Get_I2();
1073 const real_t c2 = weight*c1*c1;
1074 const real_t c3 = ie.Get_I1()*c2;
1075 ie.Assemble_ddI1(weight*(1. + c1), A.GetData());
1076 ie.Assemble_ddI2(-c3, A.GetData());
1077 ie.Assemble_TProd(-c2, ie.Get_dI1(), ie.Get_dI2(), A.GetData());
1078 ie.Assemble_TProd(2*c1*c3, ie.Get_dI2(), A.GetData());
1079}
1080
1082{
1083 // mu_9 = det(J)*|J-J^{-t}|^2 = I1b * (I2b^2 + 1) - 4 * I2b
1084 // = (I1 - 4)*I2b + I1b
1085 ie.SetJacobian(Jpt.GetData());
1086 return (ie.Get_I1() - 4.0)*ie.Get_I2b() + ie.Get_I1b();
1087}
1088
1090{
1091 // mu_9 = (I1 - 4)*I2b + I1b
1092 // P = (I1 - 4)*dI2b + I2b*dI1 + dI1b
1093 ie.SetJacobian(Jpt.GetData());
1094 Add(ie.Get_I1() - 4.0, ie.Get_dI2b(), ie.Get_I2b(), ie.Get_dI1(), P);
1095 P += ie.Get_dI1b();
1096}
1097
1099 const DenseMatrix &DS,
1100 const real_t weight,
1101 DenseMatrix &A) const
1102{
1103 // P = (I1 - 4)*dI2b + I2b*dI1 + dI1b
1104 // dP = dI2b x dI1 + (I1-4)*ddI2b + dI1 x dI2b + I2b*ddI1 + ddI1b
1105 // = (dI1 x dI2b + dI2b x dI1) + (I1-4)*ddI2b + I2b*ddI1 + ddI1b
1106 ie.SetJacobian(Jpt.GetData());
1109 ie.Assemble_ddI2b(weight*(ie.Get_I1()-4.0), A.GetData());
1112}
1113
1115{
1116 // mu_14 = |J - I|^2.
1117 DenseMatrix Mat(Jpt);
1118 Mat(0,0) -= 1.0;
1119 Mat(1,1) -= 1.0;
1120 return Mat.FNorm2();
1121}
1122
1124{
1125 // mu_14 = |J - I|^2 = I1[J-I].
1126 DenseMatrix Mat(Jpt);
1127 Mat(0,0) -= 1.0;
1128 Mat(1,1) -= 1.0;
1129
1130 ie.SetJacobian(Mat.GetData());
1131 return ie.Get_I1();
1132}
1133
1135{
1136 // P = dI1[J-I] d/dJ[J-I] = dI1[J-I].
1137 DenseMatrix JptMinusId = Jpt;
1138 for (int i = 0; i < Jpt.Size(); i++)
1139 {
1140 JptMinusId(i, i) -= 1.0;
1141 }
1142 ie.SetJacobian(JptMinusId.GetData());
1143 P = ie.Get_dI1();
1144}
1145
1147 const DenseMatrix &DS,
1148 const real_t weight,
1149 DenseMatrix &A) const
1150{
1151 // dP = ddI1[J-I].
1152 DenseMatrix JptMinusId = Jpt;
1153 for (int i = 0; i < Jpt.Size(); i++)
1154 {
1155 JptMinusId(i, i) -= 1.0;
1156 }
1157 ie.SetJacobian(JptMinusId.GetData());
1160}
1161
1162template <typename type>
1163type TMOP_Metric_014::EvalW_AD_impl(const std::vector<type> &T,
1164 const std::vector<type> &W) const
1165{
1166 return mu14_ad(T, W);
1167}
1168
1169AD1Type TMOP_Metric_014::EvalW_AD1(const std::vector<AD1Type> &T,
1170 const std::vector<AD1Type> &W) const
1171{
1172 return EvalW_AD_impl<AD1Type>(T,W);
1173}
1174
1175AD2Type TMOP_Metric_014::EvalW_AD2(const std::vector<AD2Type> &T,
1176 const std::vector<AD2Type> &W) const
1177{
1178 return EvalW_AD_impl<AD2Type>(T,W);
1179}
1180
1182{
1183 // mu_22 = (0.5*|J|^2 - det(J)) / (det(J) - tau0)
1184 // = (0.5*I1 - I2b) / (I2b - tau0)
1185 ie.SetJacobian(Jpt.GetData());
1186 const real_t I2b = ie.Get_I2b();
1187
1188 real_t d = I2b - min_detT;
1189 if (d < 0.0 && min_detT == 0.0)
1190 {
1191 // The mesh has been untangled, but it's still possible to get negative
1192 // detJ in FD calculations, as they move the nodes around with some small
1193 // increments and can produce negative determinants. Thus we put a small
1194 // value in the denominator. Note that here I2b < 0.
1195 d = - I2b * 0.1;
1196 }
1197
1198 return (0.5*ie.Get_I1() - I2b) / d;
1199}
1200
1202{
1203 // mu_22 = (0.5*I1 - I2b) / (I2b - tau0)
1204 // P = 1/(I2b - tau0)*(0.5*dI1 - dI2b) - (0.5*I1 - I2b)/(I2b - tau0)^2*dI2b
1205 // = 0.5/(I2b - tau0)*dI1 + (tau0 - 0.5*I1)/(I2b - tau0)^2*dI2b
1206 ie.SetJacobian(Jpt.GetData());
1207 const real_t c1 = 1.0/(ie.Get_I2b() - min_detT);
1208 Add(c1/2, ie.Get_dI1(), (min_detT - ie.Get_I1()/2)*c1*c1, ie.Get_dI2b(), P);
1209}
1210
1212 const DenseMatrix &DS,
1213 const real_t weight,
1214 DenseMatrix &A) const
1215{
1216 // P = 0.5/(I2b - tau0)*dI1 + (tau0 - 0.5*I1)/(I2b - tau0)^2*dI2b
1217 // dP = -0.5/(I2b - tau0)^2*(dI1 x dI2b) + 0.5/(I2b - tau0)*ddI1
1218 // + (dI2b x dz) + z*ddI2b
1219 //
1220 // z = (tau0 - 0.5*I1)/(I2b - tau0)^2
1221 // dz = -0.5/(I2b - tau0)^2*dI1 - 2*(tau0 - 0.5*I1)/(I2b - tau0)^3*dI2b
1222 //
1223 // dP = -0.5/(I2b - tau0)^2*(dI1 x dI2b + dI2b x dI1)
1224 // -2*z/(I2b - tau0)*(dI2b x dI2b)
1225 // +0.5/(I2b - tau0)*ddI1 + z*ddI2b
1226 ie.SetJacobian(Jpt.GetData());
1228 const real_t c1 = 1.0/(ie.Get_I2b() - min_detT);
1229 const real_t c2 = weight*c1/2;
1230 const real_t c3 = c1*c2;
1231 const real_t c4 = (2*min_detT - ie.Get_I1())*c3; // weight*z
1232 ie.Assemble_TProd(-c3, ie.Get_dI1(), ie.Get_dI2b(), A.GetData());
1233 ie.Assemble_TProd(-2*c1*c4, ie.Get_dI2b(), A.GetData());
1234 ie.Assemble_ddI1(c2, A.GetData());
1235 ie.Assemble_ddI2b(c4, A.GetData());
1236}
1237
1239{
1240 // mu_50 = 0.5 |J^t J|^2 / det(J)^2 - 1.
1241 DenseMatrix JtJ(2);
1242 MultAAt(Jpt, JtJ);
1243 JtJ.Transpose();
1244 real_t det = Jpt.Det();
1245
1246 return 0.5 * JtJ.FNorm2()/(det*det) - 1.0;
1247}
1248
1250{
1251 // mu_50 = 0.5*|J^t J|^2/det(J)^2 - 1
1252 // = 0.5*(l1^4 + l2^4)/(l1*l2)^2 - 1
1253 // = 0.5*((l1/l2)^2 + (l2/l1)^2) - 1 = 0.5*(l1/l2 - l2/l1)^2
1254 // = 0.5*(l1/l2 + l2/l1)^2 - 2 = 0.5*I1b^2 - 2.
1255 ie.SetJacobian(Jpt.GetData());
1256 const real_t I1b = ie.Get_I1b();
1257 return 0.5*I1b*I1b - 2.0;
1258}
1259
1261{
1262 // mu_50 = 0.5*I1b^2 - 2
1263 // P = I1b*dI1b
1264 ie.SetJacobian(Jpt.GetData());
1265 P.Set(ie.Get_I1b(), ie.Get_dI1b());
1266}
1267
1269 const DenseMatrix &DS,
1270 const real_t weight,
1271 DenseMatrix &A) const
1272{
1273 // P = I1b*dI1b
1274 // dP = dI1b x dI1b + I1b*ddI1b
1275 ie.SetJacobian(Jpt.GetData());
1279}
1280
1282{
1283 // mu_55 = (det(J) - 1)^2 = (I2b - 1)^2
1284 ie.SetJacobian(Jpt.GetData());
1285 const real_t c1 = ie.Get_I2b() - 1.0;
1286 return c1*c1;
1287}
1288
1290{
1291 // mu_55 = (I2b - 1)^2
1292 // P = 2*(I2b - 1)*dI2b
1293 ie.SetJacobian(Jpt.GetData());
1294 P.Set(2*(ie.Get_I2b() - 1.0), ie.Get_dI2b());
1295}
1296
1298 const DenseMatrix &DS,
1299 const real_t weight,
1300 DenseMatrix &A) const
1301{
1302 // P = 2*(I2b - 1)*dI2b
1303 // dP = 2*(dI2b x dI2b) + 2*(I2b - 1)*ddI2b
1304 ie.SetJacobian(Jpt.GetData());
1307 ie.Assemble_ddI2b(2*weight*(ie.Get_I2b() - 1.0), A.GetData());
1308}
1309
1310template <typename type>
1311type TMOP_Metric_055::EvalW_AD_impl(const std::vector<type> &T,
1312 const std::vector<type> &W) const
1313{
1314 return mu55_ad(T, W);
1315}
1316
1317AD1Type TMOP_Metric_055::EvalW_AD1(const std::vector<AD1Type> &T,
1318 const std::vector<AD1Type> &W) const
1319{
1320 return EvalW_AD_impl<AD1Type>(T,W);
1321}
1322
1323AD2Type TMOP_Metric_055::EvalW_AD2(const std::vector<AD2Type> &T,
1324 const std::vector<AD2Type> &W) const
1325{
1326 return EvalW_AD_impl<AD2Type>(T,W);
1327}
1328
1330{
1331 // mu_56 = 0.5 (det(J) + 1 / det(J)) - 1.
1332 const real_t d = Jpt.Det();
1333 return 0.5 * (d + 1.0 / d) - 1.0;
1334}
1335
1337{
1338 // mu_56 = 0.5*(I2b + 1/I2b) - 1.
1339 ie.SetJacobian(Jpt.GetData());
1340 const real_t I2b = ie.Get_I2b();
1341 return 0.5*(I2b + 1.0/I2b) - 1.0;
1342}
1343
1345{
1346 // mu_56 = 0.5*(I2b + 1/I2b) - 1.
1347 // P = 0.5*(1 - 1/I2b^2)*dI2b.
1348 ie.SetJacobian(Jpt.GetData());
1349 P.Set(0.5 - 0.5/ie.Get_I2(), ie.Get_dI2b());
1350}
1351
1353 const DenseMatrix &DS,
1354 const real_t weight,
1355 DenseMatrix &A) const
1356{
1357 // P = 0.5*(1 - 1/I2b^2)*dI2b.
1358 // dP = (1/I2b^3)*(dI2b x dI2b) + (0.5 - 0.5/I2)*ddI2b.
1359 ie.SetJacobian(Jpt.GetData());
1362 ie.Get_dI2b(), A.GetData());
1363 ie.Assemble_ddI2b(weight*(0.5 - 0.5/ie.Get_I2()), A.GetData());
1364}
1365
1367{
1368 // mu_58 = |J^t J|^2 / det(J)^2 - 2|J|^2 / det(J) + 2.
1369 DenseMatrix JtJ(2);
1370 MultAAt(Jpt, JtJ);
1371 JtJ.Transpose();
1372 real_t det = Jpt.Det();
1373
1374 return JtJ.FNorm2()/(det*det) - 2*Jpt.FNorm2()/det + 2.0;
1375}
1376
1378{
1379 // mu_58 = I1b*(I1b - 2)
1380 ie.SetJacobian(Jpt.GetData());
1381 const real_t I1b = ie.Get_I1b();
1382 return I1b*(I1b - 2.0);
1383}
1384
1386{
1387 // mu_58 = I1b*(I1b - 2)
1388 // P = (2*I1b - 2)*dI1b
1389 ie.SetJacobian(Jpt.GetData());
1390 P.Set(2*ie.Get_I1b() - 2.0, ie.Get_dI1b());
1391}
1392
1394 const DenseMatrix &DS,
1395 const real_t weight,
1396 DenseMatrix &A) const
1397{
1398 // P = (2*I1b - 2)*dI1b
1399 // dP = 2*(dI1b x dI1b) + (2*I1b - 2)*ddI1b
1400 ie.SetJacobian(Jpt.GetData());
1403 ie.Assemble_ddI1b(weight*(2*ie.Get_I1b() - 2.0), A.GetData());
1404}
1405
1407{
1408 // mu_77 = 0.5 (det(J)^2 + 1 / det(J)^2) - 1.
1409 const real_t d = Jpt.Det();
1410 return 0.5 * (d*d + 1.0/(d*d)) - 1.0;
1411}
1413{
1414 // mu_77 = 0.5 (I2 + 1 / I2) - 1.0.
1415 ie.SetJacobian(Jpt.GetData());
1416 const real_t I2 = ie.Get_I2();
1417 return 0.5*(I2 + 1.0/I2) - 1.0;
1418}
1419
1421{
1422 // mu_77 = 0.5 (I2 + 1 / I2) - 1.0.
1423 // P = 1/2 (1 - 1/I2^2) dI2_dJ.
1424 ie.SetJacobian(Jpt.GetData());
1425 const real_t I2 = ie.Get_I2();
1426 P.Set(0.5 * (1.0 - 1.0 / (I2 * I2)), ie.Get_dI2());
1427}
1428
1430 const DenseMatrix &DS,
1431 const real_t weight,
1432 DenseMatrix &A) const
1433{
1434 ie.SetJacobian(Jpt.GetData());
1436 const real_t I2 = ie.Get_I2(), I2inv_sq = 1.0 / (I2 * I2);
1437 ie.Assemble_ddI2(weight*0.5*(1.0 - I2inv_sq), A.GetData());
1438 ie.Assemble_TProd(weight * I2inv_sq / I2, ie.Get_dI2(), A.GetData());
1439}
1440
1441// mu_85 = |T-T'|^2, where T'= |T|*I/sqrt(2)
1443{
1444 int matsize = Jpt.TotalSize();
1445 std::vector<AD1Type> T(matsize), W(matsize);
1446 for (int i=0; i<matsize; i++) { T[i] = AD1Type{Jpt.GetData()[i], 0.0}; }
1447 return mu85_ad(T, W).value;
1448}
1449
1451{
1452 ADGrad(mu85_ad<AD1Type>, P, Jpt);
1453 return;
1454}
1455
1457 const DenseMatrix &DS,
1458 const real_t weight,
1459 DenseMatrix &A) const
1460{
1461 const int dim = Jpt.Height();
1462 DenseTensor H(dim, dim, dim*dim); H = 0.0;
1463 ADHessian(mu85_ad<AD2Type>, H, Jpt);
1464 this->DefaultAssembleH(H,DS,weight,A);
1465}
1466
1467// mu_98 = 1/(tau)|T-I|^2
1469{
1470 int matsize = Jpt.TotalSize();
1471 std::vector<AD1Type> T(matsize), W(matsize);
1472 for (int i=0; i<matsize; i++) { T[i] = AD1Type{Jpt.GetData()[i], 0.0}; }
1473 return mu98_ad(T, W).value;
1474}
1475
1477{
1478 ADGrad(mu98_ad<AD1Type>, P, Jpt);
1479 return;
1480}
1481
1483 const DenseMatrix &DS,
1484 const real_t weight,
1485 DenseMatrix &A) const
1486{
1487 const int dim = Jpt.Height();
1488 DenseTensor H(dim, dim, dim*dim); H = 0.0;
1489 ADHessian(mu98_ad<AD2Type>, H, Jpt);
1490 this->DefaultAssembleH(H,DS,weight,A);
1491}
1492
1494{
1495 // mu_211 = (det(J) - 1)^2 - det(J) + (det(J)^2 + eps)^{1/2}
1496 // = (I2b - 1)^2 - I2b + sqrt(I2b^2 + eps)
1497 ie.SetJacobian(Jpt.GetData());
1498 const real_t I2b = ie.Get_I2b();
1499 return (I2b - 1.0)*(I2b - 1.0) - I2b + std::sqrt(I2b*I2b + eps);
1500}
1501
1503{
1504 MFEM_ABORT("Metric not implemented yet. Use metric mu_55 instead.");
1505}
1506
1508 const DenseMatrix &DS,
1509 const real_t weight,
1510 DenseMatrix &A) const
1511{
1512 MFEM_ABORT("Metric not implemented yet. Use metric mu_55 instead.");
1513}
1514
1516{
1517 // mu_252 = 0.5*(det(J) - 1)^2 / (det(J) - tau0).
1518 ie.SetJacobian(Jpt.GetData());
1519 const real_t I2b = ie.Get_I2b();
1520 return 0.5*(I2b - 1.0)*(I2b - 1.0)/(I2b - tau0);
1521}
1522
1524{
1525 // mu_252 = 0.5*(det(J) - 1)^2 / (det(J) - tau0)
1526 // P = (c - 0.5*c*c) * dI2b
1527 //
1528 // c = (I2b - 1)/(I2b - tau0), see TMOP_Metric_352 for details
1529 ie.SetJacobian(Jpt.GetData());
1530 const real_t I2b = ie.Get_I2b();
1531 const real_t c = (I2b - 1.0)/(I2b - tau0);
1532 P.Set(c - 0.5*c*c, ie.Get_dI2b());
1533}
1534
1536 const DenseMatrix &DS,
1537 const real_t weight,
1538 DenseMatrix &A) const
1539{
1540 // c = (I2b - 1)/(I2b - tau0), see TMOP_Metric_352 for details
1541 //
1542 // P = (c - 0.5*c*c) * dI2b
1543 // dP = (1 - c)^2/(I2b - tau0)*(dI2b x dI2b) + (c - 0.5*c*c)*ddI2b
1544 ie.SetJacobian(Jpt.GetData());
1546 const real_t I2b = ie.Get_I2b();
1547 const real_t c0 = 1.0/(I2b - tau0);
1548 const real_t c = c0*(I2b - 1.0);
1549 ie.Assemble_TProd(weight*c0*(1.0 - c)*(1.0 - c), ie.Get_dI2b(), A.GetData());
1550 ie.Assemble_ddI2b(weight*(c - 0.5*c*c), A.GetData());
1551}
1552
1554{
1555 // mu_301 = 1/3 |J| |J^-1| - 1.
1556 ie.SetJacobian(Jpt.GetData());
1557 DenseMatrix inv(3);
1558 CalcInverse(Jpt, inv);
1559 return Jpt.FNorm() * inv.FNorm() / 3.0 - 1.0;
1560}
1561
1563{
1564 // mu_301 = 1/3 sqrt(I1b * I2b) - 1
1565 ie.SetJacobian(Jpt.GetData());
1566 return std::sqrt(ie.Get_I1b()*ie.Get_I2b())/3. - 1.;
1567}
1568
1570{
1571 // W = (1/3)*sqrt(I1b*I2b) - 1
1572 // dW = (1/6)/sqrt(I1b*I2b)*[I2b*dI1b + I1b*dI2b]
1573 ie.SetJacobian(Jpt.GetData());
1574 const real_t a = 1./(6.*std::sqrt(ie.Get_I1b()*ie.Get_I2b()));
1575 Add(a*ie.Get_I2b(), ie.Get_dI1b(), a*ie.Get_I1b(), ie.Get_dI2b(), P);
1576}
1577
1579 const DenseMatrix &DS,
1580 const real_t weight,
1581 DenseMatrix &A) const
1582{
1583 // dW = (1/6)/sqrt(I1b*I2b)*[I2b*dI1b + I1b*dI2b]
1584 // dW = (1/6)*[z2*dI1b + z1*dI2b], z1 = sqrt(I1b/I2b), z2 = sqrt(I2b/I1b)
1585 // ddW = (1/6)*[dI1b x dz2 + z2*ddI1b + dI2b x dz1 + z1*ddI2b]
1586 //
1587 // dz1 = (1/2)*sqrt(I2b/I1b) [ (1/I2b)*dI1b - (I1b/(I2b*I2b))*dI2b ]
1588 // = (1/2)/sqrt(I1b*I2b) [ dI1b - (I1b/I2b)*dI2b ]
1589 // dz2 = (1/2)/sqrt(I1b*I2b) [ dI2b - (I2b/I1b)*dI1b ]
1590 //
1591 // dI1b x dz2 + dI2b x dz1 =
1592 // (1/2)/sqrt(I1b*I2b) dI1b x [ dI2b - (I2b/I1b)*dI1b ] +
1593 // (1/2)/sqrt(I1b*I2b) dI2b x [ dI1b - (I1b/I2b)*dI2b ] =
1594 // (1/2)/sqrt(I1b*I2b) [sqrt(I1b/I2b)*dI2b - sqrt(I2b/I1b)*dI1b] x
1595 // [sqrt(I2b/I1b)*dI1b - sqrt(I1b/I2b)*dI2b] =
1596 // (1/2)*(I1b*I2b)^{-3/2} (I1b*dI2b - I2b*dI1b) x (I2b*dI1b - I1b*dI2b)
1597 // and the last two parentheses are the same up to a sign.
1598 //
1599 // z1 = I1b/sqrt(I1b*I2b), z2 = I2b/sqrt(I1b*I2b)
1600
1601 ie.SetJacobian(Jpt.GetData());
1603 real_t X_data[9];
1604 DenseMatrix X(X_data, 3, 3);
1605 Add(- ie.Get_I2b(), ie.Get_dI1b(), ie.Get_I1b(), ie.Get_dI2b(), X);
1606 const real_t I1b_I2b = ie.Get_I1b()*ie.Get_I2b();
1607 const real_t a = weight/(6*std::sqrt(I1b_I2b));
1610 ie.Assemble_TProd(-a/(2*I1b_I2b), X_data, A.GetData());
1611}
1612
1614{
1615 // mu_301 = |J|^2 |J^{-1}|^2 / 9 - 1.
1616 ie.SetJacobian(Jpt.GetData());
1617 DenseMatrix inv(3);
1618 CalcInverse(Jpt, inv);
1619 return Jpt.FNorm2() * inv.FNorm2() / 9.0 - 1.0;
1620}
1621
1623{
1624 // mu_2 = |J|^2 |J^{-1}|^2 / 9 - 1
1625 // = (l1^2 + l2^2 + l3^3)*(l1^{-2} + l2^{-2} + l3^{-2}) / 9 - 1
1626 // = I1*(l2^2*l3^2 + l1^2*l3^2 + l1^2*l2^2)/l1^2/l2^2/l3^2/9 - 1
1627 // = I1*I2/det(J)^2/9 - 1 = I1b*I2b/9-1
1628 ie.SetJacobian(Jpt.GetData());
1629 return ie.Get_I1b()*ie.Get_I2b()/9. - 1.;
1630}
1631
1633{
1634 // mu_2 = I1b*I2b/9-1
1635 // P = (I1b/9)*dI2b + (I2b/9)*dI1b
1636 ie.SetJacobian(Jpt.GetData());
1637 Add(ie.Get_I1b()/9, ie.Get_dI2b(), ie.Get_I2b()/9, ie.Get_dI1b(), P);
1638}
1639
1641 const DenseMatrix &DS,
1642 const real_t weight,
1643 DenseMatrix &A) const
1644{
1645 // P = (I1b/9)*dI2b + (I2b/9)*dI1b
1646 // dP = (dI2b x dI1b)/9 + (I1b/9)*ddI2b + (dI1b x dI2b)/9 + (I2b/9)*ddI1b
1647 // = (dI2b x dI1b + dI1b x dI2b)/9 + (I1b/9)*ddI2b + (I2b/9)*ddI1b
1648 ie.SetJacobian(Jpt.GetData());
1650 const real_t c1 = weight/9;
1652 ie.Assemble_ddI2b(c1*ie.Get_I1b(), A.GetData());
1653 ie.Assemble_ddI1b(c1*ie.Get_I2b(), A.GetData());
1654}
1655
1657{
1658 // mu_303 = |J|^2 / 3 / det(J)^(2/3) - 1.
1659 ie.SetJacobian(Jpt.GetData());
1660 return Jpt.FNorm2() / 3.0 / pow(Jpt.Det(), 2.0 / 3.0) - 1.0;
1661}
1662
1664{
1665 // mu_303 = |J|^2 / 3 / det(J)^(2/3) - 1 = I1b/3 - 1.
1666 ie.SetJacobian(Jpt.GetData());
1667 return ie.Get_I1b()/3.0 - 1.0;
1668}
1669
1671{
1672 // mu_304 = I1b/3 - 1.
1673 // P = dI1b/3.
1674 ie.SetJacobian(Jpt.GetData());
1675 P.Set(1./3., ie.Get_dI1b());
1676}
1677
1679 const DenseMatrix &DS,
1680 const real_t weight,
1681 DenseMatrix &A) const
1682{
1683 // P = dI1b/3.
1684 // dP = ddI1b/3.
1685 ie.SetJacobian(Jpt.GetData());
1688}
1689
1691{
1692 // mu_304 = |J|^3 / 3^(3/2) / det(J) - 1
1693 const real_t fnorm = Jpt.FNorm();
1694 return fnorm * fnorm * fnorm / pow(3.0, 1.5) / Jpt.Det() - 1.0;
1695}
1696
1698{
1699 // mu_304 = (I1b/3)^3/2 - 1.
1700 ie.SetJacobian(Jpt.GetData());
1701 return pow(ie.Get_I1b()/3.0, 1.5) - 1.0;
1702}
1703
1705{
1706 // mu_304 = (I1b/3)^3/2 - 1.
1707 // P = 3/2 * (I1b/3)^1/2 * dI1b / 3 = 1/2 * (I1b/3)^1/2 * dI1b.
1708 ie.SetJacobian(Jpt.GetData());
1709 P.Set(0.5 * sqrt(ie.Get_I1b()/3.0), ie.Get_dI1b());
1710}
1711
1713 const real_t weight, DenseMatrix &A) const
1714{
1715 // P = 1/2 * (I1b/3)^1/2 * dI1b.
1716 // dP = 1/12 * (I1b/3)^(-1/2) * (dI1b x dI1b) + 1/2 * (I1b/3)^1/2 * ddI1b.
1717 ie.SetJacobian(Jpt.GetData());
1719 ie.Assemble_TProd(weight / 12.0 / sqrt(ie.Get_I1b()/3.0),
1720 ie.Get_dI1b(), A.GetData());
1721 ie.Assemble_ddI1b(weight / 2.0 * sqrt(ie.Get_I1b()/3.0), A.GetData());
1722}
1723
1725{
1726 // mu_311 = (det(J) - 1)^2 - det(J) + (det(J)^2 + eps)^{1/2}
1727 // = (I3b - 1)^2 - I3b + sqrt(I3b^2 + eps)
1728 ie.SetJacobian(Jpt.GetData());
1729 const real_t I3b = ie.Get_I3b();
1730 return (I3b - 1.0)*(I3b - 1.0) - I3b + std::sqrt(I3b*I3b + eps);
1731}
1732
1734{
1735 ie.SetJacobian(Jpt.GetData());
1736 const real_t I3b = ie.Get_I3b();
1737 const real_t c = 2*I3b-3+(I3b)/(std::pow((I3b*I3b+eps),0.5));
1738 P.Set(c, ie.Get_dI3b());
1739}
1740
1742 const DenseMatrix &DS,
1743 const real_t weight,
1744 DenseMatrix &A) const
1745{
1746 ie.SetJacobian(Jpt.GetData());
1748 const real_t I3b = ie.Get_I3b();
1749 const real_t c0 = I3b*I3b+eps;
1750 const real_t c1 = 2 + 1/(pow(c0,0.5)) - I3b*I3b/(pow(c0,1.5));
1751 const real_t c2 = 2*I3b - 3 + I3b/(pow(c0,0.5));
1754}
1755
1757{
1758 ie.SetJacobian(Jpt.GetData());
1759
1760 const real_t I3b = ie.Get_I3b();
1761 real_t d = I3b - min_detT;
1762 if (d < 0.0 && min_detT == 0.0)
1763 {
1764 // The mesh has been untangled, but it's still possible to get negative
1765 // detJ in FD calculations, as they move the nodes around with some small
1766 // increments and can produce negative determinants. Thus we put a small
1767 // value in the denominator. Note that here I3b < 0.
1768 d = - I3b * 0.1;
1769 }
1770
1771 const real_t c = std::pow(d, -2.0/3.0);
1772
1773 return ie.Get_I1() * c / 3.0;
1774}
1775
1777{
1778 MFEM_ABORT("Metric not implemented yet.");
1779}
1780
1782 const DenseMatrix &DS,
1783 const real_t weight,
1784 DenseMatrix &A) const
1785{
1786 MFEM_ABORT("Metric not implemented yet.");
1787}
1788
1790{
1791 // mu_315 = mu_15_3D = (det(J) - 1)^2
1792 ie.SetJacobian(Jpt.GetData());
1793 const real_t c1 = ie.Get_I3b() - 1.0;
1794 return c1*c1;
1795}
1796
1798{
1799 // mu_315 = (I3b - 1)^2
1800 // P = 2*(I3b - 1)*dI3b
1801 ie.SetJacobian(Jpt.GetData());
1802 P.Set(2*(ie.Get_I3b() - 1.0), ie.Get_dI3b());
1803}
1804
1806 const DenseMatrix &DS,
1807 const real_t weight,
1808 DenseMatrix &A) const
1809{
1810 // P = 2*(I3b - 1)*dI3b
1811 // dP = 2*(dI3b x dI3b) + 2*(I3b - 1)*ddI3b
1812 ie.SetJacobian(Jpt.GetData());
1815 ie.Assemble_ddI3b(2*weight*(ie.Get_I3b() - 1.0), A.GetData());
1816}
1817
1819{
1820 // mu_316 = 0.5 (det(J) + 1/det(J)) - 1.
1821 return 0.5 * (Jpt.Det() + 1.0 / Jpt.Det()) - 1.0;
1822}
1823
1825{
1826 // mu_316 = mu_16_3D = 0.5*(I3b + 1/I3b) - 1
1827 ie.SetJacobian(Jpt.GetData());
1828 const real_t I3b = ie.Get_I3b();
1829 return 0.5*(I3b + 1.0/I3b) - 1.0;
1830}
1831
1833{
1834 // mu_316 = mu_16_3D = 0.5*(I3b + 1/I3b) - 1
1835 // P = 0.5*(1 - 1/I3b^2)*dI3b = (0.5 - 0.5/I3)*dI3b
1836 ie.SetJacobian(Jpt.GetData());
1837 P.Set(0.5 - 0.5/ie.Get_I3(), ie.Get_dI3b());
1838}
1839
1841 const DenseMatrix &DS,
1842 const real_t weight,
1843 DenseMatrix &A) const
1844{
1845 // P = 0.5*(1 - 1/I3b^2)*dI3b = (0.5 - 0.5/I3)*dI3b
1846 // dP = (1/I3b^3)*(dI3b x dI3b) + (0.5 - 0.5/I3)*ddI3b
1847 ie.SetJacobian(Jpt.GetData());
1850 ie.Get_dI3b(), A.GetData());
1851 ie.Assemble_ddI3b(weight*(0.5 - 0.5/ie.Get_I3()), A.GetData());
1852}
1853
1855{
1856 // mu_318 = 0.5 (det(J)^2 + 1/det(J)^2) - 1.
1857 real_t d = Jpt.Det();
1858 return 0.5 * (d*d + 1.0 / (d*d)) - 1.0;
1859}
1860
1862{
1863 // mu_318 = mu_77_3D = 0.5 * (I3 + 1/I3) - 1.
1864 ie.SetJacobian(Jpt.GetData());
1865 const real_t I3 = ie.Get_I3();
1866 return 0.5*(I3 + 1.0/I3) - 1.0;
1867}
1868
1870{
1871 // mu_318 = mu_77_3D = 0.5*(I3 + 1/I3) - 1.
1872 // P = 0.5*(1 - 1/I3^2)*dI3 = (0.5 - 0.5/I3^2)*dI3.
1873 ie.SetJacobian(Jpt.GetData());
1874 P.Set(0.5 - 0.5/(ie.Get_I3()*ie.Get_I3()), ie.Get_dI3());
1875}
1876
1878 const DenseMatrix &DS,
1879 const real_t weight,
1880 DenseMatrix &A) const
1881{
1882 // P = (0.5 - 0.5/I3^2)*dI3.
1883 // dP = (1/I3^3)*(dI3 x dI3) +(0.5 - 0.5/I3^2)*ddI3
1884 ie.SetJacobian(Jpt.GetData());
1886 const real_t i3 = ie.Get_I3();
1887 ie.Assemble_TProd(weight/(i3 * i3 * i3), ie.Get_dI3(), A.GetData());
1888 ie.Assemble_ddI3(weight*(0.5 - 0.5 / (i3 * i3)), A.GetData());
1889}
1890
1892{
1893 // mu_321 = |J - J^-t|^2.
1894 ie.SetJacobian(Jpt.GetData());
1895 DenseMatrix invt(3);
1896 CalcInverseTranspose(Jpt, invt);
1897 invt.Add(-1.0, Jpt);
1898 return invt.FNorm2();
1899}
1900
1902{
1903 // mu_321 = mu_21_3D = |J - J^{-t}|^2
1904 // = |J|^2 + |J^{-1}|^2 - 6
1905 // = |J|^2 + (l1^{-2} + l2^{-2} + l3^{-2}) - 6
1906 // = |J|^2 + (l2^2*l3^2 + l1^2*l3^2 + l1^2*l2^2)/det(J)^2 - 6
1907 // = I1 + I2/I3b^2 - 6 = I1 + I2/I3 - 6
1908 ie.SetJacobian(Jpt.GetData());
1909 return ie.Get_I1() + ie.Get_I2()/ie.Get_I3() - 6.0;
1910}
1911
1913{
1914 // mu_321 = I1 + I2/I3b^2 - 6 = I1 + I2/I3 - 6
1915 // P = dI1 + (1/I3)*dI2 - (2*I2/I3b^3)*dI3b
1916 ie.SetJacobian(Jpt.GetData());
1917 const real_t I3 = ie.Get_I3();
1918 Add(1.0/I3, ie.Get_dI2(),
1919 -2*ie.Get_I2()/(I3*ie.Get_I3b()), ie.Get_dI3b(), P);
1920 P += ie.Get_dI1();
1921}
1922
1924 const DenseMatrix &DS,
1925 const real_t weight,
1926 DenseMatrix &A) const
1927{
1928 // P = dI1 + (1/I3)*dI2 - (2*I2/I3b^3)*dI3b
1929 // dP = ddI1 + (-2/I3b^3)*(dI2 x dI3b) + (1/I3)*ddI2 + (dI3b x dz) + z*ddI3b
1930 //
1931 // z = -2*I2/I3b^3
1932 // dz = (-2/I3b^3)*dI2 + (2*I2)*(3/I3b^4)*dI3b
1933 //
1934 // dP = ddI1 + (-2/I3b^3)*(dI2 x dI3b + dI3b x dI2) + (1/I3)*ddI2
1935 // + (6*I2/I3b^4)*(dI3b x dI3b) + (-2*I2/I3b^3)*ddI3b
1936 ie.SetJacobian(Jpt.GetData());
1938 const real_t c0 = 1.0/ie.Get_I3b();
1939 const real_t c1 = weight*c0*c0;
1940 const real_t c2 = -2*c0*c1;
1941 const real_t c3 = c2*ie.Get_I2();
1943 ie.Assemble_ddI2(c1, A.GetData());
1944 ie.Assemble_ddI3b(c3, A.GetData());
1945 ie.Assemble_TProd(c2, ie.Get_dI2(), ie.Get_dI3b(), A.GetData());
1946 ie.Assemble_TProd(-3*c0*c3, ie.Get_dI3b(), A.GetData());
1947}
1948
1950{
1951 // mu_322 = 1 / (6 det(J)) |J - adj(J)^t|^2
1952 DenseMatrix adj_J_t(3);
1953 CalcAdjugateTranspose(Jpt, adj_J_t);
1954 adj_J_t *= -1.0;
1955 adj_J_t.Add(1.0, Jpt);
1956 return 1.0 / 6.0 / Jpt.Det() * adj_J_t.FNorm2();
1957}
1958
1960{
1961 // mu_322 = 1 / (6 det(J)) |J - adj(J)^t|^2
1962 // = 1 / (6 det(J)) |J|^2 + 1/6 det(J) |J^{-1}|^2 - 1
1963 // = I1b / (I3b^-1/3) / 6 + I2b (I3b^1/3) / 6 - 1
1964 ie.SetJacobian(Jpt.GetData());
1965
1966 return ie.Get_I1b() / pow(ie.Get_I3b(), 1.0/3.0) / 6.0 +
1967 ie.Get_I2b() * pow(ie.Get_I3b(), 1.0/3.0) / 6.0 - 1.0;
1968}
1969
1971{
1972 // mu_322 = I1b (I3b^-1/3) / 6 + I2b (I3b^1/3) / 6 - 1
1973 // P = 1/6 (I3b^-1/3) dI1b - 1/18 I1b (I3b^-4/3) dI3b
1974 // + 1/6 (I3b^1/3) dI2b + 1/18 I2b (I3b^-2/3) dI3b
1975 ie.SetJacobian(Jpt.GetData());
1976 P.Set(1.0/6.0 * pow(ie.Get_I3b(), -1.0/3.0),
1977 ie.Get_dI1b());
1978 P.Add(-1.0/18.0 * ie.Get_I1b() * pow(ie.Get_I3b(), -4.0/3.0),
1979 ie.Get_dI3b());
1980 P.Add(1.0/6.0 * pow(ie.Get_I3b(), 1.0/3.0),
1981 ie.Get_dI2b());
1982 P.Add(1.0/18.0 * ie.Get_I2b() * pow(ie.Get_I3b(), -2.0/3.0),
1983 ie.Get_dI3b());
1984}
1985
1987 const real_t weight, DenseMatrix &A) const
1988{
1989 // P = 1/6 (I3b^-1/3) dI1b - 1/18 I1b (I3b^-4/3) dI3b
1990 // + 1/6 (I3b^1/3) dI2b + 1/18 I2b (I3b^-2/3) dI3b
1991 // dP = 1/6 (I3b^-1/3) ddI1b - 1/18 (I3b^-4/3) (dI1b x dI3b)
1992 // - 1/18 I1b (I3b^-4/3) ddI3b
1993 // - 1/18 (I3b^-4/3) (dI3b x dI1b)
1994 // + 2/27 I1b (I3b^-7/3) (dI3b x dI3b)
1995 // + 1/6 (I3b^1/3) ddI2b + 1/18 (I3b^-2/3) (dI2b x dI3b)
1996 // + 1/18 I2b (I3b^-2/3) ddI3b
1997 // + 1/18 (I3b^-2/3) (dI3b x dI2b)
1998 // - 1/27 I2b (I3b^-5/3) (dI3b x dI3b)
1999 ie.SetJacobian(Jpt.GetData());
2001 const real_t p13 = weight * pow(ie.Get_I3b(), 1.0/3.0),
2002 m13 = weight * pow(ie.Get_I3b(), -1.0/3.0),
2003 m23 = weight * pow(ie.Get_I3b(), -2.0/3.0),
2004 m43 = weight * pow(ie.Get_I3b(), -4.0/3.0),
2005 m53 = weight * pow(ie.Get_I3b(), -5.0/3.0),
2006 m73 = weight * pow(ie.Get_I3b(), -7.0/3.0);
2007 ie.Assemble_ddI1b(1.0/6.0 * m13, A.GetData());
2008 // Combines - 1/18 (I3b^-4/3) (dI1b x dI3b) - 1/18 (I3b^-4/3) (dI3b x dI1b).
2009 ie.Assemble_TProd(-1.0/18.0 * m43,
2010 ie.Get_dI1b(), ie.Get_dI3b(), A.GetData());
2011 ie.Assemble_ddI3b(-1.0/18.0 * ie.Get_I1b() * m43, A.GetData());
2012 ie.Assemble_TProd(2.0/27.0 * ie.Get_I1b() * m73,
2013 ie.Get_dI3b(), A.GetData());
2014 ie.Assemble_ddI2b(1.0/6.0 * p13, A.GetData());
2015 // Combines + 1/18 (I3b^-2/3) (dI2b x dI3b) + 1/18 (I3b^-2/3) (dI3b x dI2b).
2016 ie.Assemble_TProd(1.0/18.0 * m23,
2017 ie.Get_dI2b(), ie.Get_dI3b(), A.GetData());
2018 ie.Assemble_ddI3b(1.0/18.0 * ie.Get_I2b() * m23, A.GetData());
2019 ie.Assemble_TProd(-1.0/27.0 * ie.Get_I2b() * m53,
2020 ie.Get_dI3b(), A.GetData());
2021}
2022
2024{
2025 // mu_323 = |J|^3 - 3 sqrt(3) ln(det(J)) - 3 sqrt(3).
2026 real_t fnorm = Jpt.FNorm();
2027 return fnorm * fnorm * fnorm - 3.0 * sqrt(3.0) * (log(Jpt.Det()) + 1.0);
2028}
2029
2031{
2032 // mu_323 = I1^3/2 - 3 sqrt(3) ln(I3b) - 3 sqrt(3).
2033 ie.SetJacobian(Jpt.GetData());
2034 return pow(ie.Get_I1(), 1.5) - 3.0 * sqrt(3.0) * (log(ie.Get_I3b()) + 1.0);
2035}
2036
2038{
2039 // mu_323 = I1^3/2 - 3 sqrt(3) ln(I3b) - 3 sqrt(3).
2040 // P = 3/2 (I1^1/2) dI1 - 3 sqrt(3) (I3b^-1) dI3b.
2041 ie.SetJacobian(Jpt.GetData());
2042 P.Set(1.5 * sqrt(ie.Get_I1()), ie.Get_dI1());
2043 P.Add(- 3.0 * sqrt(3.0) / ie.Get_I3b(), ie.Get_dI3b());
2044}
2045
2047 const real_t weight, DenseMatrix &A) const
2048{
2049 // P = 3/2 (I1^1/2) dI1 - 3 sqrt(3) (I3b^-1) dI3b
2050 // dP = 3/2 (I1^1/2) ddI1 + 3/4 (I1^-1/2) (dI1 x dI1)
2051 // - 3 sqrt(3) (I3b^-1) ddI3b + 3 sqrt(3) (I3b^-2) (dI3b x dI3b)
2052 ie.SetJacobian(Jpt.GetData());
2054 ie.Assemble_ddI1(weight * 1.5 * sqrt(ie.Get_I1()), A.GetData());
2055 ie.Assemble_TProd(weight * 0.75 / sqrt(ie.Get_I1()),
2056 ie.Get_dI1(), A.GetData());
2057 ie.Assemble_ddI3b(- weight * 3.0 * sqrt(3.0) / ie.Get_I3b(), A.GetData());
2058 ie.Assemble_TProd(weight * 3.0 * sqrt(3.0) / ie.Get_I3b() / ie.Get_I3b(),
2059 ie.Get_dI3b(), A.GetData());
2060}
2061
2062// mu_342 = 1/(tau^0.5)|T-I|^2
2064{
2065 int matsize = Jpt.TotalSize();
2066 std::vector<AD1Type> T(matsize), W(matsize);
2067 for (int i=0; i<matsize; i++) { T[i] = AD1Type{Jpt.GetData()[i], 0.0}; }
2068 return mu342_ad(T, W).value;
2069}
2070
2072{
2073 ADGrad(mu342_ad<AD1Type>, P, Jpt);
2074 return;
2075}
2076
2078 const DenseMatrix &DS,
2079 const real_t weight,
2080 DenseMatrix &A) const
2081{
2082 const int dim = Jpt.Height();
2083 DenseTensor H(dim, dim, dim*dim); H = 0.0;
2085 this->DefaultAssembleH(H,DS,weight,A);
2086}
2087
2089{
2090 // mu_352 = 0.5*(det(J) - 1)^2 / (det(J) - tau0)
2091 ie.SetJacobian(Jpt.GetData());
2092 const real_t I3b = ie.Get_I3b();
2093 return 0.5*(I3b - 1.0)*(I3b - 1.0)/(I3b - tau0);
2094}
2095
2097{
2098 // mu_352 = 0.5*(det(J) - 1)^2 / (det(J) - tau0)
2099 // P = (I3b - 1)/(I3b - tau0)*dI3b + 0.5*(I3b - 1)^2*(-1/(I3b - tau0)^2)*dI3b
2100 // = [ (I3b - 1)/(I3b - tau0) - 0.5*(I3b - 1)^2/(I3b - tau0)^2 ] * dI3b
2101 // = (c - 0.5*c*c) * dI3b
2102 ie.SetJacobian(Jpt.GetData());
2103 const real_t I3b = ie.Get_I3b();
2104 const real_t c = (I3b - 1.0)/(I3b - tau0);
2105 P.Set(c - 0.5*c*c, ie.Get_dI3b());
2106}
2107
2109 const DenseMatrix &DS,
2110 const real_t weight,
2111 DenseMatrix &A) const
2112{
2113 // c = (I3b - 1)/(I3b - tau0)
2114 //
2115 // P = (c - 0.5*c*c) * dI3b
2116 // dP = (1 - c)*(dI3b x dc) + (c - 0.5*c*c)*ddI3b
2117 //
2118 // dc = 1/(I3b - tau0)*dI3b - (I3b - 1)/(I3b - tau)^2*dI3b =
2119 // = (1 - c)/(I3b - tau0)*dI3b
2120 //
2121 // dP = (1 - c)^2/(I3b - tau0)*(dI3b x dI3b) + (c - 0.5*c*c)*ddI3b
2122 ie.SetJacobian(Jpt.GetData());
2124 const real_t I3b = ie.Get_I3b();
2125 const real_t c0 = 1.0/(I3b - tau0);
2126 const real_t c = c0*(I3b - 1.0);
2127 ie.Assemble_TProd(weight*c0*(1.0 - c)*(1.0 - c), ie.Get_dI3b(), A.GetData());
2128 ie.Assemble_ddI3b(weight*(c - 0.5*c*c), A.GetData());
2129}
2130
2132{
2133 // mu_360 = |J|^3 / 3^(3/2) - det(J)
2134 const real_t fnorm = Jpt.FNorm();
2135 return fnorm * fnorm * fnorm / pow(3.0, 1.5) - Jpt.Det();
2136}
2137
2139{
2140 // mu_360 = (I1/3)^(3/2) - I3b.
2141 ie.SetJacobian(Jpt.GetData());
2142 return pow(ie.Get_I1()/3.0, 1.5) - ie.Get_I3b();
2143}
2144
2146{
2147 // mu_360 = (I1/3)^(3/2) - I3b.
2148 // P = 3/2 * (I1/3)^1/2 * dI1 / 3 - dI3b
2149 // = 1/2 * (I1/3)^1/2 * dI1 - dI3b.
2150 ie.SetJacobian(Jpt.GetData());
2151 Add(0.5 * sqrt(ie.Get_I1()/3.0), ie.Get_dI1(), -1.0, ie.Get_dI3b(), P);
2152}
2153
2155 const real_t weight, DenseMatrix &A) const
2156{
2157 // P = 1/2 * (I1/3)^1/2 * dI1 - dI3b.
2158 // dP = 1/12 * (I1/3)^(-1/2) * (dI1 x dI1) + 1/2 * (I1/3)^1/2 * ddI1 - ddI3b
2159 ie.SetJacobian(Jpt.GetData());
2161 ie.Assemble_TProd(weight / 12.0 / sqrt(ie.Get_I1()/3.0),
2162 ie.Get_dI1(), A.GetData());
2163 ie.Assemble_ddI1(weight / 2.0 * sqrt(ie.Get_I1()/3.0), A.GetData());
2165}
2166
2168{
2169 MFEM_VERIFY(Jtr != NULL,
2170 "Requires a target Jacobian, use SetTargetJacobian().");
2171 int matsize = Jpt.TotalSize();
2172 std::vector<AD1Type> T(matsize), W(matsize);
2173 for (int i=0; i<matsize; i++)
2174 {
2175 T[i] = AD1Type{Jpt.GetData()[i], 0.0};
2176 W[i] = AD1Type{Jtr->GetData()[i], 0.0};
2177 }
2178 return nu11_ad(T, W).value;
2179}
2180
2182{
2183 ADGrad(nu11_ad<AD1Type>, P, Jpt, Jtr);
2184 return;
2185}
2186
2188{
2189 ADGrad(nu11_ad<AD1Type>, PW, Jpt, Jtr, false);
2190 return;
2191}
2192
2194 const DenseMatrix &DS,
2195 const real_t weight,
2196 DenseMatrix &A) const
2197{
2198 const int dim = Jpt.Height();
2199 DenseTensor H(dim, dim, dim*dim); H = 0.0;
2200 ADHessian(nu11_ad<AD2Type>, H, Jpt, Jtr);
2201 this->DefaultAssembleH(H,DS,weight,A);
2202}
2203
2205{
2206 MFEM_VERIFY(Jtr != NULL,
2207 "Requires a target Jacobian, use SetTargetJacobian().");
2208 int matsize = Jpt.TotalSize();
2209 std::vector<AD1Type> T(matsize), W(matsize);
2210 for (int i=0; i<matsize; i++)
2211 {
2212 T[i] = AD1Type{Jpt.GetData()[i], 0.0};
2213 W[i] = AD1Type{Jtr->GetData()[i], 0.0};
2214 }
2215 return nu14_ad(T, W).value;
2216}
2217
2219{
2220 ADGrad(nu14_ad<AD1Type>, P, Jpt, Jtr);
2221 return;
2222}
2223
2225{
2226 ADGrad(nu14_ad<AD1Type>, PW, Jpt, Jtr, false);
2227 return;
2228}
2229
2231 const DenseMatrix &DS,
2232 const real_t weight,
2233 DenseMatrix &A) const
2234{
2235 const int dim = Jpt.Height();
2236 DenseTensor H(dim, dim, dim*dim); H = 0.0;
2237 ADHessian(nu14_ad<AD2Type>, H, Jpt, Jtr);
2238 this->DefaultAssembleH(H,DS,weight,A);
2239}
2240
2242{
2243 MFEM_VERIFY(Jtr != NULL,
2244 "Requires a target Jacobian, use SetTargetJacobian().");
2245 int matsize = Jpt.TotalSize();
2246 std::vector<AD1Type> T(matsize), W(matsize);
2247 for (int i=0; i<matsize; i++)
2248 {
2249 T[i] = AD1Type{Jpt.GetData()[i], 0.0};
2250 W[i] = AD1Type{Jtr->GetData()[i], 0.0};
2251 }
2252 return nu36_ad(T, W).value;
2253}
2254
2256{
2257 ADGrad(nu36_ad<AD1Type>, P, Jpt, Jtr);
2258 return;
2259}
2260
2262{
2263 ADGrad(nu36_ad<AD1Type>, PW, Jpt, Jtr, false);
2264 return;
2265}
2266
2268 const DenseMatrix &DS,
2269 const real_t weight,
2270 DenseMatrix &A) const
2271{
2272 const int dim = Jpt.Height();
2273 DenseTensor H(dim, dim, dim*dim); H = 0.0;
2274 ADHessian(nu36_ad<AD2Type>, H, Jpt, Jtr);
2275 this->DefaultAssembleH(H,DS,weight,A);
2276}
2277
2279{
2280 MFEM_VERIFY(Jtr != NULL,
2281 "Requires a target Jacobian, use SetTargetJacobian().");
2282 int matsize = Jpt.TotalSize();
2283 std::vector<AD1Type> T(matsize), W(matsize);
2284 for (int i=0; i<matsize; i++)
2285 {
2286 T[i] = AD1Type{Jpt.GetData()[i], 0.0};
2287 W[i] = AD1Type{Jtr->GetData()[i], 0.0};
2288 }
2289 return nu50_ad(T, W).value;
2290}
2291
2293{
2294 ADGrad(nu50_ad<AD1Type>, P, Jpt, Jtr);
2295 return;
2296}
2297
2299{
2300 ADGrad(nu50_ad<AD1Type>, PW, Jpt, Jtr, false);
2301 return;
2302}
2303
2305 const DenseMatrix &DS,
2306 const real_t weight,
2307 DenseMatrix &A) const
2308{
2309 const int dim = Jpt.Height();
2310 DenseTensor H(dim, dim, dim*dim); H = 0.0;
2311 ADHessian(nu50_ad<AD2Type>, H, Jpt, Jtr);
2312 this->DefaultAssembleH(H,DS,weight,A);
2313}
2314
2316{
2317 MFEM_VERIFY(Jtr != NULL,
2318 "Requires a target Jacobian, use SetTargetJacobian().");
2319 int matsize = Jpt.TotalSize();
2320 std::vector<AD1Type> T(matsize), W(matsize);
2321 for (int i=0; i<matsize; i++)
2322 {
2323 T[i] = AD1Type{Jpt.GetData()[i], 0.0};
2324 W[i] = AD1Type{Jtr->GetData()[i], 0.0};
2325 }
2326 return nu51_ad(T, W).value;
2327}
2328
2330{
2331 ADGrad(nu51_ad<AD1Type>, P, Jpt, Jtr);
2332 return;
2333}
2334
2336{
2337 ADGrad(nu51_ad<AD1Type>, PW, Jpt, Jtr, false);
2338 return;
2339}
2340
2342 const DenseMatrix &DS,
2343 const real_t weight,
2344 DenseMatrix &A) const
2345{
2346 const int dim = Jpt.Height();
2347 DenseTensor H(dim, dim, dim*dim); H = 0.0;
2348 ADHessian(nu51_ad<AD2Type>, H, Jpt, Jtr);
2349 this->DefaultAssembleH(H,DS,weight,A);
2350}
2351
2353{
2354 MFEM_VERIFY(Jtr != NULL,
2355 "Requires a target Jacobian, use SetTargetJacobian().");
2356 int matsize = Jpt.TotalSize();
2357 std::vector<AD1Type> T(matsize), W(matsize);
2358 for (int i=0; i<matsize; i++)
2359 {
2360 T[i] = AD1Type{Jpt.GetData()[i], 0.0};
2361 W[i] = AD1Type{Jtr->GetData()[i], 0.0};
2362 }
2363 return nu107_ad(T, W).value;
2364}
2365
2367{
2368 ADGrad(nu107_ad<AD1Type>, P, Jpt, Jtr);
2369 return;
2370}
2371
2373{
2374 ADGrad(nu107_ad<AD1Type>, PW, Jpt, Jtr, false);
2375 return;
2376}
2377
2379 const DenseMatrix &DS,
2380 const real_t weight,
2381 DenseMatrix &A) const
2382{
2383 const int dim = Jpt.Height();
2384 DenseTensor H(dim, dim, dim*dim); H = 0.0;
2386 this->DefaultAssembleH(H,DS,weight,A);
2387}
2388
2390{
2391 MFEM_VERIFY(nodes, "Nodes are not given!");
2392 MFEM_ASSERT(avg_volume == 0.0, "The average volume is already computed!");
2393
2394 Mesh *mesh = nodes->FESpace()->GetMesh();
2395 const int NE = mesh->GetNE();
2397 real_t volume = 0.0;
2398
2399 for (int i = 0; i < NE; i++)
2400 {
2401 mesh->GetElementTransformation(i, *nodes, &Tr);
2402 const IntegrationRule &ir =
2403 IntRules.Get(mesh->GetElementBaseGeometry(i), Tr.OrderJ());
2404 for (int j = 0; j < ir.GetNPoints(); j++)
2405 {
2406 const IntegrationPoint &ip = ir.IntPoint(j);
2407 Tr.SetIntPoint(&ip);
2408 volume += ip.weight * Tr.Weight();
2409 }
2410 }
2411
2412 NCMesh *ncmesh = mesh->ncmesh;
2413 if (Parallel() == false)
2414 {
2415 avg_volume = (ncmesh == NULL) ?
2416 volume / NE : volume / ncmesh->GetNumRootElements();
2417
2418 }
2419#ifdef MFEM_USE_MPI
2420 else
2421 {
2422 real_t area_NE[4];
2423 area_NE[0] = volume; area_NE[1] = NE;
2424 MPI_Allreduce(area_NE, area_NE + 2, 2, MPITypeMap<real_t>::mpi_type, MPI_SUM,
2425 comm);
2426 avg_volume = (ncmesh == NULL) ?
2427 area_NE[2] / area_NE[3] : area_NE[2] / ncmesh->GetNumRootElements();
2428 }
2429#endif
2430}
2431
2433 const FiniteElementSpace &fes,
2434 const IntegrationRule &ir,
2435 const Vector &xe,
2436 DenseTensor &Jtr) const
2437{
2438 // Fallback to the 1-element method, ComputeElementTargets()
2439
2440 // When UsesPhysicalCoordinates() == true, we assume 'xe' uses
2441 // ElementDofOrdering::LEXICOGRAPHIC iff 'fe' is a TensorFiniteElement.
2442
2443 const Mesh *mesh = fes.GetMesh();
2444 const int NE = mesh->GetNE();
2445 // Quick return for empty processors:
2446 if (NE == 0) { return; }
2447 const int dim = mesh->Dimension();
2448 MFEM_VERIFY(mesh->GetNumGeometries(dim) <= 1,
2449 "mixed meshes are not supported");
2450 MFEM_VERIFY(!fes.IsVariableOrder(), "variable orders are not supported");
2451 const FiniteElement &fe = *fes.GetTypicalFE();
2452 const int sdim = fes.GetVDim();
2453 const int nvdofs = sdim*fe.GetDof();
2454 MFEM_VERIFY(!UsesPhysicalCoordinates() ||
2455 xe.Size() == NE*nvdofs, "invalid input Vector 'xe'!");
2456 const int NQ = ir.GetNPoints();
2457 const Array<int> *dof_map = nullptr;
2459 {
2460 const TensorBasisElement *tfe =
2461 dynamic_cast<const TensorBasisElement *>(&fe);
2462 if (tfe)
2463 {
2464 dof_map = &tfe->GetDofMap();
2465 if (dof_map->Size() == 0) { dof_map = nullptr; }
2466 }
2467 }
2468
2469 Vector elfun_lex, elfun_nat;
2470 DenseTensor J;
2471 xe.HostRead();
2472 Jtr.HostWrite();
2473 if (UsesPhysicalCoordinates() && dof_map != nullptr)
2474 {
2475 elfun_nat.SetSize(nvdofs);
2476 }
2477 for (int e = 0; e < NE; e++)
2478 {
2480 {
2481 if (!dof_map)
2482 {
2483 elfun_nat.SetDataAndSize(xe.GetData()+e*nvdofs, nvdofs);
2484 }
2485 else
2486 {
2487 elfun_lex.SetDataAndSize(xe.GetData()+e*nvdofs, nvdofs);
2488 const int ndofs = fe.GetDof();
2489 for (int d = 0; d < sdim; d++)
2490 {
2491 for (int i_lex = 0; i_lex < ndofs; i_lex++)
2492 {
2493 elfun_nat[(*dof_map)[i_lex]+d*ndofs] =
2494 elfun_lex[i_lex+d*ndofs];
2495 }
2496 }
2497 }
2498 }
2499 J.UseExternalData(Jtr(e*NQ).Data(), sdim, dim, NQ);
2500 ComputeElementTargets(e, fe, ir, elfun_nat, J);
2501 }
2502}
2503
2505{
2506 switch (target_type)
2507 {
2508 case IDEAL_SHAPE_UNIT_SIZE: return false;
2512 case GIVEN_FULL: return true;
2513 default: MFEM_ABORT("TargetType not added to ContainsVolumeInfo.");
2514 }
2515 return false;
2516}
2517
2519 const IntegrationRule &ir,
2520 const Vector &elfun,
2521 DenseTensor &Jtr) const
2522{
2523 MFEM_CONTRACT_VAR(elfun);
2524 MFEM_ASSERT(target_type == IDEAL_SHAPE_UNIT_SIZE || nodes != NULL, "");
2525
2527 nodes->FESpace()->GetFE(e_id) : NULL;
2528 const DenseMatrix &Wideal =
2530 MFEM_ASSERT(Wideal.Height() == Jtr.SizeI(), "");
2531 MFEM_ASSERT(Wideal.Width() == Jtr.SizeJ(), "");
2532
2533 switch (target_type)
2534 {
2536 {
2537 for (int i = 0; i < ir.GetNPoints(); i++) { Jtr(i) = Wideal; }
2538 break;
2539 }
2541 {
2542 if (avg_volume == 0.0) { ComputeAvgVolume(); }
2543 DenseMatrix W(Wideal.Height());
2544
2545 NCMesh *ncmesh = nodes->FESpace()->GetMesh()->ncmesh;
2546 real_t el_volume = avg_volume;
2547 if (ncmesh)
2548 {
2549 el_volume = avg_volume / ncmesh->GetElementSizeReduction(e_id);
2550 }
2551
2552 W.Set(std::pow(volume_scale * el_volume / Wideal.Det(),
2553 1./W.Height()), Wideal);
2554 for (int i = 0; i < ir.GetNPoints(); i++) { Jtr(i) = W; }
2555 break;
2556 }
2559 {
2560 const int dim = nfe->GetDim(), dof = nfe->GetDof();
2561 MFEM_ASSERT(dim == nodes->FESpace()->GetVDim(), "");
2562 DenseMatrix dshape(dof, dim), pos(dof, dim);
2563 Array<int> xdofs(dof * dim);
2564 Vector posV(pos.Data(), dof * dim);
2565 real_t detW;
2566
2567 // always initialize detW to suppress a warning:
2568 detW = (target_type == IDEAL_SHAPE_GIVEN_SIZE) ? Wideal.Det() : 0.0;
2569 nodes->FESpace()->GetElementVDofs(e_id, xdofs);
2570 nodes->GetSubVector(xdofs, posV);
2571 for (int i = 0; i < ir.GetNPoints(); i++)
2572 {
2573 nfe->CalcDShape(ir.IntPoint(i), dshape);
2574 MultAtB(pos, dshape, Jtr(i));
2576 {
2577 const real_t det = Jtr(i).Det();
2578 MFEM_VERIFY(det > 0.0, "The given mesh is inverted!");
2579 Jtr(i).Set(std::pow(det / detW, 1./dim), Wideal);
2580 }
2581 }
2582 break;
2583 }
2584 default:
2585 MFEM_ABORT("invalid target type!");
2586 }
2587}
2588
2590 const IntegrationRule &ir,
2591 const Vector &elfun,
2593 DenseTensor &dJtr) const
2594{
2595 MFEM_CONTRACT_VAR(elfun);
2596 MFEM_ASSERT(target_type == IDEAL_SHAPE_UNIT_SIZE || nodes != NULL, "");
2597
2598 // TODO: Compute derivative for targets with GIVEN_SHAPE or/and GIVEN_SIZE
2599 for (int i = 0; i < Tpr.GetFE()->GetDim()*ir.GetNPoints(); i++)
2600 { dJtr(i) = 0.; }
2601}
2602
2604 VectorCoefficient *vspec,
2605 TMOPMatrixCoefficient *mspec)
2606{
2607 scalar_tspec = sspec;
2608 vector_tspec = vspec;
2609 matrix_tspec = mspec;
2610}
2611
2613 const IntegrationRule &ir,
2614 const Vector &elfun,
2615 DenseTensor &Jtr) const
2616{
2617 DenseMatrix point_mat;
2618 point_mat.UseExternalData(elfun.GetData(), fe.GetDof(), fe.GetDim());
2619
2620 switch (target_type)
2621 {
2622 case GIVEN_FULL:
2623 {
2624 MFEM_VERIFY(matrix_tspec != NULL,
2625 "Target type GIVEN_FULL requires a MatrixCoefficient.");
2626
2628 Tpr.SetFE(&fe);
2629 Tpr.ElementNo = e_id;
2631 Tpr.GetPointMat().Transpose(point_mat);
2632
2633 for (int i = 0; i < ir.GetNPoints(); i++)
2634 {
2635 const IntegrationPoint &ip = ir.IntPoint(i);
2636 Tpr.SetIntPoint(&ip);
2637 matrix_tspec->Eval(Jtr(i), Tpr, ip);
2638 }
2639 break;
2640 }
2641 default:
2642 MFEM_ABORT("Incompatible target type for analytic adaptation!");
2643 }
2644}
2645
2647 const Vector &elfun,
2649 DenseTensor &dJtr) const
2650{
2651 const FiniteElement *fe = Tpr.GetFE();
2652 DenseMatrix point_mat;
2653 point_mat.UseExternalData(elfun.GetData(), fe->GetDof(), fe->GetDim());
2654
2655 switch (target_type)
2656 {
2657 case GIVEN_FULL:
2658 {
2659 MFEM_VERIFY(matrix_tspec != NULL,
2660 "Target type GIVEN_FULL requires a TMOPMatrixCoefficient.");
2661
2662 for (int d = 0; d < fe->GetDim(); d++)
2663 {
2664 for (int i = 0; i < ir.GetNPoints(); i++)
2665 {
2666 const IntegrationPoint &ip = ir.IntPoint(i);
2667 Tpr.SetIntPoint(&ip);
2668 DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
2669 matrix_tspec->EvalGrad(dJtr_i, Tpr, ip, d);
2670 }
2671 }
2672 break;
2673 }
2674 default:
2675 MFEM_ABORT("Incompatible target type for analytic adaptation!");
2676 }
2677}
2678
2679namespace internal
2680{
2681
2682// mfem::forall-based copy kernel -- used by protected methods below.
2683// Needed as a workaround for the nvcc restriction that methods with mfem::forall
2684// in them must to be public.
2685static inline void device_copy(real_t *d_dest, const real_t *d_src, int size)
2686{
2687 mfem::forall(size, [=] MFEM_HOST_DEVICE (int i) { d_dest[i] = d_src[i]; });
2688}
2689
2690} // namespace internal
2691
2692#ifdef MFEM_USE_MPI
2694{
2695 MFEM_VERIFY(adapt_eval, "SetAdaptivityEvaluator() has not been called!")
2696 MFEM_VERIFY(ncomp > 0, "No target specifications have been set!");
2697
2698 ParFiniteElementSpace *ptspec_fes = t.ParFESpace();
2699
2700 tspec_sav = tspec;
2701
2702 delete tspec_fesv;
2703 tspec_fesv = new FiniteElementSpace(ptspec_fes->GetMesh(),
2704 ptspec_fes->FEColl(), ncomp);
2705
2706 delete ptspec_fesv;
2707 ptspec_fesv = new ParFiniteElementSpace(ptspec_fes->GetParMesh(),
2708 ptspec_fes->FEColl(), ncomp);
2709
2710 delete tspec_pgf;
2713
2715 adapt_eval->SetInitialField(*ptspec_fes->GetMesh()->GetNodes(), tspec);
2716}
2717
2735
2737{
2738 const int vdim = tspec_.FESpace()->GetVDim(),
2739 ndof = tspec_.FESpace()->GetNDofs();
2740 MFEM_VERIFY(ndof == tspec.Size()/ncomp, "Inconsistency in SetTspecAtIndex.");
2741
2742 const auto tspec__d = tspec_.Read();
2743 auto tspec_d = tspec.ReadWrite();
2744 const int offset = idx*ndof;
2745 internal::device_copy(tspec_d + offset, tspec__d, ndof*vdim);
2747}
2748
2750{
2751 MFEM_VERIFY(tspec_.FESpace()->GetOrdering() == Ordering::byNODES,
2752 "Discrete target size should be ordered byNodes.");
2753 if (sizeidx > -1) { SetTspecAtIndex(sizeidx, tspec_); return; }
2754 sizeidx = ncomp;
2755 SetDiscreteTargetBase(tspec_);
2757}
2758
2760{
2761 MFEM_VERIFY(tspec_.FESpace()->GetOrdering() == Ordering::byNODES,
2762 "Discrete target skewness should be ordered byNodes.");
2763 if (skewidx > -1) { SetTspecAtIndex(skewidx, tspec_); return; }
2764 skewidx = ncomp;
2765 SetDiscreteTargetBase(tspec_);
2767}
2768
2770{
2771 MFEM_VERIFY(ar.FESpace()->GetOrdering() == Ordering::byNODES,
2772 "Discrete target aspect ratio should be ordered byNodes.");
2773 if (aspectratioidx > -1) { SetTspecAtIndex(aspectratioidx, ar); return; }
2777}
2778
2780{
2781 MFEM_VERIFY(o.FESpace()->GetOrdering() == Ordering::byNODES,
2782 "Discrete target orientation should be ordered byNodes.");
2783 if (orientationidx > -1) { SetTspecAtIndex(orientationidx, o); return; }
2787}
2788
2793#endif // MFEM_USE_MPI
2794
2796{
2797 const int vdim = tspec_.FESpace()->GetVDim(),
2798 ndof = tspec_.FESpace()->GetNDofs();
2799 ncomp += vdim;
2800
2801 // need to append data to tspec
2802 // make a copy of tspec->tspec_temp, increase its size, and
2803 // copy data from tspec_temp -> tspec, then add new entries
2804 Vector tspec_temp = tspec;
2805 tspec.UseDevice(true);
2806 tspec_sav.UseDevice(true);
2807 tspec.SetSize(ncomp*ndof);
2808
2809 const auto tspec_temp_d = tspec_temp.Read();
2810 auto tspec_d = tspec.ReadWrite();
2811 internal::device_copy(tspec_d, tspec_temp_d, tspec_temp.Size());
2812
2813 const auto tspec__d = tspec_.Read();
2814 const int offset = (ncomp-vdim)*ndof;
2815 internal::device_copy(tspec_d + offset, tspec__d, ndof*vdim);
2816}
2817
2819{
2820 const int vdim = tspec_.FESpace()->GetVDim(),
2821 ndof = tspec_.FESpace()->GetNDofs();
2822 MFEM_VERIFY(ndof == tspec.Size()/ncomp, "Inconsistency in SetTspecAtIndex.");
2823
2824 const auto tspec__d = tspec_.Read();
2825 auto tspec_d = tspec.ReadWrite();
2826 const int offset = idx*ndof;
2827 internal::device_copy(tspec_d + offset, tspec__d, ndof*vdim);
2829}
2830
2832{
2833 MFEM_VERIFY(tspec_.FESpace()->GetOrdering() == Ordering::byNODES,
2834 "Discrete target size should be ordered byNodes.");
2835 if (sizeidx > -1) { SetTspecAtIndex(sizeidx, tspec_); return; }
2836 sizeidx = ncomp;
2837 SetDiscreteTargetBase(tspec_);
2839}
2840
2842{
2843 MFEM_VERIFY(tspec_.FESpace()->GetOrdering() == Ordering::byNODES,
2844 "Discrete target skewness should be ordered byNodes.");
2845 if (skewidx > -1) { SetTspecAtIndex(skewidx, tspec_); return; }
2846 skewidx = ncomp;
2847 SetDiscreteTargetBase(tspec_);
2849}
2850
2852{
2853 MFEM_VERIFY(ar.FESpace()->GetOrdering() == Ordering::byNODES,
2854 "Discrete target aspect ratio should be ordered byNodes.");
2855 if (aspectratioidx > -1) { SetTspecAtIndex(aspectratioidx, ar); return; }
2859}
2860
2862{
2863 MFEM_VERIFY(o.FESpace()->GetOrdering() == Ordering::byNODES,
2864 "Discrete target orientation should be ordered byNodes.");
2865 if (orientationidx > -1) { SetTspecAtIndex(orientationidx, o); return; }
2869}
2870
2872{
2873 MFEM_VERIFY(adapt_eval, "SetAdaptivityEvaluator() has not been called!")
2874 MFEM_VERIFY(ncomp > 0, "No target specifications have been set!");
2875
2876 const FiniteElementSpace *tspec_fes = t.FESpace();
2877
2878 tspec_sav = tspec;
2879
2880 delete tspec_fesv;
2881 tspec_fesv = new FiniteElementSpace(tspec_fes->GetMesh(),
2882 tspec_fes->FEColl(), ncomp,
2884
2885 delete tspec_gf;
2887
2889 adapt_eval->SetInitialField(*tspec_fes->GetMesh()->GetNodes(), tspec);
2890}
2891
2893{
2894 if (idx < 0) { return; }
2895 const int ndof = tspec_.FESpace()->GetNDofs(),
2896 vdim = tspec_.FESpace()->GetVDim();
2897 MFEM_VERIFY(ndof == tspec.Size()/ncomp,
2898 "Inconsistency in GetSerialDiscreteTargetSpec.");
2899
2900 for (int i = 0; i < ndof*vdim; i++)
2901 {
2902 tspec_(i) = tspec(i + idx*ndof);
2903 }
2904}
2905
2916
2921
2922
2924 bool reuse_flag,
2925 int new_x_ordering)
2926{
2927 if (reuse_flag && good_tspec) { return; }
2928
2929 MFEM_VERIFY(tspec.Size() > 0, "Target specification is not set!");
2930 adapt_eval->ComputeAtNewPosition(new_x, tspec, new_x_ordering);
2931 tspec_sav = tspec;
2932
2933 good_tspec = reuse_flag;
2934}
2935
2937 Vector &IntData,
2938 int new_x_ordering)
2939{
2940 adapt_eval->ComputeAtNewPosition(new_x, IntData, new_x_ordering);
2941}
2942
2945 int dofidx, int dir,
2946 const Vector &IntData)
2947{
2948 MFEM_VERIFY(tspec.Size() > 0, "Target specification is not set!");
2949
2950 Array<int> dofs;
2952 const int cnt = tspec.Size()/ncomp; // dofs per scalar-field
2953
2954 for (int i = 0; i < ncomp; i++)
2955 {
2956 tspec(dofs[dofidx]+i*cnt) = IntData(dofs[dofidx] + i*cnt + dir*cnt*ncomp);
2957 }
2958}
2959
2961 int dofidx)
2962{
2963 MFEM_VERIFY(tspec.Size() > 0, "Target specification is not set!");
2964
2965 Array<int> dofs;
2967 const int cnt = tspec.Size()/ncomp;
2968 for (int i = 0; i < ncomp; i++)
2969 {
2970 tspec(dofs[dofidx] + i*cnt) = tspec_sav(dofs[dofidx] + i*cnt);
2971 }
2972}
2973
2975 const IntegrationRule &intrule)
2976{
2977 switch (target_type)
2978 {
2981 {
2982 const int ndofs = tspec_fesv->GetFE(e_id)->GetDof(),
2983 ntspec_dofs = ndofs*ncomp;
2984
2985 Vector tspec_vals(ntspec_dofs);
2986
2987 Array<int> dofs;
2988 tspec_fesv->GetElementVDofs(e_id, dofs);
2989 tspec.GetSubVector(dofs, tspec_vals);
2990 DenseMatrix tr;
2991 tspec_gf->GetVectorValues(e_id, intrule, tspec_refine, tr);
2993 break;
2994 }
2995 default:
2996 MFEM_ABORT("Incompatible target type for discrete adaptation!");
2997 }
2998}
2999
3007
3009 const IntegrationRule &ir,
3010 const Vector &elfun,
3011 DenseTensor &Jtr) const
3012{
3013 MFEM_VERIFY(tspec_fesv, "No target specifications have been set.");
3014 const int dim = fe.GetDim(),
3015 nqp = ir.GetNPoints();
3016 Jtrcomp.SetSize(dim, dim, 4*nqp);
3017
3018 FiniteElementSpace *src_fes = tspec_fesv;
3019
3020 switch (target_type)
3021 {
3024 {
3025 const DenseMatrix &Wideal =
3027 const int ndofs = tspec_fesv->GetFE(e_id)->GetDof(),
3028 ntspec_dofs = ndofs*ncomp;
3029
3030 Vector shape(ndofs), tspec_vals(ntspec_dofs), par_vals,
3031 par_vals_c1, par_vals_c2, par_vals_c3;
3032
3033 Array<int> dofs;
3034 DenseMatrix D_rho(dim), Q_phi(dim), R_theta(dim);
3035 tspec_fesv->GetElementVDofs(e_id, dofs);
3036 tspec.UseDevice(true);
3037 tspec.GetSubVector(dofs, tspec_vals);
3038 if (tspec_refine.NumCols() > 0) // Refinement
3039 {
3040 MFEM_VERIFY(amr_el >= 0, " Target being constructed for an AMR element.");
3041 for (int i = 0; i < ncomp; i++)
3042 {
3043 for (int j = 0; j < ndofs; j++)
3044 {
3045 tspec_vals(j + i*ndofs) = tspec_refine(j + amr_el*ndofs, i);
3046 }
3047 }
3048 }
3049 else if (tspec_derefine.Size() > 0) // Derefinement
3050 {
3051 dofs.SetSize(0);
3053 tspec_derefine.GetSubVector(dofs, tspec_vals);
3054 src_fes = coarse_tspec_fesv;
3055 }
3056
3057 for (int q = 0; q < nqp; q++)
3058 {
3059 const IntegrationPoint &ip = ir.IntPoint(q);
3060 src_fes->GetFE(e_id)->CalcShape(ip, shape);
3061 Jtr(q) = Wideal; // Initialize to identity
3062 for (int d = 0; d < 4; d++)
3063 {
3064 DenseMatrix Jtrcomp_q(Jtrcomp.GetData(d + 4*q), dim, dim);
3065 Jtrcomp_q = Wideal; // Initialize to identity
3066 }
3067
3068 if (sizeidx != -1) // Set size
3069 {
3070 par_vals.SetDataAndSize(tspec_vals.GetData()+sizeidx*ndofs, ndofs);
3071 real_t min_size = par_vals.Min();
3072 if (lim_min_size > 0.) { min_size = lim_min_size; }
3073 MFEM_VERIFY(min_size > 0.0,
3074 "Non-positive size propagated in the target definition.");
3075
3076 real_t size = std::max(shape * par_vals, min_size);
3077 NCMesh *ncmesh = tspec_fesv->GetMesh()->ncmesh;
3078 if (ncmesh)
3079 {
3080 size /= ncmesh->GetElementSizeReduction(e_id);
3081 }
3082 Jtr(q).Set(std::pow(size, 1.0/dim), Jtr(q));
3083 DenseMatrix Jtrcomp_q(Jtrcomp.GetData(0 + 4*q), dim, dim);
3084 Jtrcomp_q = Jtr(q);
3085 } // Done size
3086
3087 if (target_type == IDEAL_SHAPE_GIVEN_SIZE) { continue; }
3088
3089 if (aspectratioidx != -1) // Set aspect ratio
3090 {
3091 if (dim == 2)
3092 {
3093 par_vals.SetDataAndSize(tspec_vals.GetData()+
3094 aspectratioidx*ndofs, ndofs);
3095 const real_t min_size = par_vals.Min();
3096 MFEM_VERIFY(min_size > 0.0,
3097 "Non-positive aspect-ratio propagated in the target definition.");
3098
3099 const real_t aspectratio = shape * par_vals;
3100 D_rho = 0.;
3101 D_rho(0,0) = 1./pow(aspectratio,0.5);
3102 D_rho(1,1) = pow(aspectratio,0.5);
3103 }
3104 else
3105 {
3106 par_vals.SetDataAndSize(tspec_vals.GetData()+
3107 aspectratioidx*ndofs, ndofs*3);
3108 par_vals_c1.SetDataAndSize(par_vals.GetData(), ndofs);
3109 par_vals_c2.SetDataAndSize(par_vals.GetData()+ndofs, ndofs);
3110 par_vals_c3.SetDataAndSize(par_vals.GetData()+2*ndofs, ndofs);
3111
3112 const real_t rho1 = shape * par_vals_c1;
3113 const real_t rho2 = shape * par_vals_c2;
3114 const real_t rho3 = shape * par_vals_c3;
3115 D_rho = 0.;
3116 D_rho(0,0) = pow(rho1,2./3.);
3117 D_rho(1,1) = pow(rho2,2./3.);
3118 D_rho(2,2) = pow(rho3,2./3.);
3119 }
3120 DenseMatrix Jtrcomp_q(Jtrcomp.GetData(1 + 4*q), dim, dim);
3121 Jtrcomp_q = D_rho;
3122 DenseMatrix Temp = Jtr(q);
3123 Mult(D_rho, Temp, Jtr(q));
3124 } // Done aspect ratio
3125
3126 if (skewidx != -1) // Set skew
3127 {
3128 if (dim == 2)
3129 {
3130 par_vals.SetDataAndSize(tspec_vals.GetData()+
3131 skewidx*ndofs, ndofs);
3132
3133 const real_t skew = shape * par_vals;
3134
3135 Q_phi = 0.;
3136 Q_phi(0,0) = 1.;
3137 Q_phi(0,1) = cos(skew);
3138 Q_phi(1,1) = sin(skew);
3139 }
3140 else
3141 {
3142 par_vals.SetDataAndSize(tspec_vals.GetData()+
3143 skewidx*ndofs, ndofs*3);
3144 par_vals_c1.SetDataAndSize(par_vals.GetData(), ndofs);
3145 par_vals_c2.SetDataAndSize(par_vals.GetData()+ndofs, ndofs);
3146 par_vals_c3.SetDataAndSize(par_vals.GetData()+2*ndofs, ndofs);
3147
3148 const real_t phi12 = shape * par_vals_c1;
3149 const real_t phi13 = shape * par_vals_c2;
3150 const real_t chi = shape * par_vals_c3;
3151
3152 Q_phi = 0.;
3153 Q_phi(0,0) = 1.;
3154 Q_phi(0,1) = cos(phi12);
3155 Q_phi(0,2) = cos(phi13);
3156
3157 Q_phi(1,1) = sin(phi12);
3158 Q_phi(1,2) = sin(phi13)*cos(chi);
3159
3160 Q_phi(2,2) = sin(phi13)*sin(chi);
3161 }
3162 DenseMatrix Jtrcomp_q(Jtrcomp.GetData(2 + 4*q), dim, dim);
3163 Jtrcomp_q = Q_phi;
3164 DenseMatrix Temp = Jtr(q);
3165 Mult(Q_phi, Temp, Jtr(q));
3166 } // Done skew
3167
3168 if (orientationidx != -1) // Set orientation
3169 {
3170 if (dim == 2)
3171 {
3172 par_vals.SetDataAndSize(tspec_vals.GetData()+
3173 orientationidx*ndofs, ndofs);
3174
3175 const real_t theta = shape * par_vals;
3176 R_theta(0,0) = cos(theta);
3177 R_theta(0,1) = -sin(theta);
3178 R_theta(1,0) = sin(theta);
3179 R_theta(1,1) = cos(theta);
3180 }
3181 else
3182 {
3183 par_vals.SetDataAndSize(tspec_vals.GetData()+
3184 orientationidx*ndofs, ndofs*3);
3185 par_vals_c1.SetDataAndSize(par_vals.GetData(), ndofs);
3186 par_vals_c2.SetDataAndSize(par_vals.GetData()+ndofs, ndofs);
3187 par_vals_c3.SetDataAndSize(par_vals.GetData()+2*ndofs, ndofs);
3188
3189 const real_t theta = shape * par_vals_c1;
3190 const real_t psi = shape * par_vals_c2;
3191 const real_t beta = shape * par_vals_c3;
3192
3193 real_t ct = cos(theta), st = sin(theta),
3194 cp = cos(psi), sp = sin(psi),
3195 cb = cos(beta), sb = sin(beta);
3196
3197 R_theta = 0.;
3198 R_theta(0,0) = ct*sp;
3199 R_theta(1,0) = st*sp;
3200 R_theta(2,0) = cp;
3201
3202 R_theta(0,1) = -st*cb + ct*cp*sb;
3203 R_theta(1,1) = ct*cb + st*cp*sb;
3204 R_theta(2,1) = -sp*sb;
3205
3206 R_theta(0,0) = -st*sb - ct*cp*cb;
3207 R_theta(1,0) = ct*sb - st*cp*cb;
3208 R_theta(2,0) = sp*cb;
3209 }
3210 DenseMatrix Jtrcomp_q(Jtrcomp.GetData(3 + 4*q), dim, dim);
3211 Jtrcomp_q = R_theta;
3212 DenseMatrix Temp = Jtr(q);
3213 Mult(R_theta, Temp, Jtr(q));
3214 } // Done orientation
3215 }
3216 break;
3217 }
3218 default:
3219 MFEM_ABORT("Incompatible target type for discrete adaptation!");
3220 }
3221}
3222
3224 const Vector &elfun,
3226 DenseTensor &dJtr) const
3227{
3228 MFEM_ASSERT(target_type == IDEAL_SHAPE_UNIT_SIZE || nodes != NULL, "");
3229
3230 MFEM_VERIFY(tspec_fesv, "No target specifications have been set.");
3231
3232 dJtr = 0.;
3233 const int e_id = Tpr.ElementNo;
3234 const FiniteElement *fe = Tpr.GetFE();
3235
3236 switch (target_type)
3237 {
3240 {
3241 const DenseMatrix &Wideal =
3243 const int dim = Wideal.Height(),
3244 ndofs = fe->GetDof(),
3245 ntspec_dofs = ndofs*ncomp;
3246
3247 Vector shape(ndofs), tspec_vals(ntspec_dofs), par_vals,
3248 par_vals_c1(ndofs), par_vals_c2(ndofs), par_vals_c3(ndofs);
3249
3250 Array<int> dofs;
3251 DenseMatrix dD_rho(dim), dQ_phi(dim), dR_theta(dim);
3252 DenseMatrix dQ_phi13(dim), dQ_phichi(dim); // dQ_phi is used for dQ/dphi12 in 3D
3253 DenseMatrix dR_psi(dim), dR_beta(dim);
3254 tspec_fesv->GetElementVDofs(e_id, dofs);
3255 tspec.GetSubVector(dofs, tspec_vals);
3256
3257 DenseMatrix grad_e_c1(ndofs, dim),
3258 grad_e_c2(ndofs, dim),
3259 grad_e_c3(ndofs, dim);
3260 Vector grad_ptr_c1(grad_e_c1.GetData(), ndofs*dim),
3261 grad_ptr_c2(grad_e_c2.GetData(), ndofs*dim),
3262 grad_ptr_c3(grad_e_c3.GetData(), ndofs*dim);
3263
3264 DenseMatrix grad_phys; // This will be (dof x dim, dof).
3265 fe->ProjectGrad(*fe, Tpr, grad_phys);
3266
3267 for (int i = 0; i < ir.GetNPoints(); i++)
3268 {
3269 const IntegrationPoint &ip = ir.IntPoint(i);
3270 DenseMatrix Jtrcomp_s(Jtrcomp.GetData(0 + 4*i), dim, dim); // size
3271 DenseMatrix Jtrcomp_d(Jtrcomp.GetData(1 + 4*i), dim, dim); // aspect-ratio
3272 DenseMatrix Jtrcomp_q(Jtrcomp.GetData(2 + 4*i), dim, dim); // skew
3273 DenseMatrix Jtrcomp_r(Jtrcomp.GetData(3 + 4*i), dim, dim); // orientation
3274 DenseMatrix work1(dim), work2(dim), work3(dim);
3275
3276 if (sizeidx != -1) // Set size
3277 {
3278 par_vals.SetDataAndSize(tspec_vals.GetData()+sizeidx*ndofs, ndofs);
3279
3280 grad_phys.Mult(par_vals, grad_ptr_c1);
3281 Vector grad_q(dim);
3282 tspec_fesv->GetFE(e_id)->CalcShape(ip, shape);
3283 grad_e_c1.MultTranspose(shape, grad_q);
3284
3285 const real_t min_size = par_vals.Min();
3286 MFEM_VERIFY(min_size > 0.0,
3287 "Non-positive size propagated in the target definition.");
3288 const real_t size = std::max(shape * par_vals, min_size);
3289 real_t dz_dsize = (1./dim)*pow(size, 1./dim - 1.);
3290
3291 Mult(Jtrcomp_q, Jtrcomp_d, work1); // Q*D
3292 Mult(Jtrcomp_r, work1, work2); // R*Q*D
3293
3294 for (int d = 0; d < dim; d++)
3295 {
3296 DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
3297 work1 = Wideal;
3298 work1.Set(dz_dsize, work1); // dz/dsize
3299 work1 *= grad_q(d); // dz/dsize*dsize/dx
3300 AddMult(work1, work2, dJtr_i); // dz/dx*R*Q*D
3301 }
3302 } // Done size
3303
3304 if (target_type == IDEAL_SHAPE_GIVEN_SIZE) { continue; }
3305
3306 if (aspectratioidx != -1) // Set aspect ratio
3307 {
3308 if (dim == 2)
3309 {
3310 par_vals.SetDataAndSize(tspec_vals.GetData()+
3311 aspectratioidx*ndofs, ndofs);
3312
3313 grad_phys.Mult(par_vals, grad_ptr_c1);
3314 Vector grad_q(dim);
3315 tspec_fesv->GetFE(e_id)->CalcShape(ip, shape);
3316 grad_e_c1.MultTranspose(shape, grad_q);
3317
3318 const real_t aspectratio = shape * par_vals;
3319 dD_rho = 0.;
3320 dD_rho(0,0) = -0.5*pow(aspectratio,-1.5);
3321 dD_rho(1,1) = 0.5*pow(aspectratio,-0.5);
3322
3323 Mult(Jtrcomp_s, Jtrcomp_r, work1); // z*R
3324 Mult(work1, Jtrcomp_q, work2); // z*R*Q
3325
3326 for (int d = 0; d < dim; d++)
3327 {
3328 DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
3329 work1 = dD_rho;
3330 work1 *= grad_q(d); // work1 = dD/drho*drho/dx
3331 AddMult(work2, work1, dJtr_i); // z*R*Q*dD/dx
3332 }
3333 }
3334 else // 3D
3335 {
3336 par_vals.SetDataAndSize(tspec_vals.GetData()+
3337 aspectratioidx*ndofs, ndofs*3);
3338 par_vals_c1.SetData(par_vals.GetData());
3339 par_vals_c2.SetData(par_vals.GetData()+ndofs);
3340 par_vals_c3.SetData(par_vals.GetData()+2*ndofs);
3341
3342 grad_phys.Mult(par_vals_c1, grad_ptr_c1);
3343 grad_phys.Mult(par_vals_c2, grad_ptr_c2);
3344 grad_phys.Mult(par_vals_c3, grad_ptr_c3);
3345 Vector grad_q1(dim), grad_q2(dim), grad_q3(dim);
3346 tspec_fesv->GetFE(e_id)->CalcShape(ip, shape);
3347 grad_e_c1.MultTranspose(shape, grad_q1);
3348 grad_e_c2.MultTranspose(shape, grad_q2);
3349 grad_e_c3.MultTranspose(shape, grad_q3);
3350
3351 const real_t rho1 = shape * par_vals_c1;
3352 const real_t rho2 = shape * par_vals_c2;
3353 const real_t rho3 = shape * par_vals_c3;
3354 dD_rho = 0.;
3355 dD_rho(0,0) = (2./3.)*pow(rho1,-1./3.);
3356 dD_rho(1,1) = (2./3.)*pow(rho2,-1./3.);
3357 dD_rho(2,2) = (2./3.)*pow(rho3,-1./3.);
3358
3359 Mult(Jtrcomp_s, Jtrcomp_r, work1); // z*R
3360 Mult(work1, Jtrcomp_q, work2); // z*R*Q
3361
3362
3363 for (int d = 0; d < dim; d++)
3364 {
3365 DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
3366 work1 = dD_rho;
3367 work1(0,0) *= grad_q1(d);
3368 work1(1,2) *= grad_q2(d);
3369 work1(2,2) *= grad_q3(d);
3370 // work1 = dD/dx = dD/drho1*drho1/dx + dD/drho2*drho2/dx
3371 AddMult(work2, work1, dJtr_i); // z*R*Q*dD/dx
3372 }
3373 }
3374 } // Done aspect ratio
3375
3376 if (skewidx != -1) // Set skew
3377 {
3378 if (dim == 2)
3379 {
3380 par_vals.SetDataAndSize(tspec_vals.GetData()+
3381 skewidx*ndofs, ndofs);
3382
3383 grad_phys.Mult(par_vals, grad_ptr_c1);
3384 Vector grad_q(dim);
3385 tspec_fesv->GetFE(e_id)->CalcShape(ip, shape);
3386 grad_e_c1.MultTranspose(shape, grad_q);
3387
3388 const real_t skew = shape * par_vals;
3389
3390 dQ_phi = 0.;
3391 dQ_phi(0,0) = 1.;
3392 dQ_phi(0,1) = -sin(skew);
3393 dQ_phi(1,1) = cos(skew);
3394
3395 Mult(Jtrcomp_s, Jtrcomp_r, work2); // z*R
3396
3397 for (int d = 0; d < dim; d++)
3398 {
3399 DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
3400 work1 = dQ_phi;
3401 work1 *= grad_q(d); // work1 = dQ/dphi*dphi/dx
3402 Mult(work1, Jtrcomp_d, work3); // dQ/dx*D
3403 AddMult(work2, work3, dJtr_i); // z*R*dQ/dx*D
3404 }
3405 }
3406 else
3407 {
3408 par_vals.SetDataAndSize(tspec_vals.GetData()+
3409 skewidx*ndofs, ndofs*3);
3410 par_vals_c1.SetData(par_vals.GetData());
3411 par_vals_c2.SetData(par_vals.GetData()+ndofs);
3412 par_vals_c3.SetData(par_vals.GetData()+2*ndofs);
3413
3414 grad_phys.Mult(par_vals_c1, grad_ptr_c1);
3415 grad_phys.Mult(par_vals_c2, grad_ptr_c2);
3416 grad_phys.Mult(par_vals_c3, grad_ptr_c3);
3417 Vector grad_q1(dim), grad_q2(dim), grad_q3(dim);
3418 tspec_fesv->GetFE(e_id)->CalcShape(ip, shape);
3419 grad_e_c1.MultTranspose(shape, grad_q1);
3420 grad_e_c2.MultTranspose(shape, grad_q2);
3421 grad_e_c3.MultTranspose(shape, grad_q3);
3422
3423 const real_t phi12 = shape * par_vals_c1;
3424 const real_t phi13 = shape * par_vals_c2;
3425 const real_t chi = shape * par_vals_c3;
3426
3427 dQ_phi = 0.;
3428 dQ_phi(0,0) = 1.;
3429 dQ_phi(0,1) = -sin(phi12);
3430 dQ_phi(1,1) = cos(phi12);
3431
3432 dQ_phi13 = 0.;
3433 dQ_phi13(0,2) = -sin(phi13);
3434 dQ_phi13(1,2) = cos(phi13)*cos(chi);
3435 dQ_phi13(2,2) = cos(phi13)*sin(chi);
3436
3437 dQ_phichi = 0.;
3438 dQ_phichi(1,2) = -sin(phi13)*sin(chi);
3439 dQ_phichi(2,2) = sin(phi13)*cos(chi);
3440
3441 Mult(Jtrcomp_s, Jtrcomp_r, work2); // z*R
3442
3443 for (int d = 0; d < dim; d++)
3444 {
3445 DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
3446 work1 = dQ_phi;
3447 work1 *= grad_q1(d); // work1 = dQ/dphi12*dphi12/dx
3448 work1.Add(grad_q2(d), dQ_phi13); // + dQ/dphi13*dphi13/dx
3449 work1.Add(grad_q3(d), dQ_phichi); // + dQ/dchi*dchi/dx
3450 Mult(work1, Jtrcomp_d, work3); // dQ/dx*D
3451 AddMult(work2, work3, dJtr_i); // z*R*dQ/dx*D
3452 }
3453 }
3454 } // Done skew
3455
3456 if (orientationidx != -1) // Set orientation
3457 {
3458 if (dim == 2)
3459 {
3460 par_vals.SetDataAndSize(tspec_vals.GetData()+
3461 orientationidx*ndofs, ndofs);
3462
3463 grad_phys.Mult(par_vals, grad_ptr_c1);
3464 Vector grad_q(dim);
3465 tspec_fesv->GetFE(e_id)->CalcShape(ip, shape);
3466 grad_e_c1.MultTranspose(shape, grad_q);
3467
3468 const real_t theta = shape * par_vals;
3469 dR_theta(0,0) = -sin(theta);
3470 dR_theta(0,1) = -cos(theta);
3471 dR_theta(1,0) = cos(theta);
3472 dR_theta(1,1) = -sin(theta);
3473
3474 Mult(Jtrcomp_q, Jtrcomp_d, work1); // Q*D
3475 Mult(Jtrcomp_s, work1, work2); // z*Q*D
3476 for (int d = 0; d < dim; d++)
3477 {
3478 DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
3479 work1 = dR_theta;
3480 work1 *= grad_q(d); // work1 = dR/dtheta*dtheta/dx
3481 AddMult(work1, work2, dJtr_i); // z*dR/dx*Q*D
3482 }
3483 }
3484 else
3485 {
3486 par_vals.SetDataAndSize(tspec_vals.GetData()+
3487 orientationidx*ndofs, ndofs*3);
3488 par_vals_c1.SetData(par_vals.GetData());
3489 par_vals_c2.SetData(par_vals.GetData()+ndofs);
3490 par_vals_c3.SetData(par_vals.GetData()+2*ndofs);
3491
3492 grad_phys.Mult(par_vals_c1, grad_ptr_c1);
3493 grad_phys.Mult(par_vals_c2, grad_ptr_c2);
3494 grad_phys.Mult(par_vals_c3, grad_ptr_c3);
3495 Vector grad_q1(dim), grad_q2(dim), grad_q3(dim);
3496 tspec_fesv->GetFE(e_id)->CalcShape(ip, shape);
3497 grad_e_c1.MultTranspose(shape, grad_q1);
3498 grad_e_c2.MultTranspose(shape, grad_q2);
3499 grad_e_c3.MultTranspose(shape, grad_q3);
3500
3501 const real_t theta = shape * par_vals_c1;
3502 const real_t psi = shape * par_vals_c2;
3503 const real_t beta = shape * par_vals_c3;
3504
3505 const real_t ct = cos(theta), st = sin(theta),
3506 cp = cos(psi), sp = sin(psi),
3507 cb = cos(beta), sb = sin(beta);
3508
3509 dR_theta = 0.;
3510 dR_theta(0,0) = -st*sp;
3511 dR_theta(1,0) = ct*sp;
3512 dR_theta(2,0) = 0;
3513
3514 dR_theta(0,1) = -ct*cb - st*cp*sb;
3515 dR_theta(1,1) = -st*cb + ct*cp*sb;
3516 dR_theta(2,1) = 0.;
3517
3518 dR_theta(0,0) = -ct*sb + st*cp*cb;
3519 dR_theta(1,0) = -st*sb - ct*cp*cb;
3520 dR_theta(2,0) = 0.;
3521
3522 dR_beta = 0.;
3523 dR_beta(0,0) = 0.;
3524 dR_beta(1,0) = 0.;
3525 dR_beta(2,0) = 0.;
3526
3527 dR_beta(0,1) = st*sb + ct*cp*cb;
3528 dR_beta(1,1) = -ct*sb + st*cp*cb;
3529 dR_beta(2,1) = -sp*cb;
3530
3531 dR_beta(0,0) = -st*cb + ct*cp*sb;
3532 dR_beta(1,0) = ct*cb + st*cp*sb;
3533 dR_beta(2,0) = 0.;
3534
3535 dR_psi = 0.;
3536 dR_psi(0,0) = ct*cp;
3537 dR_psi(1,0) = st*cp;
3538 dR_psi(2,0) = -sp;
3539
3540 dR_psi(0,1) = 0. - ct*sp*sb;
3541 dR_psi(1,1) = 0. + st*sp*sb;
3542 dR_psi(2,1) = -cp*sb;
3543
3544 dR_psi(0,0) = 0. + ct*sp*cb;
3545 dR_psi(1,0) = 0. + st*sp*cb;
3546 dR_psi(2,0) = cp*cb;
3547
3548 Mult(Jtrcomp_q, Jtrcomp_d, work1); // Q*D
3549 Mult(Jtrcomp_s, work1, work2); // z*Q*D
3550 for (int d = 0; d < dim; d++)
3551 {
3552 DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
3553 work1 = dR_theta;
3554 work1 *= grad_q1(d); // work1 = dR/dtheta*dtheta/dx
3555 work1.Add(grad_q2(d), dR_psi); // +dR/dpsi*dpsi/dx
3556 work1.Add(grad_q3(d), dR_beta); // +dR/dbeta*dbeta/dx
3557 AddMult(work1, work2, dJtr_i); // z*dR/dx*Q*D
3558 }
3559 }
3560 } // Done orientation
3561 }
3562 break;
3563 }
3564 default:
3565 MFEM_ABORT("Incompatible target type for discrete adaptation!");
3566 }
3567 Jtrcomp.Clear();
3568}
3569
3572 bool reuse_flag, int x_ordering)
3573{
3574 if (reuse_flag && good_tspec_grad) { return; }
3575
3576 const int dim = tspec_fesv->GetTypicalFE()->GetDim(),
3577 cnt = x.Size()/dim;
3578
3579 MFEM_VERIFY(tspec_fesv->GetVSize() / ncomp == cnt,
3580 "FD with discrete adaptivity assume mesh_order = field_order.");
3581
3583
3584 Vector TSpecTemp;
3585 Vector xtemp = x;
3586 for (int j = 0; j < dim; j++)
3587 {
3588 for (int i = 0; i < cnt; i++)
3589 {
3590 int idx = x_ordering == Ordering::byNODES ? j*cnt + i : i*dim + j;
3591 xtemp(idx) += dx;
3592 }
3593
3594 TSpecTemp.NewDataAndSize(tspec_pert1h.GetData() + j*cnt*ncomp, cnt*ncomp);
3595 UpdateTargetSpecification(xtemp, TSpecTemp, x_ordering);
3596
3597 for (int i = 0; i < cnt; i++)
3598 {
3599 int idx = x_ordering == Ordering::byNODES ? j*cnt + i : i*dim + j;
3600 xtemp(idx) -= dx;
3601 }
3602 }
3603
3604 good_tspec_grad = reuse_flag;
3605}
3606
3609 bool reuse_flag, int x_ordering)
3610{
3611 if (reuse_flag && good_tspec_hess) { return; }
3612
3613 const int dim = tspec_fesv->GetTypicalFE()->GetDim(),
3614 cnt = x.Size()/dim,
3615 totmix = 1+2*(dim-2);
3616
3617 MFEM_VERIFY(tspec_fesv->GetVSize() / ncomp == cnt,
3618 "FD with discrete adaptivity assume mesh_order = field_order.");
3619
3621 tspec_pertmix.SetSize(cnt*totmix*ncomp);
3622
3623 Vector TSpecTemp;
3624 Vector xtemp = x;
3625
3626 // T(x+2h)
3627 for (int j = 0; j < dim; j++)
3628 {
3629 for (int i = 0; i < cnt; i++)
3630 {
3631 int idx = x_ordering == Ordering::byNODES ? j*cnt + i : i*dim + j;
3632 xtemp(idx) += 2*dx;
3633 }
3634
3635 TSpecTemp.NewDataAndSize(tspec_pert2h.GetData() + j*cnt*ncomp, cnt*ncomp);
3636 UpdateTargetSpecification(xtemp, TSpecTemp, x_ordering);
3637
3638 for (int i = 0; i < cnt; i++)
3639 {
3640 int idx = x_ordering == Ordering::byNODES ? j*cnt + i : i*dim + j;
3641 xtemp(idx) -= 2*dx;
3642 }
3643 }
3644
3645 // T(x+h,y+h)
3646 int j = 0;
3647 for (int k1 = 0; k1 < dim; k1++)
3648 {
3649 for (int k2 = 0; (k1 != k2) && (k2 < dim); k2++)
3650 {
3651 for (int i = 0; i < cnt; i++)
3652 {
3653 int idx1 = x_ordering == Ordering::byNODES ? k1*cnt+i : i*dim + k1;
3654 int idx2 = x_ordering == Ordering::byNODES ? k2*cnt+i : i*dim + k2;
3655 xtemp(idx1) += dx;
3656 xtemp(idx2) += dx;
3657 }
3658
3659 TSpecTemp.NewDataAndSize(tspec_pertmix.GetData() + j*cnt*ncomp, cnt*ncomp);
3660 UpdateTargetSpecification(xtemp, TSpecTemp, x_ordering);
3661
3662 for (int i = 0; i < cnt; i++)
3663 {
3664 int idx1 = x_ordering == Ordering::byNODES ? k1*cnt+i : i*dim + k1;
3665 int idx2 = x_ordering == Ordering::byNODES ? k2*cnt+i : i*dim + k2;
3666 xtemp(idx1) -= dx;
3667 xtemp(idx2) -= dx;
3668 }
3669 j++;
3670 }
3671 }
3672
3673 good_tspec_hess = reuse_flag;
3674}
3675
3677{
3678 delete tspec_gf;
3679 delete adapt_eval;
3680 delete tspec_fesv;
3681#ifdef MFEM_USE_MPI
3682 delete ptspec_fesv;
3683#endif
3684}
3685
3687 const FiniteElementSpace &f)
3688{
3689 delete fes;
3690 delete mesh;
3691 mesh = new Mesh(m, true);
3692 fes = new FiniteElementSpace(mesh, f.FEColl(),
3693 f.GetVDim(), f.GetOrdering());
3694}
3695
3696#ifdef MFEM_USE_MPI
3698 const ParFiniteElementSpace &f)
3699{
3700 delete pfes;
3701 delete pmesh;
3702 pmesh = new ParMesh(m, true);
3703 pfes = new ParFiniteElementSpace(pmesh, f.FEColl(),
3704 f.GetVDim(), f.GetOrdering());
3705}
3706#endif
3707
3709{
3710#ifdef MFEM_USE_MPI
3712#else
3713 if (mesh) { mesh->DeleteGeometricFactors(); }
3714#endif
3715}
3716
3718{
3719 delete fes;
3720 delete mesh;
3721#ifdef MFEM_USE_MPI
3722 delete pfes;
3723 delete pmesh;
3724#endif
3725}
3726
3728{
3729 if (PA.enabled)
3730 {
3731 PA.H.GetMemory().DeleteDevice(copy_to_host);
3732 PA.H0.GetMemory().DeleteDevice(copy_to_host);
3733 if (!copy_to_host && !PA.Jtr.GetMemory().HostIsValid())
3734 {
3735 PA.Jtr_needs_update = true;
3736 }
3737 PA.Jtr.GetMemory().DeleteDevice(copy_to_host);
3738 }
3739}
3740
3742{
3743 x_0 = x0;
3744
3745 periodic = (x_0 && x_0->FESpace()->IsDGSpace()) ? true : false;
3746
3747 // Compute PA.X0 when we're setting x_0 to something.
3748 if (PA.enabled && x_0 != nullptr)
3749 {
3751 const Operator *n0_R = x0->FESpace()->GetElementRestriction(ord);
3752 PA.X0.UseDevice(true);
3753 PA.X0.SetSize(n0_R->Height(), Device::GetMemoryType());
3754 n0_R->Mult(*x_0, PA.X0);
3755 }
3756}
3757
3759{
3760 delete lim_func;
3761 for (int i = 0; i < adapt_lim_gf.Size(); i++) { delete adapt_lim_gf[i]; }
3762 for (int i = 0; i < adapt_lim_gf0.Size(); i++) { delete adapt_lim_gf0[i]; }
3763 delete surf_fit_gf;
3764 delete surf_fit_limiter;
3765 delete surf_fit_grad;
3766 delete surf_fit_hess;
3767 for (int i = 0; i < ElemDer.Size(); i++)
3768 {
3769 delete ElemDer[i];
3770 delete ElemPertEnergy[i];
3771 }
3772}
3773
3775 const GridFunction &dist, Coefficient &w0,
3776 TMOP_LimiterFunction *lfunc)
3777{
3778 lim_nodes0 = &n0;
3779 lim_coeff = &w0;
3780 lim_dist = &dist;
3781 MFEM_VERIFY(lim_dist->FESpace()->GetVDim() == 1,
3782 "'dist' must be a scalar GridFunction!");
3783
3784 delete lim_func;
3785 lim_func = (lfunc) ? lfunc : new TMOP_QuadraticLimiter;
3786}
3787
3789 TMOP_LimiterFunction *lfunc)
3790{
3791 lim_nodes0 = &n0;
3792 lim_coeff = &w0;
3793 lim_dist = NULL;
3794
3795 delete lim_func;
3796 lim_func = (lfunc) ? lfunc : new TMOP_QuadraticLimiter;
3797}
3798
3800 Coefficient &coeff,
3802 real_t delta_max)
3803{
3805 Array<Coefficient *> c_arr(1);
3806 Array<real_t> d_arr(1);
3807 z0_arr[0] = &z0;
3808 c_arr[0] = &coeff;
3809 d_arr[0] = delta_max;
3810 EnableAdaptiveLimiting(z0_arr, c_arr, ae, d_arr);
3811}
3812
3813#ifdef MFEM_USE_MPI
3815 Coefficient &coeff,
3817 real_t delta_max)
3818{
3820 Array<Coefficient *> c_arr(1);
3821 Array<real_t> d_arr(1);
3822 z0_arr[0] = &z0;
3823 c_arr[0] = &coeff;
3824 d_arr[0] = delta_max;
3825 EnableAdaptiveLimiting(z0_arr, c_arr, ae, d_arr);
3826}
3827#endif
3828
3831 const Array<Coefficient *> &coeff,
3832 AdaptivityEvaluator &ae, const Array<real_t> &delta_max)
3833{
3834 MFEM_VERIFY(z0.Size() > 0, "Requires at least one field.");
3835 MFEM_VERIFY(z0.Size() == coeff.Size(), "Requires one Coefficient per field.");
3836 MFEM_VERIFY(z0.Size() == delta_max.Size(), "Requires one delta_max per field.");
3837 for (int i = 0; i < delta_max.Size(); i++)
3838 {
3839 MFEM_VERIFY(delta_max[i] > 0.0, "Requires delta_max > 0.0.");
3840 }
3841
3842 // Verify compatibility of input fields.
3843 const FiniteElementSpace *sfes = z0[0]->FESpace();
3844 MFEM_VERIFY(sfes->GetVDim() == 1, "Expects scalar input GridFunctions.");
3845 const int ndofs = sfes->GetVSize();
3846 Mesh *mesh = sfes->GetMesh();
3847 MFEM_VERIFY(mesh->GetNodes(), "EnableAdaptiveLimiting requires mesh Nodes.");
3848 for (int i = 0; i < z0.Size(); i++)
3849 {
3850 MFEM_VERIFY(z0[i], "NULL GridFunction pointer.");
3851 const FiniteElementSpace *fes_i = z0[i]->FESpace();
3852 MFEM_VERIFY(fes_i->GetVDim() == 1, "Expects scalar input GridFunctions.");
3853 MFEM_VERIFY(fes_i->GetVSize() == ndofs,
3854 "All fields must be on the same FE space.");
3855 MFEM_VERIFY(fes_i->GetMesh() == mesh,
3856 "All fields must be on the same Mesh.");
3857 MFEM_VERIFY(coeff[i], "NULL Coefficient pointer.");
3858 }
3859
3860 // Delete previous adaptive limiting data.
3861 for (int i = 0; i < adapt_lim_gf.Size(); i++) { delete adapt_lim_gf[i]; }
3862 for (int i = 0; i < adapt_lim_gf0.Size(); i++) { delete adapt_lim_gf0[i]; }
3863
3864 adapt_lim_coeff.SetSize(coeff.Size());
3865 for (int i = 0; i < coeff.Size(); i++) { adapt_lim_coeff[i] = coeff[i]; }
3866 adapt_lim_eval = &ae;
3867 adapt_lim_delta_max = delta_max;
3868 adapt_lim_init_nodes = *mesh->GetNodes();
3869
3870 // Use one internal vector field (vdim = #fields) so remapping can be done in
3871 // one call and incremental remap state (when provided by the evaluator) is
3872 // preserved across TMOP iterations.
3873 //
3874 // Use Ordering::byNODES for the packed vector field so packing / unpacking
3875 // can be done with contiguous sub-vector copies (device-friendly).
3876 const int nal = z0.Size();
3877 const Ordering::Type packed_ord = Ordering::byNODES;
3878
3879 // Setup the evaluator.
3880#ifdef MFEM_USE_MPI
3881 if (auto pfes = dynamic_cast<const ParFiniteElementSpace *>(sfes))
3882 {
3883 auto *pm = pfes->GetParMesh();
3884 MFEM_VERIFY(pm, "Invalid ParMesh.");
3885 ParFiniteElementSpace vfes(pm, pfes->FEColl(), nal, packed_ord);
3886 adapt_lim_eval->SetParMetaInfo(*pm, vfes);
3887 }
3888 else
3889#endif
3890 {
3891 FiniteElementSpace vfes(mesh, sfes->FEColl(), nal, packed_ord);
3892 adapt_lim_eval->SetSerialMetaInfo(*mesh, vfes);
3893 }
3894
3895 // Copy the initial fields; remapped fields are initialized to the same data.
3896 adapt_lim_gf0.SetSize(z0.Size());
3897 adapt_lim_gf.SetSize(z0.Size());
3898 for (int i = 0; i < z0.Size(); i++)
3899 {
3900 adapt_lim_gf0[i] = new GridFunction(*z0[i]);
3901 adapt_lim_gf[i] = new GridFunction(*z0[i]);
3902 }
3903
3904 // Initialize the evaluator with the packed vector field.
3905 Vector init_field_vec;
3906 init_field_vec.SetSize(nal * ndofs, *adapt_lim_gf0[0]);
3907 init_field_vec.UseDevice(adapt_lim_gf0[0]->UseDevice());
3908 for (int c = 0; c < nal; c++)
3909 {
3910 init_field_vec.SetVector(*adapt_lim_gf0[c], c * ndofs);
3911 }
3913}
3914
3915#ifdef MFEM_USE_MPI
3918 const Array<Coefficient *> &coeff,
3919 AdaptivityEvaluator &ae, const Array<real_t> &delta_max)
3920{
3921 Array<const GridFunction *> z0_base(z0.Size());
3922 for (int i = 0; i < z0.Size(); i++) { z0_base[i] = z0[i]; }
3923 EnableAdaptiveLimiting(z0_base, coeff, ae, delta_max);
3924}
3925#endif
3926
3928 const Array<bool> &smarker,
3929 Coefficient &coeff,
3931{
3932 // To have both we must duplicate the markers.
3933 MFEM_VERIFY(surf_fit_pos == NULL,
3934 "Using both fitting approaches is not supported.");
3935
3936 const bool per = s0.FESpace()->IsDGSpace();
3937 MFEM_VERIFY(per == false, "Fitting is not supported for periodic meshes.");
3938
3939 const int dim = s0.FESpace()->GetMesh()->Dimension();
3940 Mesh *mesh = s0.FESpace()->GetMesh();
3941 MFEM_VERIFY(mesh->GetNodes()->Size() == dim*s0.Size(),
3942 "Mesh and level-set polynomial order must be the same.");
3943 const H1_FECollection *fec = dynamic_cast<const H1_FECollection *>
3944 (s0.FESpace()->FEColl());
3945 MFEM_VERIFY(fec, "Only H1_FECollection is supported for the surface fitting "
3946 "grid function.");
3947
3948 delete surf_fit_gf;
3949 surf_fit_gf = new GridFunction(s0);
3951 surf_fit_marker = &smarker;
3952 surf_fit_coeff = &coeff;
3953 surf_fit_eval = &ae;
3954
3956 *s0.FESpace());
3959}
3960
3962 const Array<bool> &smarker,
3963 Coefficient &coeff)
3964{
3965 // To have both we must duplicate the markers.
3966 MFEM_VERIFY(surf_fit_gf == NULL,
3967 "Using both fitting approaches is not supported.");
3968 MFEM_VERIFY(pos.FESpace()->GetMesh()->GetNodes(),
3969 "Positions on a mesh without Nodes is not supported.");
3970 MFEM_VERIFY(pos.FESpace()->GetOrdering() ==
3971 pos.FESpace()->GetMesh()->GetNodes()->FESpace()->GetOrdering(),
3972 "Incompatible ordering of spaces!");
3973
3974 const bool per = pos.FESpace()->IsDGSpace();
3975 MFEM_VERIFY(per == false, "Fitting is not supported for periodic meshes.");
3976
3977 surf_fit_pos = &pos;
3979 surf_fit_marker = &smarker;
3980 surf_fit_coeff = &coeff;
3981 delete surf_fit_limiter;
3983}
3984
3985#ifdef MFEM_USE_MPI
3987 const Array<bool> &smarker,
3988 Coefficient &coeff,
3990 AdaptivityEvaluator *aegrad,
3991 AdaptivityEvaluator *aehess)
3992{
3993 // To have both we must duplicate the markers.
3994 MFEM_VERIFY(surf_fit_pos == NULL,
3995 "Using both fitting approaches is not supported.");
3996
3997 const bool per = s0.FESpace()->IsDGSpace();
3998 MFEM_VERIFY(per == false, "Fitting is not supported for periodic meshes.");
3999
4000 const int dim = s0.FESpace()->GetMesh()->Dimension();
4001 ParMesh *pmesh = s0.ParFESpace()->GetParMesh();
4002 MFEM_VERIFY(pmesh->GetNodes()->Size() == dim*s0.Size(),
4003 "Mesh and level-set polynomial order must be the same.");
4004 const H1_FECollection *fec = dynamic_cast<const H1_FECollection *>
4005 (s0.FESpace()->FEColl());
4006 MFEM_VERIFY(fec, "Only H1_FECollection is supported for the surface fitting "
4007 "grid function.");
4008
4009
4010 delete surf_fit_gf;
4011 surf_fit_gf = new GridFunction(s0);
4013 surf_fit_marker = &smarker;
4014 surf_fit_coeff = &coeff;
4015 surf_fit_eval = &ae;
4016
4017 surf_fit_eval->SetParMetaInfo(*pmesh, *s0.ParFESpace());
4020
4021 if (!aegrad) { return; }
4022
4023 MFEM_VERIFY(aehess, "AdaptivityEvaluator for Hessians must be provided too.");
4024
4026
4027 // FE space for gradients.
4028 delete surf_fit_grad;
4029 H1_FECollection *fec_grad = new H1_FECollection(fec->GetOrder(), dim,
4030 fec->GetBasisType());
4031 ParFiniteElementSpace *fes_grad = new ParFiniteElementSpace(pmesh, fec_grad,
4032 dim);
4033 // Initial gradients.
4034 surf_fit_grad = new GridFunction(fes_grad);
4035 surf_fit_grad->MakeOwner(fec_grad);
4036 for (int d = 0; d < dim; d++)
4037 {
4038 ParGridFunction surf_fit_grad_comp(fes, surf_fit_grad->GetData()+d*s0.Size());
4039 s0.GetDerivative(1, d, surf_fit_grad_comp);
4040 }
4041 surf_fit_eval_grad = aegrad;
4042 surf_fit_eval_grad->SetParMetaInfo(*pmesh, *fes_grad);
4044
4045 // FE space for Hessians.
4046 delete surf_fit_hess;
4047 H1_FECollection *fec_hess = new H1_FECollection(fec->GetOrder(), dim,
4048 fec->GetBasisType());
4049 ParFiniteElementSpace *fes_hess = new ParFiniteElementSpace(pmesh, fec_hess,
4050 dim*dim);
4051 // Initial Hessians.
4052 surf_fit_hess = new GridFunction(fes_hess);
4053 surf_fit_hess->MakeOwner(fec_hess);
4054 int id = 0;
4055 for (int d = 0; d < dim; d++)
4056 {
4057 for (int idir = 0; idir < dim; idir++)
4058 {
4059 ParGridFunction surf_fit_grad_comp(fes,
4060 surf_fit_grad->GetData()+d*s0.Size());
4061 ParGridFunction surf_fit_hess_comp(fes,
4062 surf_fit_hess->GetData()+id*s0.Size());
4063 surf_fit_grad_comp.GetDerivative(1, idir, surf_fit_hess_comp);
4064 id++;
4065 }
4066 }
4067 surf_fit_eval_hess = aehess;
4068 surf_fit_eval_hess->SetParMetaInfo(*pmesh, *fes_hess);
4070
4071 // Store DOF indices that are marked for fitting. Used to reduce work for
4072 // transferring information between source/background and current mesh.
4074#ifdef MFEM_USE_GSLIB
4075 if (dynamic_cast<InterpolatorFP *>(surf_fit_eval) &&
4076 dynamic_cast<InterpolatorFP *>(surf_fit_eval_grad) &&
4077 dynamic_cast<InterpolatorFP *>(surf_fit_eval_hess))
4078 {
4079 for (int i = 0; i < surf_fit_marker->Size(); i++)
4080 {
4081 if ((*surf_fit_marker)[i] == true)
4082 {
4084 }
4085 }
4086 }
4087#endif
4088
4089 *surf_fit_grad = 0.0;
4090 *surf_fit_hess = 0.0;
4091}
4092
4094 const ParGridFunction &s_bg, ParGridFunction &s0,
4095 const Array<bool> &smarker, Coefficient &coeff, AdaptivityEvaluator &ae,
4096 const ParGridFunction &s_bg_grad,
4097 ParGridFunction &s0_grad, AdaptivityEvaluator &age,
4098 const ParGridFunction &s_bg_hess,
4099 ParGridFunction &s0_hess, AdaptivityEvaluator &ahe)
4100{
4101#ifndef MFEM_USE_GSLIB
4102 MFEM_ABORT("Surface fitting from source requires GSLIB!");
4103#endif
4104
4105 const bool per = s0.FESpace()->IsDGSpace();
4106 MFEM_VERIFY(per == false, "Fitting is not supported for periodic meshes.");
4107
4108 // Setup for level set function
4109 delete surf_fit_gf;
4110 surf_fit_gf = new GridFunction(s0);
4111 surf_fit_marker = &smarker;
4112 surf_fit_coeff = &coeff;
4113 surf_fit_eval = &ae;
4115 *s_bg.ParFESpace());
4117 (*s_bg.FESpace()->GetMesh()->GetNodes(), s_bg);
4121 nodes->FESpace()->GetOrdering());
4122
4123 // Setup for gradient on background mesh
4124 MFEM_VERIFY(s_bg_grad.ParFESpace()->GetOrdering() ==
4125 s0_grad.ParFESpace()->GetOrdering(),
4126 "Nodal ordering for grid function on source mesh and current mesh"
4127 "should be the same.");
4128 delete surf_fit_grad;
4129 surf_fit_grad = new GridFunction(s0_grad);
4130 *surf_fit_grad = 0.0;
4131 surf_fit_eval_grad = &age;
4133 *s_bg_grad.ParFESpace());
4135 (*s_bg_grad.FESpace()->GetMesh()->GetNodes(), s_bg_grad);
4137
4138 // Setup for Hessian on background mesh
4139 MFEM_VERIFY(s_bg_hess.ParFESpace()->GetOrdering() ==
4140 s0_hess.ParFESpace()->GetOrdering(),
4141 "Nodal ordering for grid function on source mesh and current mesh"
4142 "should be the same.");
4143 delete surf_fit_hess;
4144 surf_fit_hess = new GridFunction(s0_hess);
4145 *surf_fit_hess = 0.0;
4146 surf_fit_eval_hess = &ahe;
4148 *s_bg_hess.ParFESpace());
4150 (*s_bg_hess.FESpace()->GetMesh()->GetNodes(), s_bg_hess);
4152
4153 // Count number of zones that share each of the DOFs
4155 // Store DOF indices that are marked for fitting. Used to reduce work for
4156 // transferring information between source/background and current mesh.
4158 for (int i = 0; i < surf_fit_marker->Size(); i++)
4159 {
4160 if ((*surf_fit_marker)[i] == true)
4161 {
4163 }
4164 }
4165}
4166#endif
4167
4169 real_t &err_avg, real_t &err_max)
4170{
4171 MFEM_VERIFY(periodic == false,
4172 "Fitting is not supported for periodic meshes.");
4173
4174 Vector pos(d_loc.Size());
4175 if (x_0) { add(*x_0, d_loc, pos); }
4176 else { pos = d_loc; }
4177
4178 MFEM_VERIFY(surf_fit_marker, "Surface fitting has not been enabled.");
4179
4180 const FiniteElementSpace *fes =
4182#ifdef MFEM_USE_MPI
4183 auto pfes = dynamic_cast<const ParFiniteElementSpace *>(fes);
4184 bool parallel = (pfes) ? true : false;
4185#endif
4186
4187 int dim = fes->GetMesh()->Dimension();
4188 const int node_cnt = surf_fit_marker->Size();
4189 err_max = 0.0;
4190 int dof_cnt = 0;
4191 real_t err_sum = 0.0;
4192 for (int i = 0; i < node_cnt; i++)
4193 {
4194 if ((*surf_fit_marker)[i] == false) { continue; }
4195
4196#ifdef MFEM_USE_MPI
4197 // Don't count the overlapping DOFs in parallel.
4198 // The pfes might be ordered byVDIM, while the loop goes consecutively.
4199 if (parallel)
4200 {
4201 const int dof_i = pfes->DofToVDof(i, 0);
4202 if (pfes->GetLocalTDofNumber(dof_i) < 0) { continue; }
4203 }
4204#endif
4205
4206 dof_cnt++;
4207 real_t sigma_s = 0.0;
4208 if (surf_fit_gf) { sigma_s = fabs((*surf_fit_gf)(i)); }
4209 if (surf_fit_pos)
4210 {
4211 Vector pos_s(dim), pos_s_target(dim);
4212 for (int d = 0; d < dim; d++)
4213 {
4214 pos_s(d) = (fes->GetOrdering() == Ordering::byNODES) ?
4215 pos(d*node_cnt + i) : pos(i*dim + d);
4216 pos_s_target(d) = (fes->GetOrdering() == Ordering::byNODES)
4217 ? (*surf_fit_pos)(d*node_cnt + i)
4218 : (*surf_fit_pos)(i*dim + d);
4219 }
4220 sigma_s = pos_s.DistanceTo(pos_s_target);
4221 }
4222
4223 err_max = std::max(err_max, sigma_s);
4224 err_sum += sigma_s;
4225 }
4226
4227#ifdef MFEM_USE_MPI
4228 if (parallel)
4229 {
4230 MPI_Comm comm = pfes->GetComm();
4231 MPI_Allreduce(MPI_IN_PLACE, &err_max, 1, MPITypeMap<real_t>::mpi_type, MPI_MAX,
4232 comm);
4233 MPI_Allreduce(MPI_IN_PLACE, &dof_cnt, 1, MPI_INT, MPI_SUM, comm);
4234 MPI_Allreduce(MPI_IN_PLACE, &err_sum, 1, MPITypeMap<real_t>::mpi_type, MPI_SUM,
4235 comm);
4236 }
4237#endif
4238
4239 err_avg = (dof_cnt > 0) ? err_sum / dof_cnt : 0.0;
4240}
4241
4243{
4244 if (adapt_lim_gf.Size() > 0)
4245 {
4246 for (int i = 0; i < adapt_lim_gf0.Size(); i++) { adapt_lim_gf0[i]->Update(); }
4247 for (int i = 0; i < adapt_lim_gf.Size(); i++) { adapt_lim_gf[i]->Update(); }
4248
4249 Mesh *mesh = adapt_lim_gf[0]->FESpace()->GetMesh();
4250
4251 // Same setup as in EnableAdaptiveLimiting().
4252 const int nal = adapt_lim_coeff.Size();
4253 const Ordering::Type packed_ord = Ordering::byNODES;
4254 FiniteElementSpace vfes(mesh, adapt_lim_gf[0]->FESpace()->FEColl(), nal,
4255 packed_ord);
4256 adapt_lim_eval->SetSerialMetaInfo(*mesh, vfes);
4257
4258 adapt_lim_init_nodes = *mesh->GetNodes();
4259 const int ndofs = adapt_lim_gf0[0]->Size();
4260 Vector init_field_vec;
4261 init_field_vec.SetSize(nal * ndofs, *adapt_lim_gf0[0]);
4262 init_field_vec.UseDevice(adapt_lim_gf0[0]->UseDevice());
4263 for (int c = 0; c < nal; c++)
4264 {
4265 init_field_vec.SetVector(*adapt_lim_gf0[c], c * ndofs);
4266 }
4268 }
4269}
4270
4271#ifdef MFEM_USE_MPI
4273{
4274 if (adapt_lim_gf.Size() > 0)
4275 {
4276 for (int i = 0; i < adapt_lim_gf0.Size(); i++) { adapt_lim_gf0[i]->Update(); }
4277 for (int i = 0; i < adapt_lim_gf.Size(); i++) { adapt_lim_gf[i]->Update(); }
4278
4279 // Same setup as in EnableAdaptiveLimiting().
4280 auto *pfes = dynamic_cast<ParFiniteElementSpace *>(adapt_lim_gf[0]->FESpace());
4281 MFEM_VERIFY(pfes, "internal error");
4282 ParMesh *pmesh = pfes->GetParMesh();
4283
4284 const int nal = adapt_lim_coeff.Size();
4285 const Ordering::Type packed_ord = Ordering::byNODES;
4286 ParFiniteElementSpace vfes(pmesh, pfes->FEColl(), nal, packed_ord);
4287 adapt_lim_eval->SetParMetaInfo(*pmesh, vfes);
4288
4289 adapt_lim_init_nodes = *pmesh->GetNodes();
4290 const int ndofs = adapt_lim_gf0[0]->Size();
4291 Vector init_field_vec;
4292 init_field_vec.SetSize(nal * ndofs, *adapt_lim_gf0[0]);
4293 init_field_vec.UseDevice(adapt_lim_gf0[0]->UseDevice());
4294 for (int c = 0; c < nal; c++)
4295 {
4296 init_field_vec.SetVector(*adapt_lim_gf0[c], c * ndofs);
4297 }
4299 }
4300}
4301#endif
4302
4305 const Vector &d_el)
4306{
4307 const int dof = el.GetDof(), dim = el.GetDim();
4308 const int el_id = T.ElementNo;
4309
4310 // Form the Vector of node positions, depending on what's the input.
4311 Vector elfun;
4312 if (x_0)
4313 {
4314 // The input is the displacement.
4315 x_0->GetElementDofValues(el_id, elfun);
4316 if (periodic)
4317 {
4318 auto n_el = dynamic_cast<const NodalFiniteElement *>(&el);
4319 n_el->ReorderLexToNative(dim, elfun);
4320 }
4321 elfun += d_el;
4322 }
4323 else { elfun = d_el; }
4324
4325 real_t energy;
4326
4327 // No adaptive limiting / surface fitting terms if the function is called
4328 // as part of a FD derivative computation (because we include the exact
4329 // derivatives of these terms in FD computations).
4330 const bool adaptive_limiting = (adapt_lim_gf.Size() > 0 &&
4331 fd_call_flag == false);
4332 const bool surface_fit = (surf_fit_marker && fd_call_flag == false);
4333
4334 DSh.SetSize(dof, dim);
4335 Jrt.SetSize(dim);
4336 Jpr.SetSize(dim);
4337 Jpt.SetSize(dim);
4338 PMatI.UseExternalData(elfun.GetData(), dof, dim);
4339
4341
4342 energy = 0.0;
4344 targetC->ComputeElementTargets(el_id, el, ir, elfun, Jtr);
4345
4346 // Limited case.
4347 Vector shape, p, p0, d_vals;
4348 DenseMatrix pos0;
4349 if (lim_coeff)
4350 {
4351 shape.SetSize(dof);
4352 p.SetSize(dim);
4353 p0.SetSize(dim);
4354 pos0.SetSize(dof, dim);
4355 Vector pos0V(pos0.Data(), dof * dim);
4356 Array<int> pos_dofs;
4357 lim_nodes0->FESpace()->GetElementVDofs(el_id, pos_dofs);
4358 lim_nodes0->GetSubVector(pos_dofs, pos0V);
4359 if (periodic)
4360 {
4361 auto n_el = dynamic_cast<const NodalFiniteElement *>(&el);
4362 n_el->ReorderLexToNative(dim, pos0V);
4363 }
4364 if (lim_dist)
4365 {
4366 lim_dist->GetValues(el_id, ir, d_vals);
4367 }
4368 else
4369 {
4370 d_vals.SetSize(ir.GetNPoints()); d_vals = 1.0;
4371 }
4372 }
4373
4374 // Define ref->physical transformation, when a Coefficient is specified.
4375 IsoparametricTransformation *Tpr = NULL;
4376 if (metric_coeff || lim_coeff || adaptive_limiting || surface_fit)
4377 {
4379 Tpr->SetFE(&el);
4380 Tpr->ElementNo = el_id;
4382 Tpr->Attribute = T.Attribute;
4383 Tpr->mesh = T.mesh;
4384 Tpr->GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
4385 }
4386 // TODO: computing the coefficients 'metric_coeff' and 'lim_coeff' in physical
4387 // coordinates means that, generally, the gradient and Hessian of the
4388 // TMOP_Integrator will depend on the derivatives of the coefficients.
4389 //
4390 // In some cases the coefficients are independent of any movement of
4391 // the physical coordinates (i.e. changes in 'elfun'), e.g. when the
4392 // coefficient is a ConstantCoefficient or a GridFunctionCoefficient.
4393
4394 const int nal = adapt_lim_coeff.Size();
4395 const int nqp = ir.GetNPoints();
4396 Vector adapt_lim_gf_q, adapt_lim_gf0_q;
4397 if (adaptive_limiting)
4398 {
4399 adapt_lim_gf_q.SetSize(nal * nqp);
4400 adapt_lim_gf0_q.SetSize(nal * nqp);
4401 Vector zc, z0c;
4402 for (int c = 0; c < nal; c++)
4403 {
4404 zc.MakeRef(adapt_lim_gf_q, c * nqp, nqp);
4405 z0c.MakeRef(adapt_lim_gf0_q, c * nqp, nqp);
4406 adapt_lim_gf[c]->GetValues(el_id, ir, zc);
4407 adapt_lim_gf0[c]->GetValues(el_id, ir, z0c);
4408 }
4409 }
4410
4411 for (int i = 0; i < ir.GetNPoints(); i++)
4412 {
4413 const IntegrationPoint &ip = ir.IntPoint(i);
4414
4416 CalcInverse(Jtr(i), Jrt);
4417 const real_t weight =
4418 (integ_over_target) ? ip.weight * Jtr(i).Det() : ip.weight;
4419
4420 el.CalcDShape(ip, DSh);
4421 MultAtB(PMatI, DSh, Jpr);
4422 Mult(Jpr, Jrt, Jpt);
4423
4425 if (metric_coeff) { val *= metric_coeff->Eval(*Tpr, ip); }
4426
4427 if (lim_coeff)
4428 {
4429 el.CalcShape(ip, shape);
4430 PMatI.MultTranspose(shape, p);
4431 pos0.MultTranspose(shape, p0);
4432 val += lim_normal *
4433 lim_func->Eval(p, p0, d_vals(i)) *
4434 lim_coeff->Eval(*Tpr, ip);
4435 }
4436
4437 // Contribution from the adaptive limiting term.
4438 if (adaptive_limiting)
4439 {
4440 for (int c = 0; c < nal; c++)
4441 {
4442 const int idx = c * nqp + i;
4443 const real_t diff = (adapt_lim_gf_q(idx) - adapt_lim_gf0_q(idx)) /
4445 val += adapt_lim_coeff[c]->Eval(*Tpr, ip) * lim_normal * diff * diff;
4446 }
4447 }
4448
4449 energy += weight * val;
4450 }
4451
4452 // Contribution from the surface fitting term.
4453 if (surface_fit)
4454 {
4455 // Scalar for surf_fit_gf, vector for surf_fit_pos, but that's ok.
4456 const FiniteElementSpace *fes_fit =
4458 const IntegrationRule *ir_s = &fes_fit->GetFE(el_id)->GetNodes();
4459 Array<int> vdofs;
4460 fes_fit->GetElementVDofs(el_id, vdofs);
4461
4462 Vector sigma_e(dof);
4463 if (surf_fit_gf) { surf_fit_gf->GetSubVector(vdofs, sigma_e); }
4464
4465 for (int s = 0; s < dof; s++)
4466 {
4467 // Because surf_fit_pos.fes might be ordered byVDIM.
4468 const int scalar_dof_id = fes_fit->VDofToDof(vdofs[s]);
4469 if ((*surf_fit_marker)[scalar_dof_id] == false) { continue; }
4470
4471 const IntegrationPoint &ip_s = ir_s->IntPoint(s);
4472 Tpr->SetIntPoint(&ip_s);
4473 real_t w = surf_fit_coeff->Eval(*Tpr, ip_s) * surf_fit_normal *
4474 1.0 / surf_fit_dof_count[scalar_dof_id];
4475
4476 if (surf_fit_gf)
4477 {
4478 energy += w * sigma_e(s) * sigma_e(s);
4479 }
4480 if (surf_fit_pos)
4481 {
4482 // Fitting to exact positions.
4483 Vector pos(dim), pos_target(dim);
4484 for (int d = 0; d < dim; d++)
4485 {
4486 pos(d) = PMatI(s, d);
4487 pos_target(d) = (*surf_fit_pos)(vdofs[d*dof + s]);
4488 }
4489 energy += w * surf_fit_limiter->Eval(pos, pos_target, 1.0);
4490 }
4491 }
4492 }
4493
4494 delete Tpr;
4495 return energy;
4496}
4497
4500 const Vector &elfun,
4501 const IntegrationRule &irule)
4502{
4503 int dof = el.GetDof(), dim = el.GetDim(),
4504 NEsplit = elfun.Size() / (dof*dim), el_id = T.ElementNo;
4505 real_t energy = 0.;
4506
4507 TargetConstructor *tc = const_cast<TargetConstructor *>(targetC);
4508 DiscreteAdaptTC *dtc = dynamic_cast<DiscreteAdaptTC *>(tc);
4509 // For DiscreteAdaptTC the GridFunctions used to set the targets must be
4510 // mapped onto the fine elements.
4511 if (dtc) { dtc->SetTspecFromIntRule(el_id, irule); }
4512
4513 for (int e = 0; e < NEsplit; e++)
4514 {
4515 DSh.SetSize(dof, dim);
4516 Jrt.SetSize(dim);
4517 Jpr.SetSize(dim);
4518 Jpt.SetSize(dim);
4519 Vector elfun_child(dof*dim);
4520 for (int i = 0; i < dof; i++)
4521 {
4522 for (int d = 0; d < dim; d++)
4523 {
4524 // elfun is (xe1,xe2,...xen,ye1,ye2...yen) and has nodal coordinates
4525 // for all the children element of the parent element being considered.
4526 // So we must index and get (xek, yek) i.e. nodal coordinates for
4527 // the fine element being considered.
4528 elfun_child(i + d*dof) = elfun(i + e*dof + d*dof*NEsplit);
4529 }
4530 }
4531 PMatI.UseExternalData(elfun_child.GetData(), dof, dim);
4532
4534
4535 real_t el_energy = 0;
4537 if (dtc)
4538 {
4539 // This is used to index into the tspec vector inside DiscreteAdaptTC.
4541 }
4542 targetC->ComputeElementTargets(el_id, el, ir, elfun_child, Jtr);
4543
4544 // Define ref->physical transformation, wn a Coefficient is specified.
4545 IsoparametricTransformation *Tpr = NULL;
4546 if (metric_coeff || lim_coeff)
4547 {
4549 Tpr->SetFE(&el);
4550 Tpr->ElementNo = T.ElementNo;
4552 Tpr->Attribute = T.Attribute;
4553 Tpr->mesh = T.mesh;
4554 Tpr->GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
4555 }
4556
4557 for (int i = 0; i < ir.GetNPoints(); i++)
4558 {
4559 const IntegrationPoint &ip = ir.IntPoint(i);
4561 CalcInverse(Jtr(i), Jrt);
4562 const real_t weight =
4563 (integ_over_target) ? ip.weight * Jtr(i).Det() : ip.weight;
4564
4565 el.CalcDShape(ip, DSh);
4566 MultAtB(PMatI, DSh, Jpr);
4567 Mult(Jpr, Jrt, Jpt);
4568
4570 if (metric_coeff) { val *= metric_coeff->Eval(*Tpr, ip); }
4571
4572 el_energy += weight * val;
4573 delete Tpr;
4574 }
4575 energy += el_energy;
4576 }
4577 energy /= NEsplit;
4578
4579 if (dtc) { dtc->ResetRefinementTspecData(); }
4580
4581 return energy;
4582}
4583
4586 const Vector &elfun)
4587{
4588 int dof = el.GetDof(), dim = el.GetDim();
4589 real_t energy = 0.;
4590
4591 DSh.SetSize(dof, dim);
4592 Jrt.SetSize(dim);
4593 Jpr.SetSize(dim);
4594 Jpt.SetSize(dim);
4595 PMatI.UseExternalData(elfun.GetData(), dof, dim);
4596
4598
4599 energy = 0.0;
4601 targetC->ComputeElementTargets(T.ElementNo, el, ir, elfun, Jtr);
4602
4603 // Define ref->physical transformation, wn a Coefficient is specified.
4604 IsoparametricTransformation *Tpr = NULL;
4605 if (metric_coeff)
4606 {
4608 Tpr->SetFE(&el);
4609 Tpr->ElementNo = T.ElementNo;
4611 Tpr->Attribute = T.Attribute;
4612 Tpr->mesh = T.mesh;
4613 Tpr->GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
4614 }
4615
4616 for (int i = 0; i < ir.GetNPoints(); i++)
4617 {
4618 const IntegrationPoint &ip = ir.IntPoint(i);
4620 CalcInverse(Jtr(i), Jrt);
4621 const real_t weight =
4622 (integ_over_target) ? ip.weight * Jtr(i).Det() : ip.weight;
4623
4624 el.CalcDShape(ip, DSh);
4625 MultAtB(PMatI, DSh, Jpr);
4626 Mult(Jpr, Jrt, Jpt);
4627
4629 if (metric_coeff) { val *= metric_coeff->Eval(*Tpr, ip); }
4630
4631 energy += weight * val;
4632 }
4633
4634 delete Tpr;
4635 return energy;
4636}
4637
4640 const Vector &d_el, Vector &elvect)
4641{
4642 if (!fdflag)
4643 {
4644 AssembleElementVectorExact(el, T, d_el, elvect);
4645 }
4646 else
4647 {
4648 AssembleElementVectorFD(el, T, d_el, elvect);
4649 }
4650}
4651
4654 const Vector &d_el,
4655 DenseMatrix &elmat)
4656{
4657 if (!fdflag)
4658 {
4659 AssembleElementGradExact(el, T, d_el, elmat);
4660 }
4661 else
4662 {
4663 AssembleElementGradFD(el, T, d_el, elmat);
4664 }
4665}
4666
4669 const Vector &d_el,
4670 Vector &elvect)
4671{
4672 const int dof = el.GetDof(), dim = el.GetDim();
4673 const int el_id = T.ElementNo;
4674
4675 // Form the Vector of node positions, depending on what's the input.
4676 Vector elfun;
4677 if (x_0)
4678 {
4679 // The input is the displacement.
4680 x_0->GetElementDofValues(el_id, elfun);
4681 if (periodic)
4682 {
4683 auto n_el = dynamic_cast<const NodalFiniteElement *>(&el);
4684 n_el->ReorderLexToNative(dim, elfun);
4685 }
4686 elfun += d_el;
4687 }
4688 else { elfun = d_el; }
4689
4690 DenseMatrix Amat(dim), work1(dim), work2(dim);
4691 DSh.SetSize(dof, dim);
4692 DS.SetSize(dof, dim);
4693 Jrt.SetSize(dim);
4694 Jpt.SetSize(dim);
4695 P.SetSize(dim);
4696 PMatI.UseExternalData(elfun.GetData(), dof, dim);
4697 elvect.SetSize(dof*dim);
4698 PMatO.UseExternalData(elvect.GetData(), dof, dim);
4699
4701 const int nqp = ir.GetNPoints();
4702
4703 elvect = 0.0;
4704 Vector weights(nqp);
4705 DenseTensor Jtr(dim, dim, nqp);
4706 DenseTensor dJtr(dim, dim, dim*nqp);
4707 targetC->ComputeElementTargets(el_id, el, ir, elfun, Jtr);
4708
4709 // Limited case.
4710 DenseMatrix pos0;
4711 Vector shape, p, p0, d_vals, grad;
4712 shape.SetSize(dof);
4713 if (lim_coeff)
4714 {
4715 p.SetSize(dim);
4716 p0.SetSize(dim);
4717 pos0.SetSize(dof, dim);
4718 Vector pos0V(pos0.Data(), dof * dim);
4719 Array<int> pos_dofs;
4720 lim_nodes0->FESpace()->GetElementVDofs(el_id, pos_dofs);
4721 lim_nodes0->GetSubVector(pos_dofs, pos0V);
4722 if (periodic)
4723 {
4724 auto n_el = dynamic_cast<const NodalFiniteElement *>(&el);
4725 n_el->ReorderLexToNative(dim, pos0V);
4726 }
4727 if (lim_dist)
4728 {
4729 lim_dist->GetValues(el_id, ir, d_vals);
4730 }
4731 else
4732 {
4733 d_vals.SetSize(nqp); d_vals = 1.0;
4734 }
4735 }
4736
4737 // Define ref->physical transformation, when a Coefficient is specified.
4738 IsoparametricTransformation *Tpr = NULL;
4739 if (metric_coeff || lim_coeff || adapt_lim_gf.Size() > 0 ||
4741 {
4743 Tpr->SetFE(&el);
4744 Tpr->ElementNo = el_id;
4746 Tpr->Attribute = T.Attribute;
4747 Tpr->mesh = T.mesh;
4748 Tpr->GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
4749 if (exact_action)
4750 {
4751 targetC->ComputeElementTargetsGradient(ir, elfun, *Tpr, dJtr);
4752 }
4753 }
4754
4755 Vector d_detW_dx(dim);
4756 Vector d_Winv_dx(dim);
4757
4758 for (int q = 0; q < nqp; q++)
4759 {
4760 const IntegrationPoint &ip = ir.IntPoint(q);
4762 CalcInverse(Jtr(q), Jrt);
4763 weights(q) = (integ_over_target) ? ip.weight * Jtr(q).Det() : ip.weight;
4764 real_t weight_m = weights(q) * metric_normal;
4765
4766 el.CalcDShape(ip, DSh);
4767 Mult(DSh, Jrt, DS);
4768 MultAtB(PMatI, DS, Jpt);
4769
4770 metric->EvalP(Jpt, P);
4771
4772 if (metric_coeff) { weight_m *= metric_coeff->Eval(*Tpr, ip); }
4773 P *= weight_m;
4774 AddMultABt(DS, P, PMatO); // w_q det(W) dmu/dx : dA/dx Winv
4775
4776 if (exact_action)
4777 {
4778 el.CalcShape(ip, shape);
4779 // Derivatives of adaptivity-based targets.
4780 // First term: w_q d*(Det W)/dx * mu(T)
4781 // d(Det W)/dx = det(W)*Tr[Winv*dW/dx]
4782 DenseMatrix dwdx(dim);
4783 for (int d = 0; d < dim; d++)
4784 {
4785 const DenseMatrix &dJtr_q = dJtr(q + d * nqp);
4786 Mult(Jrt, dJtr_q, dwdx);
4787 d_detW_dx(d) = dwdx.Trace();
4788 }
4789 d_detW_dx *= weight_m*metric->EvalW(Jpt); // *[w_q*det(W)]*mu(T)
4790
4791 // Second term: w_q det(W) dmu/dx : AdWinv/dx
4792 // dWinv/dx = -Winv*dW/dx*Winv
4793 MultAtB(PMatI, DSh, Amat);
4794 for (int d = 0; d < dim; d++)
4795 {
4796 const DenseMatrix &dJtr_q = dJtr(q + d*nqp);
4797 Mult(Jrt, dJtr_q, work1); // Winv*dw/dx
4798 Mult(work1, Jrt, work2); // Winv*dw/dx*Winv
4799 Mult(Amat, work2, work1); // A*Winv*dw/dx*Winv
4800 MultAtB(P, work1, work2); // dmu/dT^T*A*Winv*dw/dx*Winv
4801 d_Winv_dx(d) = work2.Trace(); // Tr[dmu/dT : AWinv*dw/dx*Winv]
4802 }
4803 d_Winv_dx *= -weight_m; // Include (-) factor as well
4804 d_detW_dx += d_Winv_dx;
4805
4806 AddMultVWt(shape, d_detW_dx, PMatO);
4807
4808 // For mu(T,W) we also need w_q dmu/dW:dW/dx det(W)
4809 // dmu/dW:dW/dx_i
4810 DenseMatrix PW(dim);
4811 Vector dmudxw(dim);
4812 metric->EvalPW(Jpt, PW);
4813 DenseMatrix Prod(dim);
4814
4815 for (int d = 0; d < dim; d++)
4816 {
4817 const DenseMatrix &dJtr_q = dJtr(q + d*nqp);
4818 Prod = 0.0;
4819 MultAtB(PW, dJtr_q, Prod); // dmu/dW:dW/dx_i
4820 dmudxw(d) = Prod.Trace();
4821 }
4822 dmudxw *= weight_m;
4823 AddMultVWt(shape, dmudxw, PMatO);
4824 }
4825
4826 if (lim_coeff)
4827 {
4828 if (!exact_action) { el.CalcShape(ip, shape); }
4829 PMatI.MultTranspose(shape, p);
4830 pos0.MultTranspose(shape, p0);
4831 lim_func->Eval_d1(p, p0, d_vals(q), grad);
4832 grad *= weights(q) * lim_normal * lim_coeff->Eval(*Tpr, ip);
4833 AddMultVWt(shape, grad, PMatO);
4834 }
4835 }
4836
4837 if (adapt_lim_gf.Size() > 0) { AssembleElemVecAdaptLim(el, *Tpr, ir, weights, PMatO); }
4839
4840 delete Tpr;
4841}
4842
4845 const Vector &d_el,
4846 DenseMatrix &elmat)
4847{
4848 const int dof = el.GetDof(), dim = el.GetDim();
4849 const int el_id = T.ElementNo;
4850
4851 // Form the Vector of node positions, depending on what's the input.
4852 Vector elfun;
4853 if (x_0)
4854 {
4855 // The input is the displacement.
4856 x_0->GetElementDofValues(el_id, elfun);
4857 if (periodic)
4858 {
4859 auto n_el = dynamic_cast<const NodalFiniteElement *>(&el);
4860 n_el->ReorderLexToNative(dim, elfun);
4861 }
4862 elfun += d_el;
4863 }
4864 else { elfun = d_el; }
4865
4866 DSh.SetSize(dof, dim);
4867 DS.SetSize(dof, dim);
4868 Jrt.SetSize(dim);
4869 Jpt.SetSize(dim);
4870 PMatI.UseExternalData(elfun.GetData(), dof, dim);
4871 elmat.SetSize(dof*dim);
4872
4874 const int nqp = ir.GetNPoints();
4875
4876 elmat = 0.0;
4877 Vector weights(nqp);
4878 DenseTensor Jtr(dim, dim, nqp);
4879 targetC->ComputeElementTargets(el_id, el, ir, elfun, Jtr);
4880
4881 // Limited case.
4882 DenseMatrix pos0, hess;
4883 Vector shape, p, p0, d_vals;
4884 if (lim_coeff)
4885 {
4886 shape.SetSize(dof);
4887 p.SetSize(dim);
4888 p0.SetSize(dim);
4889 pos0.SetSize(dof, dim);
4890 Vector pos0V(pos0.Data(), dof * dim);
4891 Array<int> pos_dofs;
4892 lim_nodes0->FESpace()->GetElementVDofs(el_id, pos_dofs);
4893 lim_nodes0->GetSubVector(pos_dofs, pos0V);
4894 if (periodic)
4895 {
4896 auto n_el = dynamic_cast<const NodalFiniteElement *>(&el);
4897 n_el->ReorderLexToNative(dim, pos0V);
4898 }
4899 if (lim_dist)
4900 {
4901 lim_dist->GetValues(el_id, ir, d_vals);
4902 }
4903 else
4904 {
4905 d_vals.SetSize(nqp); d_vals = 1.0;
4906 }
4907 }
4908
4909 // Define ref->physical transformation, when a Coefficient is specified.
4910 IsoparametricTransformation *Tpr = NULL;
4911 if (metric_coeff || lim_coeff || adapt_lim_gf.Size() > 0 ||
4913 {
4915 Tpr->SetFE(&el);
4916 Tpr->ElementNo = T.ElementNo;
4918 Tpr->Attribute = T.Attribute;
4919 Tpr->mesh = T.mesh;
4920 Tpr->GetPointMat().Transpose(PMatI);
4921 }
4922
4923 for (int q = 0; q < nqp; q++)
4924 {
4925 const IntegrationPoint &ip = ir.IntPoint(q);
4926 const DenseMatrix &Jtr_q = Jtr(q);
4927 metric->SetTargetJacobian(Jtr_q);
4928 CalcInverse(Jtr_q, Jrt);
4929 weights(q) = (integ_over_target) ? ip.weight * Jtr_q.Det() : ip.weight;
4930 real_t weight_m = weights(q) * metric_normal;
4931
4932 el.CalcDShape(ip, DSh);
4933 Mult(DSh, Jrt, DS);
4934 MultAtB(PMatI, DS, Jpt);
4935
4936 if (metric_coeff) { weight_m *= metric_coeff->Eval(*Tpr, ip); }
4937
4938 metric->AssembleH(Jpt, DS, weight_m, elmat);
4939
4940 // TODO: derivatives of adaptivity-based targets.
4941
4942 if (lim_coeff)
4943 {
4944 el.CalcShape(ip, shape);
4945 PMatI.MultTranspose(shape, p);
4946 pos0.MultTranspose(shape, p0);
4947 weight_m = weights(q) * lim_normal * lim_coeff->Eval(*Tpr, ip);
4948 lim_func->Eval_d2(p, p0, d_vals(q), hess);
4949 for (int i = 0; i < dof; i++)
4950 {
4951 const real_t w_shape_i = weight_m * shape(i);
4952 for (int j = 0; j < dof; j++)
4953 {
4954 const real_t w = w_shape_i * shape(j);
4955 for (int d1 = 0; d1 < dim; d1++)
4956 {
4957 for (int d2 = 0; d2 < dim; d2++)
4958 {
4959 elmat(d1*dof + i, d2*dof + j) += w * hess(d1, d2);
4960 }
4961 }
4962 }
4963 }
4964 }
4965 }
4966
4967 if (adapt_lim_gf.Size() > 0) { AssembleElemGradAdaptLim(el, *Tpr, ir, weights, elmat); }
4968 if (surf_fit_gf || surf_fit_pos) { AssembleElemGradSurfFit(el, *Tpr, elmat);}
4969
4970 delete Tpr;
4971}
4972
4975 const IntegrationRule &ir,
4976 const Vector &weights,
4977 DenseMatrix &mat)
4978{
4979 const int dof = el.GetDof(), dim = el.GetDim(), nqp = weights.Size();
4980 const int nal = adapt_lim_coeff.Size();
4981
4982 Vector shape(dof), adapt_lim_gf_e, adapt_lim_gf_q(nqp), adapt_lim_gf0_q(nqp);
4983 Array<int> dofs;
4984 adapt_lim_gf[0]->FESpace()->GetElementDofs(Tpr.ElementNo, dofs);
4985
4986 // Project the gradient of adapt_lim_gf in the same space.
4987 // The FE coefficients of the gradient go in adapt_lim_gf_grad_e.
4988 DenseMatrix grad_phys; // This will be (dof x dim, dof).
4989 el.ProjectGrad(el, Tpr, grad_phys);
4990
4991 Vector adapt_lim_gf_grad_q(dim);
4992 for (int c = 0; c < nal; c++)
4993 {
4994 const real_t delta2 = adapt_lim_delta_max[c] * adapt_lim_delta_max[c];
4995 adapt_lim_gf[c]->GetSubVector(dofs, adapt_lim_gf_e);
4996 adapt_lim_gf[c]->GetValues(Tpr.ElementNo, ir, adapt_lim_gf_q);
4997 adapt_lim_gf0[c]->GetValues(Tpr.ElementNo, ir, adapt_lim_gf0_q);
4998
4999 DenseMatrix adapt_lim_gf_grad_e(dof, dim);
5000 Vector grad_ptr(adapt_lim_gf_grad_e.GetData(), dof*dim);
5001 grad_phys.Mult(adapt_lim_gf_e, grad_ptr);
5002
5003 for (int q = 0; q < nqp; q++)
5004 {
5005 const IntegrationPoint &ip = ir.IntPoint(q);
5006 el.CalcShape(ip, shape);
5007
5008 adapt_lim_gf_grad_e.MultTranspose(shape, adapt_lim_gf_grad_q);
5009 adapt_lim_gf_grad_q *= 2.0 * (adapt_lim_gf_q(q) - adapt_lim_gf0_q(q)) /
5010 delta2;
5011 adapt_lim_gf_grad_q *=
5012 weights(q) * lim_normal * adapt_lim_coeff[c]->Eval(Tpr, ip);
5013
5014 AddMultVWt(shape, adapt_lim_gf_grad_q, mat);
5015 }
5016 }
5017}
5018
5021 const IntegrationRule &ir,
5022 const Vector &weights,
5023 DenseMatrix &mat)
5024{
5025 const int dof = el.GetDof(), dim = el.GetDim(), nqp = weights.Size();
5026 const int nal = adapt_lim_coeff.Size();
5027
5028 Vector shape(dof), adapt_lim_gf_e, adapt_lim_gf_q(nqp), adapt_lim_gf0_q(nqp);
5029 Array<int> dofs;
5030 adapt_lim_gf[0]->FESpace()->GetElementDofs(Tpr.ElementNo, dofs);
5031
5032 // Project the gradient of adapt_lim_gf in the same space.
5033 // The FE coefficients of the gradient go in adapt_lim_gf_grad_e.
5034 DenseMatrix grad_phys; // This will be (dof x dim, dof).
5035 el.ProjectGrad(el, Tpr, grad_phys);
5036 Vector adapt_lim_gf_grad_q(dim);
5037 DenseMatrix adapt_lim_gf_hess_q(dim, dim);
5038
5039 for (int c = 0; c < nal; c++)
5040 {
5041 const real_t delta2 = adapt_lim_delta_max[c] * adapt_lim_delta_max[c];
5042 adapt_lim_gf[c]->GetSubVector(dofs, adapt_lim_gf_e);
5043 adapt_lim_gf[c]->GetValues(Tpr.ElementNo, ir, adapt_lim_gf_q);
5044 adapt_lim_gf0[c]->GetValues(Tpr.ElementNo, ir, adapt_lim_gf0_q);
5045
5046 DenseMatrix adapt_lim_gf_grad_e(dof, dim);
5047 Vector grad_ptr(adapt_lim_gf_grad_e.GetData(), dof*dim);
5048 grad_phys.Mult(adapt_lim_gf_e, grad_ptr);
5049
5050 // Project the gradient of each gradient of adapt_lim_gf in the same space.
5051 // The FE coefficients of the second derivatives go in adapt_lim_gf_hess_e.
5052 DenseMatrix adapt_lim_gf_hess_e(dof*dim, dim);
5053 Mult(grad_phys, adapt_lim_gf_grad_e, adapt_lim_gf_hess_e);
5054 // Reshape to be more convenient later (no change in the data).
5055 adapt_lim_gf_hess_e.SetSize(dof, dim*dim);
5056
5057 for (int q = 0; q < nqp; q++)
5058 {
5059 const IntegrationPoint &ip = ir.IntPoint(q);
5060 el.CalcShape(ip, shape);
5061
5062 adapt_lim_gf_grad_e.MultTranspose(shape, adapt_lim_gf_grad_q);
5063 Vector gg_ptr(adapt_lim_gf_hess_q.GetData(), dim*dim);
5064 adapt_lim_gf_hess_e.MultTranspose(shape, gg_ptr);
5065
5066 const real_t coeff_q = adapt_lim_coeff[c]->Eval(Tpr, ip);
5067 const real_t factor =
5068 weights(q) * lim_normal * coeff_q * 2.0 /
5069 delta2;
5070
5071 for (int i = 0; i < dof * dim; i++)
5072 {
5073 const int idof = i % dof, idim = i / dof;
5074 for (int j = 0; j <= i; j++)
5075 {
5076 const int jdof = j % dof, jdim = j / dof;
5077 const real_t entry =
5078 factor *
5079 (adapt_lim_gf_grad_q(idim) * shape(idof) *
5080 adapt_lim_gf_grad_q(jdim) * shape(jdof) +
5081 (adapt_lim_gf_q(q) - adapt_lim_gf0_q(q)) *
5082 adapt_lim_gf_hess_q(idim, jdim) * shape(idof) * shape(jdof));
5083 mat(i, j) += entry;
5084 if (i != j) { mat(j, i) += entry; }
5085 }
5086 }
5087 }
5088 }
5089}
5090
5093 DenseMatrix &mat)
5094{
5095 const int el_id = Tpr.ElementNo;
5096
5097 // Scalar for surf_fit_gf, vector for surf_fit_pos, but that's ok.
5098 const FiniteElementSpace *fes_fit =
5100 const FiniteElement &el_s = *fes_fit->GetFE(el_id);
5101 const int dof_s = el_s.GetDof(), dim = el_x.GetDim();
5102
5103 // Check if the element has any DOFs marked for surface fitting.
5104 Array<int> dofs, vdofs;
5105 fes_fit->GetElementVDofs(el_id, vdofs);
5106 int count = 0;
5107 for (int s = 0; s < dof_s; s++)
5108 {
5109 // Because surf_fit_pos.fes might be ordered byVDIM.
5110 const int scalar_dof_id = fes_fit->VDofToDof(vdofs[s]);
5111 count += ((*surf_fit_marker)[scalar_dof_id]) ? 1 : 0;
5112 }
5113 if (count == 0) { return; }
5114
5115 Vector sigma_e(dof_s);
5116 DenseMatrix surf_fit_grad_e(dof_s, dim);
5117 if (surf_fit_gf)
5118 {
5119 surf_fit_gf->GetSubVector(vdofs, sigma_e);
5120
5121 // Project the gradient of sigma in the same space.
5122 // The FE coefficients of the gradient go in surf_fit_grad_e.
5123 Vector grad_ptr(surf_fit_grad_e.GetData(), dof_s * dim);
5124 DenseMatrix grad_phys; // This will be (dof x dim, dof).
5125 if (surf_fit_grad)
5126 {
5127 surf_fit_grad->FESpace()->GetElementVDofs(el_id, dofs);
5128 surf_fit_grad->GetSubVector(dofs, grad_ptr);
5129 }
5130 else
5131 {
5132 el_s.ProjectGrad(el_s, Tpr, grad_phys);
5133 grad_phys.Mult(sigma_e, grad_ptr);
5134 }
5135 }
5136 else { Tpr.GetPointMat().Transpose(PMatI); }
5137
5138 const IntegrationRule &ir = el_s.GetNodes();
5139
5140 for (int s = 0; s < dof_s; s++)
5141 {
5142 // Because surf_fit_pos.fes might be ordered byVDIM.
5143 const int scalar_dof_id = fes_fit->VDofToDof(vdofs[s]);
5144 if ((*surf_fit_marker)[scalar_dof_id] == false) { continue; }
5145
5146 const IntegrationPoint &ip = ir.IntPoint(s);
5147 Tpr.SetIntPoint(&ip);
5148 real_t w = surf_fit_normal * surf_fit_coeff->Eval(Tpr, ip) *
5149 1.0 / surf_fit_dof_count[vdofs[s]];
5150
5151 if (surf_fit_gf) { w *= 2.0 * sigma_e(s); }
5152 if (surf_fit_pos)
5153 {
5154 Vector pos(dim), pos_target(dim);
5155 for (int d = 0; d < dim; d++)
5156 {
5157 pos(d) = PMatI(s, d);
5158 pos_target(d) = (*surf_fit_pos)(vdofs[d*dof_s + s]);
5159 }
5160 Vector grad_s(dim);
5161 surf_fit_limiter->Eval_d1(pos, pos_target, 1.0, grad_s);
5162 for (int d = 0; d < dim; d++) { surf_fit_grad_e(s, d) = grad_s(d); }
5163 }
5164
5165 for (int d = 0; d < dim; d++)
5166 {
5167 mat(s, d) += w * surf_fit_grad_e(s, d);
5168 }
5169 }
5170}
5171
5174 DenseMatrix &mat)
5175{
5176 const int el_id = Tpr.ElementNo;
5177
5178 // Scalar for surf_fit_gf, vector for surf_fit_pos, but that's ok.
5179 const FiniteElementSpace *fes_fit =
5181 const FiniteElement &el_s = *fes_fit->GetFE(el_id);
5182 const int dof_s = el_s.GetDof(), dim = el_x.GetDim();
5183
5184 // Check if the element has any DOFs marked for surface fitting.
5185 Array<int> dofs, vdofs;
5186 fes_fit->GetElementVDofs(el_id, vdofs);
5187 int count = 0;
5188 for (int s = 0; s < dof_s; s++)
5189 {
5190 // Because surf_fit_pos.fes might be ordered byVDIM.
5191 const int scalar_dof_id = fes_fit->VDofToDof(vdofs[s]);
5192 count += ((*surf_fit_marker)[scalar_dof_id]) ? 1 : 0;
5193 }
5194 if (count == 0) { return; }
5195
5196 Vector sigma_e(dof_s);
5197 DenseMatrix surf_fit_grad_e(dof_s, dim);
5198 DenseMatrix surf_fit_hess_e(dof_s, dim*dim);
5199 if (surf_fit_gf)
5200 {
5201 surf_fit_gf->GetSubVector(vdofs, sigma_e);
5202
5203 // Project the gradient of sigma in the same space.
5204 // The FE coefficients of the gradient go in surf_fit_grad_e.
5205 Vector grad_ptr(surf_fit_grad_e.GetData(), dof_s * dim);
5206 DenseMatrix grad_phys; // This will be (dof x dim, dof).
5207 if (surf_fit_grad)
5208 {
5209 surf_fit_grad->FESpace()->GetElementVDofs(el_id, dofs);
5210 surf_fit_grad->GetSubVector(dofs, grad_ptr);
5211 }
5212 else
5213 {
5214 el_s.ProjectGrad(el_s, Tpr, grad_phys);
5215 grad_phys.Mult(sigma_e, grad_ptr);
5216 }
5217
5218 // Project the Hessian of sigma in the same space.
5219 // The FE coefficients of the Hessian go in surf_fit_hess_e.
5220 Vector hess_ptr(surf_fit_hess_e.GetData(), dof_s*dim*dim);
5221 if (surf_fit_hess)
5222 {
5223 surf_fit_hess->FESpace()->GetElementVDofs(el_id, dofs);
5224 surf_fit_hess->GetSubVector(dofs, hess_ptr);
5225 }
5226 else
5227 {
5228 surf_fit_hess_e.SetSize(dof_s*dim, dim);
5229 Mult(grad_phys, surf_fit_grad_e, surf_fit_hess_e);
5230 surf_fit_hess_e.SetSize(dof_s, dim * dim);
5231 }
5232 }
5233 else { Tpr.GetPointMat().Transpose(PMatI); }
5234
5235 const IntegrationRule &ir = el_s.GetNodes();
5236
5237 DenseMatrix surf_fit_hess_s(dim, dim);
5238 for (int s = 0; s < dof_s; s++)
5239 {
5240 // Because surf_fit_pos.fes might be ordered byVDIM.
5241 const int scalar_dof_id = fes_fit->VDofToDof(vdofs[s]);
5242 if ((*surf_fit_marker)[scalar_dof_id] == false) { continue; }
5243
5244 const IntegrationPoint &ip = ir.IntPoint(s);
5245 Tpr.SetIntPoint(&ip);
5246 real_t w = surf_fit_normal * surf_fit_coeff->Eval(Tpr, ip);
5247
5248 if (surf_fit_gf)
5249 {
5250 Vector gg_ptr(surf_fit_hess_s.GetData(), dim * dim);
5251 surf_fit_hess_e.GetRow(s, gg_ptr);
5252 w *= 2.0;
5253 }
5254 if (surf_fit_pos)
5255 {
5256 Vector pos(dim), pos_target(dim);
5257 for (int d = 0; d < dim; d++)
5258 {
5259 pos(d) = PMatI(s, d);
5260 pos_target(d) = (*surf_fit_pos)(vdofs[d*dof_s + s]);
5261 }
5262 // Eval_d2 returns the full Hessian, but we still use the general
5263 // computation that's in the dim x dim loop below.
5264 sigma_e(s) = 1.0;
5265 for (int d = 0; d < dim; d++) { surf_fit_grad_e(s, d) = 0.0; }
5266 surf_fit_limiter->Eval_d2(pos, pos_target, 1.0, surf_fit_hess_s);
5267 }
5268
5269 // Loops over the local matrix.
5270 for (int idim = 0; idim < dim; idim++)
5271 {
5272 for (int jdim = 0; jdim <= idim; jdim++)
5273 {
5274 real_t entry = w * ( surf_fit_grad_e(s, idim) *
5275 surf_fit_grad_e(s, jdim) +
5276 sigma_e(s) * surf_fit_hess_s(idim, jdim));
5277 entry *= 1.0 / surf_fit_dof_count[vdofs[s]];
5278 int idx = s + idim*dof_s;
5279 int jdx = s + jdim*dof_s;
5280 mat(idx, jdx) += entry;
5281 if (idx != jdx) { mat(jdx, idx) += entry; }
5282 }
5283 }
5284 }
5285}
5286
5289 Vector &d_el, const int dofidx,
5290 const int dir, const real_t e_fx,
5291 bool update_stored)
5292{
5293 int dof = el.GetDof();
5294 int idx = dir*dof+dofidx;
5295 d_el[idx] += fd_h;
5296 real_t e_fxph = GetElementEnergy(el, T, d_el);
5297 d_el[idx] -= fd_h;
5298 real_t dfdx = (e_fxph - e_fx) / fd_h;
5299
5300 if (update_stored)
5301 {
5302 (*(ElemPertEnergy[T.ElementNo]))(idx) = e_fxph;
5303 (*(ElemDer[T.ElementNo]))(idx) = dfdx;
5304 }
5305
5306 return dfdx;
5307}
5308
5311 const Vector &d_el,
5312 Vector &elvect)
5313{
5314 // Form the Vector of node positions, depending on what's the input.
5315 Vector elfun;
5316 if (x_0)
5317 {
5318 // The input is the displacement.
5320 elfun += d_el;
5321 }
5322 else { elfun = d_el; }
5323
5324 const int dof = el.GetDof(), dim = el.GetDim(), elnum = T.ElementNo;
5325 if (elnum >= ElemDer.Size())
5326 {
5327 ElemDer.Append(new Vector);
5328 ElemPertEnergy.Append(new Vector);
5329 ElemDer[elnum]->SetSize(dof*dim);
5330 ElemPertEnergy[elnum]->SetSize(dof*dim);
5331 }
5332
5333 elvect.SetSize(dof*dim);
5334
5335 // In GetElementEnergy(), skip terms that have exact derivative calculations.
5336 fd_call_flag = true;
5337
5338 // Energy for unperturbed configuration.
5339 const real_t e_fx = GetElementEnergy(el, T, d_el);
5340
5341 Vector d_el_mod(d_el);
5342 for (int j = 0; j < dim; j++)
5343 {
5344 for (int i = 0; i < dof; i++)
5345 {
5346 if (discr_tc)
5347 {
5349 el, T, i, j, discr_tc->GetTspecPert1H());
5350 }
5351 elvect(j*dof+i) = GetFDDerivative(el, T, d_el_mod, i, j, e_fx, true);
5353 }
5354 }
5355 fd_call_flag = false;
5356
5357 // Contributions from adaptive limiting, surface fitting (exact derivatives).
5358 if (adapt_lim_gf.Size() > 0 || surf_fit_gf || surf_fit_pos)
5359 {
5361 const int nqp = ir.GetNPoints();
5362 DenseTensor Jtr(dim, dim, nqp);
5363 targetC->ComputeElementTargets(T.ElementNo, el, ir, elfun, Jtr);
5364
5366 Tpr.SetFE(&el);
5367 Tpr.ElementNo = T.ElementNo;
5368 Tpr.Attribute = T.Attribute;
5369 Tpr.mesh = T.mesh;
5370 PMatI.UseExternalData(elfun.GetData(), dof, dim);
5371 Tpr.GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
5372
5373 Vector weights(nqp);
5374 for (int q = 0; q < nqp; q++)
5375 {
5376 weights(q) = (integ_over_target) ?
5377 ir.IntPoint(q).weight * Jtr(q).Det() :
5378 ir.IntPoint(q).weight;
5379 }
5380
5381 PMatO.UseExternalData(elvect.GetData(), dof, dim);
5382 if (adapt_lim_gf.Size() > 0) { AssembleElemVecAdaptLim(el, Tpr, ir, weights, PMatO); }
5384 }
5385}
5386
5389 const Vector &d_el,
5390 DenseMatrix &elmat)
5391{
5392 // Form the Vector of node positions, depending on what's the input.
5393 Vector elfun;
5394 if (x_0)
5395 {
5396 // The input is the displacement.
5398 elfun += d_el;
5399 }
5400 else { elfun = d_el; }
5401
5402 const int dof = el.GetDof(), dim = el.GetDim();
5403
5404 elmat.SetSize(dof*dim);
5405
5406 const Vector &ElemDerLoc = *(ElemDer[T.ElementNo]);
5407 const Vector &ElemPertLoc = *(ElemPertEnergy[T.ElementNo]);
5408
5409 // In GetElementEnergy(), skip terms that have exact derivative calculations.
5410 Vector d_el_mod(d_el);
5411 fd_call_flag = true;
5412 for (int i = 0; i < dof; i++)
5413 {
5414 for (int j = 0; j < i+1; j++)
5415 {
5416 for (int k1 = 0; k1 < dim; k1++)
5417 {
5418 for (int k2 = 0; k2 < dim; k2++)
5419 {
5420 d_el_mod(k2 * dof + j) += fd_h;
5421
5422 if (discr_tc)
5423 {
5425 el, T, j, k2, discr_tc->GetTspecPert1H());
5426 if (j != i)
5427 {
5429 el, T, i, k1, discr_tc->GetTspecPert1H());
5430 }
5431 else // j==i
5432 {
5433 if (k1 != k2)
5434 {
5435 int idx = k1+k2-1;
5437 el, T, i, idx, discr_tc->GetTspecPertMixH());
5438 }
5439 else // j==i && k1==k2
5440 {
5442 el, T, i, k1, discr_tc->GetTspecPert2H());
5443 }
5444 }
5445 }
5446
5447 real_t e_fx = ElemPertLoc(k2 * dof + j);
5448 real_t e_fpxph = GetFDDerivative(el, T, d_el_mod, i, k1, e_fx,
5449 false);
5450 d_el_mod(k2 * dof + j) -= fd_h;
5451 real_t e_fpx = ElemDerLoc(k1*dof+i);
5452
5453 elmat(k1*dof+i, k2*dof+j) = (e_fpxph - e_fpx) / fd_h;
5454 elmat(k2*dof+j, k1*dof+i) = (e_fpxph - e_fpx) / fd_h;
5455
5456 if (discr_tc)
5457 {
5460 }
5461 }
5462 }
5463 }
5464 }
5465 fd_call_flag = false;
5466
5467 // Contributions from adaptive limiting.
5468 if (adapt_lim_gf.Size() > 0 || surf_fit_gf || surf_fit_pos)
5469 {
5471 const int nqp = ir.GetNPoints();
5472 DenseTensor Jtr(dim, dim, nqp);
5473 targetC->ComputeElementTargets(T.ElementNo, el, ir, elfun, Jtr);
5474
5476 Tpr.SetFE(&el);
5477 Tpr.ElementNo = T.ElementNo;
5478 Tpr.Attribute = T.Attribute;
5479 Tpr.mesh = T.mesh;
5480 PMatI.UseExternalData(elfun.GetData(), dof, dim);
5481 Tpr.GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
5482
5483 Vector weights(nqp);
5484 for (int q = 0; q < nqp; q++)
5485 {
5486 weights(q) = (integ_over_target) ?
5487 ir.IntPoint(q).weight * Jtr(q).Det() :
5488 ir.IntPoint(q).weight;
5489 }
5490
5491 if (adapt_lim_gf.Size() > 0) { AssembleElemGradAdaptLim(el, Tpr, ir, weights, elmat); }
5492 if (surf_fit_gf || surf_fit_pos) { AssembleElemGradSurfFit(el, Tpr, elmat); }
5493 }
5494}
5495
5497{
5498 if (!surf_fit_coeff) { return; }
5499
5500 if (surf_fit_coeff)
5501 {
5502 auto cf = dynamic_cast<ConstantCoefficient *>(surf_fit_coeff);
5503 MFEM_VERIFY(cf, "Dynamic weight works only with a ConstantCoefficient.");
5504 cf->constant *= factor;
5505 }
5506}
5507
5509{
5510 if (surf_fit_coeff)
5511 {
5512 auto cf = dynamic_cast<ConstantCoefficient *>(surf_fit_coeff);
5513 MFEM_VERIFY(cf, "Dynamic weight works only with a ConstantCoefficient.");
5514 return cf->constant;
5515 }
5516 return 0.0;
5517}
5518
5526
5527#ifdef MFEM_USE_MPI
5529{
5530 real_t loc[2];
5531 ComputeNormalizationEnergies(x, loc[0], loc[1]);
5532 real_t rdc[2];
5533 MPI_Allreduce(loc, rdc, 2, MPITypeMap<real_t>::mpi_type, MPI_SUM,
5534 x.ParFESpace()->GetComm());
5535 metric_normal = 1.0 / rdc[0];
5536 lim_normal = 1.0 / rdc[1];
5538}
5539#endif
5540
5542 real_t &l_normal,
5543 real_t &s_normal)
5544{
5545 m_normal = this->metric_normal;
5546 l_normal = this->lim_normal;
5547 s_normal = this->surf_fit_normal;
5548}
5549
5551 real_t &metric_energy,
5552 real_t &lim_energy)
5553{
5554 metric_energy = 0.0;
5555 lim_energy = 0.0;
5556 if (PA.enabled)
5557 {
5558 MFEM_VERIFY(PA.E.Size() > 0, "Must be called after AssemblePA!");
5559 MFEM_VERIFY(surf_fit_gf == nullptr,
5560 "Normalization + PA + Fitting is not implemented!");
5561
5563 auto R = x.FESpace()->GetElementRestriction(ord);
5564 Vector xe(R->Height());
5565 R->Mult(x, xe);
5566
5567 // Force update of the target Jacobian.
5569
5570 if (PA.dim == 2)
5571 {
5572 GetLocalNormalizationEnergiesPA_2D(xe, metric_energy, lim_energy);
5573 }
5574 else
5575 {
5576 GetLocalNormalizationEnergiesPA_3D(xe, metric_energy, lim_energy);
5577 }
5578
5579 // Cases when integration is not over the target element, or when the
5580 // targets don't contain volumetric information.
5581 if (integ_over_target == false || targetC->ContainsVolumeInfo() == false)
5582 {
5583 lim_energy = x.FESpace()->GetNE();
5584 }
5585
5586 return;
5587 }
5588
5589 Array<int> vdofs;
5590 Vector x_vals;
5591 const FiniteElementSpace* const fes = x.FESpace();
5592
5593 const int dim = fes->GetMesh()->Dimension();
5594 Jrt.SetSize(dim);
5595 Jpr.SetSize(dim);
5596 Jpt.SetSize(dim);
5597
5598 for (int i = 0; i < fes->GetNE(); i++)
5599 {
5600 const FiniteElement *fe = fes->GetFE(i);
5602 const int nqp = ir.GetNPoints();
5603 DenseTensor Jtr(dim, dim, nqp);
5604 const int dof = fe->GetDof();
5605 DSh.SetSize(dof, dim);
5606
5607 fes->GetElementVDofs(i, vdofs);
5608 x.GetSubVector(vdofs, x_vals);
5609 PMatI.UseExternalData(x_vals.GetData(), dof, dim);
5610
5611 targetC->ComputeElementTargets(i, *fe, ir, x_vals, Jtr);
5612
5613 for (int q = 0; q < nqp; q++)
5614 {
5615 const IntegrationPoint &ip = ir.IntPoint(q);
5617 CalcInverse(Jtr(q), Jrt);
5618 const real_t weight =
5619 (integ_over_target) ? ip.weight * Jtr(q).Det() : ip.weight;
5620
5621 fe->CalcDShape(ip, DSh);
5622 MultAtB(PMatI, DSh, Jpr);
5623 Mult(Jpr, Jrt, Jpt);
5624
5625 metric_energy += weight * metric->EvalW(Jpt);
5626 lim_energy += weight;
5627 }
5628
5629 // TODO: Normalization of the surface fitting term.
5630 }
5631
5632 // Cases when integration is not over the target element, or when the
5633 // targets don't contain volumetric information.
5634 if (integ_over_target == false || targetC->ContainsVolumeInfo() == false)
5635 {
5636 lim_energy = fes->GetNE();
5637 }
5638}
5639
5641 const FiniteElementSpace &fes)
5642{
5643 const FiniteElement *fe = fes.GetTypicalFE();
5645 const int NE = fes.GetMesh()->GetNE(), dim = fe->GetDim(),
5646 dof = fe->GetDof(), nsp = ir.GetNPoints();
5647
5648 Array<int> xdofs(dof * dim);
5649 DenseMatrix dshape(dof, dim), pos(dof, dim);
5650 Vector posV(pos.Data(), dof * dim);
5651 Jpr.SetSize(dim);
5652
5653 fd_h = std::numeric_limits<float>::max();
5654
5655 real_t detv_sum;
5656 real_t detv_avg_min = std::numeric_limits<float>::max();
5657 for (int i = 0; i < NE; i++)
5658 {
5659 fes.GetElementVDofs(i, xdofs);
5660 x.GetSubVector(xdofs, posV);
5661 detv_sum = 0.;
5662 for (int j = 0; j < nsp; j++)
5663 {
5664 fes.GetFE(i)->CalcDShape(ir.IntPoint(j), dshape);
5665 MultAtB(pos, dshape, Jpr);
5666 detv_sum += std::fabs(Jpr.Det());
5667 }
5668 real_t detv_avg = pow(detv_sum/nsp, 1./dim);
5669 detv_avg_min = std::min(detv_avg, detv_avg_min);
5670 }
5671 fd_h = detv_avg_min / fd_h_scale;
5672}
5673
5675 int new_x_ordering)
5676{
5677 MFEM_VERIFY(periodic == false, "Periodic not implemented yet.");
5678
5679 if (!surf_fit_gf) { return; }
5680
5682 {
5683 // Interpolate information only at DOFs marked for fitting.
5684 const int dim = surf_fit_gf->FESpace()->GetMesh()->Dimension();
5685 const int cnt = surf_fit_marker_dof_index.Size();
5686 const int total_cnt = new_x.Size()/dim;
5687 Vector new_x_sorted(cnt*dim);
5688 if (new_x_ordering == 0)
5689 {
5690 for (int d = 0; d < dim; d++)
5691 {
5692 for (int i = 0; i < cnt; i++)
5693 {
5694 int dof_index = surf_fit_marker_dof_index[i];
5695 new_x_sorted(i + d*cnt) = new_x(dof_index + d*total_cnt);
5696 }
5697 }
5698 }
5699 else
5700 {
5701 for (int i = 0; i < cnt; i++)
5702 {
5703 int dof_index = surf_fit_marker_dof_index[i];
5704 for (int d = 0; d < dim; d++)
5705 {
5706 new_x_sorted(d + i*dim) = new_x(d + dof_index*dim);
5707 }
5708 }
5709 }
5710
5711 // Interpolate values of the LS.
5712 Vector surf_fit_gf_int, surf_fit_grad_int, surf_fit_hess_int;
5713 surf_fit_eval->ComputeAtGivenPositions(new_x_sorted, surf_fit_gf_int,
5714 new_x_ordering);
5715 for (int i = 0; i < cnt; i++)
5716 {
5717 int dof_index = surf_fit_marker_dof_index[i];
5718 (*surf_fit_gf)[dof_index] = surf_fit_gf_int(i);
5719 }
5720
5721 // Interpolate gradients of the LS.
5723 surf_fit_grad_int,
5724 new_x_ordering);
5725 // Assumes surf_fit_grad and surf_fit_gf share the same space
5726 const int grad_dim = surf_fit_grad->VectorDim();
5727 const int grad_cnt = surf_fit_grad->Size()/grad_dim;
5729 {
5730 for (int d = 0; d < grad_dim; d++)
5731 {
5732 for (int i = 0; i < cnt; i++)
5733 {
5734 int dof_index = surf_fit_marker_dof_index[i];
5735 (*surf_fit_grad)[dof_index + d*grad_cnt] =
5736 surf_fit_grad_int(i + d*cnt);
5737 }
5738 }
5739 }
5740 else
5741 {
5742 for (int i = 0; i < cnt; i++)
5743 {
5744 int dof_index = surf_fit_marker_dof_index[i];
5745 for (int d = 0; d < grad_dim; d++)
5746 {
5747 (*surf_fit_grad)[dof_index*grad_dim + d] =
5748 surf_fit_grad_int(i*grad_dim + d);
5749 }
5750 }
5751 }
5752
5753 // Interpolate Hessians of the LS.
5755 surf_fit_hess_int,
5756 new_x_ordering);
5757 // Assumes surf_fit_hess and surf_fit_gf share the same space
5758 const int hess_dim = surf_fit_hess->VectorDim();
5759 const int hess_cnt = surf_fit_hess->Size()/hess_dim;
5761 {
5762 for (int d = 0; d < hess_dim; d++)
5763 {
5764 for (int i = 0; i < cnt; i++)
5765 {
5766 int dof_index = surf_fit_marker_dof_index[i];
5767 (*surf_fit_hess)[dof_index + d*hess_cnt] =
5768 surf_fit_hess_int(i + d*cnt);
5769 }
5770 }
5771 }
5772 else
5773 {
5774 for (int i = 0; i < cnt; i++)
5775 {
5776 int dof_index = surf_fit_marker_dof_index[i];
5777 for (int d = 0; d < hess_dim; d++)
5778 {
5779 (*surf_fit_hess)[dof_index*hess_dim + d] =
5780 surf_fit_hess_int(i*hess_dim + d);
5781 }
5782 }
5783 }
5784
5785 }
5786 else
5787 {
5788 surf_fit_eval->ComputeAtNewPosition(new_x, *surf_fit_gf, new_x_ordering);
5790 {
5792 new_x_ordering);
5793 }
5795 {
5797 new_x_ordering);
5798 }
5799 }
5800}
5801
5804{
5805 if (discr_tc) { PA.Jtr_needs_update = true; }
5806
5807 if (PA.enabled) { UpdateCoefficientsPA(d); }
5808
5809 Ordering::Type ordering = d_fes.GetOrdering();
5810
5811 // Update the finite difference delta if FD are used.
5812 if (fdflag) { ComputeFDh(d, d_fes); }
5813
5814 Vector x_loc;
5815 if (periodic)
5816 {
5817 GetPeriodicPositions(*x_0, d, *x_0->FESpace(), d_fes, x_loc);
5818 }
5819 else
5820 {
5821 x_loc.SetSize(x_0->Size());
5822 add(*x_0, d, x_loc);
5823 }
5824
5825 // Update the target constructor if it's a discrete one.
5826 if (discr_tc)
5827 {
5828 discr_tc->UpdateTargetSpecification(x_loc, true, ordering);
5829 if (fdflag)
5830 {
5831 if (periodic) { MFEM_ABORT("Periodic not implemented yet."); }
5832 discr_tc->UpdateGradientTargetSpecification(x_loc, fd_h, true, ordering);
5833 discr_tc->UpdateHessianTargetSpecification(x_loc, fd_h, true, ordering);
5834 }
5835 }
5836
5837 // Update adapt_lim_gf if adaptive limiting is enabled.
5838 if (adapt_lim_gf.Size() > 0)
5839 {
5840 // All adapt_lim_gf are remapped as a multi-component vector.
5841 const int nal = adapt_lim_coeff.Size();
5842 const int ndofs = adapt_lim_gf0[0]->Size();
5843 Vector new_field_vec;
5844 new_field_vec.SetSize(nal * ndofs, *adapt_lim_gf[0]);
5845 new_field_vec.UseDevice(adapt_lim_gf[0]->UseDevice());
5846 adapt_lim_eval->ComputeAtNewPosition(x_loc, new_field_vec, ordering);
5847 for (int c = 0; c < nal; c++)
5848 {
5849 const real_t *src = new_field_vec.Read() + c * ndofs;
5850 real_t *dst = adapt_lim_gf[c]->Write();
5851 internal::device_copy(dst, src, ndofs);
5852 }
5853
5854 if (PA.enabled)
5855 {
5856 PA.AL_grads_assembled = false;
5857
5858 // Step 1 of PA.ALFmF0 update: subtract the old ALF.
5859 PA.ALFmF0 -= PA.ALF;
5860
5861 // Refresh PA.ALF from the updated adapt_lim_gf.
5863 const FiniteElementSpace *alfes = adapt_lim_gf[0]->FESpace();
5864 const Operator *alf_R = alfes->GetElementRestriction(ord);
5865
5866 const int Esize = alf_R->Height();
5867 Vector ALFc;
5868 for (int c = 0; c < nal; c++)
5869 {
5870 MFEM_VERIFY(adapt_lim_gf[c]->Size() == ndofs, "internal error");
5871 ALFc.MakeRef(PA.ALF, c * Esize, Esize);
5872 alf_R->Mult(*adapt_lim_gf[c], ALFc);
5873 }
5874
5875 // Step 2 of PA.ALFmF0 update: add the new ALF.
5876 PA.ALFmF0 += PA.ALF;
5877 }
5878 }
5879
5880 // Update surf_fit_gf (and optionally its gradients) if surface
5881 // fitting is enabled.
5882 if (surf_fit_gf)
5883 {
5884 RemapSurfaceFittingLevelSetAtNodes(x_loc, ordering);
5885 }
5886}
5887
5889{
5890 if (periodic) { MFEM_ABORT("Periodic not implemented yet."); }
5891
5892 Vector x_loc(*x_0);
5893 x_loc += d;
5894
5895 if (!fdflag) { return; }
5896 ComputeMinJac(x_loc, fes);
5897#ifdef MFEM_USE_MPI
5898 const ParFiniteElementSpace *pfes =
5899 dynamic_cast<const ParFiniteElementSpace *>(&fes);
5900 if (pfes)
5901 {
5902 real_t min_jac_all;
5903 MPI_Allreduce(&fd_h, &min_jac_all, 1, MPITypeMap<real_t>::mpi_type,
5904 MPI_MIN, pfes->GetComm());
5905 fd_h = min_jac_all;
5906 }
5907#endif
5908}
5909
5911{
5912 fdflag = true;
5913 const FiniteElementSpace *fes = x.FESpace();
5914
5915 const bool per = fes->IsDGSpace();
5916 MFEM_VERIFY(per == false, "FD is not supported for periodic meshes.");
5917
5918 if (discr_tc)
5919 {
5920#ifdef MFEM_USE_GSLIB
5922 if (dynamic_cast<const InterpolatorFP *>(ae))
5923 {
5924 MFEM_ABORT("Using GSLIB-based interpolation with finite differences"
5925 "requires careful consideration. Contact TMOP team.");
5926 }
5927#endif
5930 fes->GetOrdering());
5932 fes->GetOrdering());
5933 }
5934}
5935
5936#ifdef MFEM_USE_MPI
5938{
5939 fdflag = true;
5940 const ParFiniteElementSpace *pfes = x.ParFESpace();
5941
5942 const bool per = pfes->IsDGSpace();
5943 MFEM_VERIFY(per == false, "FD is not supported for periodic meshes.");
5944
5945 if (discr_tc)
5946 {
5947#ifdef MFEM_USE_GSLIB
5949 if (dynamic_cast<const InterpolatorFP *>(ae))
5950 {
5951 MFEM_ABORT("Using GSLIB-based interpolation with finite differences"
5952 "requires careful consideration. Contact TMOP team.");
5953 }
5954#endif
5957 pfes->GetOrdering());
5959 pfes->GetOrdering());
5960 }
5961}
5962#endif
5963
5965 const FiniteElementSpace &fes)
5966{
5967 real_t min_detT = std::numeric_limits<real_t>::infinity();
5968 const int NE = fes.GetMesh()->GetNE();
5969 const int dim = fes.GetMesh()->Dimension();
5970 Array<int> xdofs;
5971 Jpr.SetSize(dim);
5972 Jpt.SetSize(dim);
5973 Jrt.SetSize(dim);
5974
5975 for (int i = 0; i < NE; i++)
5976 {
5977 const FiniteElement *fe = fes.GetFE(i);
5979 const int dof = fe->GetDof(), nsp = ir.GetNPoints();
5980
5981 DSh.SetSize(dof, dim);
5982 Vector posV(dof * dim);
5983 PMatI.UseExternalData(posV.GetData(), dof, dim);
5984
5985 fes.GetElementVDofs(i, xdofs);
5986 x.GetSubVector(xdofs, posV);
5987
5989 targetC->ComputeElementTargets(i, *fe, ir, posV, Jtr);
5990
5991 for (int q = 0; q < nsp; q++)
5992 {
5993 const IntegrationPoint &ip = ir.IntPoint(q);
5994 const DenseMatrix &Jtr_q = Jtr(q);
5995 CalcInverse(Jtr_q, Jrt);
5996 fe->CalcDShape(ip, DSh);
5997 MultAtB(PMatI, DSh, Jpr);
5998 Mult(Jpr, Jrt, Jpt);
5999 real_t detT = Jpt.Det();
6000 min_detT = std::min(min_detT, detT);
6001 }
6002 }
6003 return min_detT;
6004}
6005
6008{
6009 real_t max_muT = -std::numeric_limits<real_t>::infinity();
6010 const int NE = fes.GetMesh()->GetNE();
6011 const int dim = fes.GetMesh()->Dimension();
6012 Array<int> xdofs;
6013 Jpr.SetSize(dim);
6014 Jpt.SetSize(dim);
6015 Jrt.SetSize(dim);
6016
6019
6020 if (!wcuo || wcuo->GetWorstCaseType() !=
6022 {
6023 return 0.0;
6024 }
6025
6026 for (int i = 0; i < NE; i++)
6027 {
6028 const FiniteElement *fe = fes.GetFE(i);
6030 const int dof = fe->GetDof(), nsp = ir.GetNPoints();
6031 Jpr.SetSize(dim);
6032 Jrt.SetSize(dim);
6033 Jpt.SetSize(dim);
6034
6035 DSh.SetSize(dof, dim);
6036 Vector posV(dof * dim);
6037 PMatI.UseExternalData(posV.GetData(), dof, dim);
6038
6039 fes.GetElementVDofs(i, xdofs);
6040 x.GetSubVector(xdofs, posV);
6041
6043 targetC->ComputeElementTargets(i, *fe, ir, posV, Jtr);
6044
6045 for (int q = 0; q < nsp; q++)
6046 {
6047 const IntegrationPoint &ip = ir.IntPoint(q);
6048 const DenseMatrix &Jtr_q = Jtr(q);
6049 CalcInverse(Jtr_q, Jrt);
6050
6051 fe->CalcDShape(ip, DSh);
6052 MultAtB(PMatI, DSh, Jpr);
6053 Mult(Jpr, Jrt, Jpt);
6054
6055 real_t metric_val = 0.0;
6056 if (wcuo)
6057 {
6058 wcuo->SetTargetJacobian(Jtr_q);
6059 metric_val = wcuo->EvalWBarrier(Jpt);
6060 }
6061
6062 max_muT = std::max(max_muT, metric_val);
6063 }
6064 }
6065 return max_muT;
6066}
6067
6070{
6073
6074 if (!wcuo) { return; }
6075
6076 if (periodic) { MFEM_ABORT("Periodic not implemented yet."); }
6077
6078 Vector x_loc(d.Size());
6079 if (x_0)
6080 {
6081 add(*x_0, d, x_loc);
6082 }
6083 else { x_loc = d; }
6084
6085#ifdef MFEM_USE_MPI
6086 const ParFiniteElementSpace *pfes =
6087 dynamic_cast<const ParFiniteElementSpace *>(&fes);
6088#endif
6089
6090 if (wcuo->GetBarrierType() ==
6092 {
6093 real_t min_detT = ComputeMinDetT(x_loc, fes);
6094 real_t min_detT_all = min_detT;
6095#ifdef MFEM_USE_MPI
6096 if (pfes)
6097 {
6098 MPI_Allreduce(&min_detT, &min_detT_all, 1,
6099 MPITypeMap<real_t>::mpi_type, MPI_MIN, pfes->GetComm());
6100 }
6101#endif
6102 wcuo->SetMinDetT(min_detT_all);
6103 }
6104
6105 real_t max_muT = ComputeUntanglerMaxMuBarrier(x_loc, fes);
6106 real_t max_muT_all = max_muT;
6107#ifdef MFEM_USE_MPI
6108 if (pfes)
6109 {
6110 MPI_Allreduce(&max_muT, &max_muT_all, 1, MPITypeMap<real_t>::mpi_type,
6111 MPI_MAX, pfes->GetComm());
6112 }
6113#endif
6114 wcuo->SetMaxMuT(max_muT_all);
6115}
6116
6118 const GridFunction &dist,
6119 Coefficient &w0,
6120 TMOP_LimiterFunction *lfunc)
6121{
6122 MFEM_VERIFY(tmopi.Size() > 0, "No TMOP_Integrators were added.");
6123
6124 tmopi[0]->EnableLimiting(n0, dist, w0, lfunc);
6125 for (int i = 1; i < tmopi.Size(); i++) { tmopi[i]->DisableLimiting(); }
6126}
6127
6129 Coefficient &w0,
6130 TMOP_LimiterFunction *lfunc)
6131{
6132 MFEM_VERIFY(tmopi.Size() > 0, "No TMOP_Integrators were added.");
6133
6134 tmopi[0]->EnableLimiting(n0, w0, lfunc);
6135 for (int i = 1; i < tmopi.Size(); i++) { tmopi[i]->DisableLimiting(); }
6136}
6137
6139 Coefficient &coeff,
6141 real_t delta_max)
6142{
6143 MFEM_VERIFY(tmopi.Size() > 0, "No TMOP_Integrators were added.");
6144
6145 tmopi[0]->EnableAdaptiveLimiting(z0, coeff, ae, delta_max);
6146}
6147
6150 const Array<Coefficient *> &coeff,
6151 AdaptivityEvaluator &ae, const Array<real_t> &delta_max)
6152{
6153 MFEM_VERIFY(tmopi.Size() > 0, "No TMOP_Integrators were added.");
6154
6155 tmopi[0]->EnableAdaptiveLimiting(z0, coeff, ae, delta_max);
6156}
6157
6158#ifdef MFEM_USE_MPI
6160 Coefficient &coeff,
6162 real_t delta_max)
6163{
6164 MFEM_VERIFY(tmopi.Size() > 0, "No TMOP_Integrators were added.");
6165
6166 tmopi[0]->EnableAdaptiveLimiting(z0, coeff, ae, delta_max);
6167}
6168
6171 const Array<Coefficient *> &coeff,
6172 AdaptivityEvaluator &ae, const Array<real_t> &delta_max)
6173{
6174 MFEM_VERIFY(tmopi.Size() > 0, "No TMOP_Integrators were added.");
6175
6176 tmopi[0]->EnableAdaptiveLimiting(z0, coeff, ae, delta_max);
6177}
6178#endif
6179
6181{
6182 MFEM_VERIFY(tmopi.Size() > 0, "No TMOP_Integrators were added.");
6183
6184 tmopi[0]->SetLimitingNodes(n0);
6185 for (int i = 1; i < tmopi.Size(); i++) { tmopi[i]->DisableLimiting(); }
6186}
6187
6190 const Vector &elfun)
6191{
6192 real_t energy= 0.0;
6193 for (int i = 0; i < tmopi.Size(); i++)
6194 {
6195 energy += tmopi[i]->GetElementEnergy(el, T, elfun);
6196 }
6197 return energy;
6198}
6199
6202 const Vector &elfun,
6203 Vector &elvect)
6204{
6205 MFEM_VERIFY(tmopi.Size() > 0, "No TMOP_Integrators were added.");
6206
6207 tmopi[0]->AssembleElementVector(el, T, elfun, elvect);
6208 for (int i = 1; i < tmopi.Size(); i++)
6209 {
6210 Vector elvect_i;
6211 tmopi[i]->AssembleElementVector(el, T, elfun, elvect_i);
6212 elvect += elvect_i;
6213 }
6214}
6215
6218 const Vector &elfun,
6219 DenseMatrix &elmat)
6220{
6221 MFEM_VERIFY(tmopi.Size() > 0, "No TMOP_Integrators were added.");
6222
6223 tmopi[0]->AssembleElementGrad(el, T, elfun, elmat);
6224 for (int i = 1; i < tmopi.Size(); i++)
6225 {
6226 DenseMatrix elmat_i;
6227 tmopi[i]->AssembleElementGrad(el, T, elfun, elmat_i);
6228 elmat += elmat_i;
6229 }
6230}
6231
6234 const Vector &elfun,
6235 const IntegrationRule &irule)
6236{
6237 real_t energy= 0.0;
6238 for (int i = 0; i < tmopi.Size(); i++)
6239 {
6240 energy += tmopi[i]->GetRefinementElementEnergy(el, T, elfun, irule);
6241 }
6242 return energy;
6243}
6244
6246 const FiniteElement &el,
6248 const Vector &elfun)
6249{
6250 real_t energy= 0.0;
6251 for (int i = 0; i < tmopi.Size(); i++)
6252 {
6253 energy += tmopi[i]->GetDerefinementElementEnergy(el, T, elfun);
6254 }
6255 return energy;
6256}
6257
6259{
6260 const int cnt = tmopi.Size();
6261 real_t total_integral = 0.0;
6262 for (int i = 0; i < cnt; i++)
6263 {
6264 tmopi[i]->EnableNormalization(x);
6265 total_integral += 1.0 / tmopi[i]->metric_normal;
6266 }
6267 for (int i = 0; i < cnt; i++)
6268 {
6269 tmopi[i]->metric_normal = 1.0 / total_integral;
6270 }
6271}
6272
6273#ifdef MFEM_USE_MPI
6275{
6276 const int cnt = tmopi.Size();
6277 real_t total_integral = 0.0;
6278 for (int i = 0; i < cnt; i++)
6279 {
6280 tmopi[i]->ParEnableNormalization(x);
6281 total_integral += 1.0 / tmopi[i]->metric_normal;
6282 }
6283 for (int i = 0; i < cnt; i++)
6284 {
6285 tmopi[i]->metric_normal = 1.0 / total_integral;
6286 }
6287}
6288#endif
6289
6291{
6292 for (int i = 0; i < tmopi.Size(); i++)
6293 {
6294 tmopi[i]->AssemblePA(fes);
6295 }
6296}
6297
6299 const FiniteElementSpace &fes)
6300{
6301 for (int i = 0; i < tmopi.Size(); i++)
6302 {
6303 tmopi[i]->AssembleGradPA(xe,fes);
6304 }
6305}
6306
6308{
6309 for (int i = 0; i < tmopi.Size(); i++)
6310 {
6311 tmopi[i]->AssembleGradDiagonalPA(de);
6312 }
6313}
6314
6316{
6317 for (int i = 0; i < tmopi.Size(); i++)
6318 {
6319 tmopi[i]->AddMultPA(xe, ye);
6320 }
6321}
6322
6324{
6325 for (int i = 0; i < tmopi.Size(); i++)
6326 {
6327 tmopi[i]->AddMultGradPA(re, ce);
6328 }
6329}
6330
6332{
6333 real_t energy = 0.0;
6334 for (int i = 0; i < tmopi.Size(); i++)
6335 {
6336 energy += tmopi[i]->GetLocalStateEnergyPA(xe);
6337 }
6338 return energy;
6339}
6340
6342 const TargetConstructor &tc,
6343 const Mesh &mesh, GridFunction &metric_gf)
6344{
6345 const int NE = mesh.GetNE();
6346 const GridFunction &nodes = *mesh.GetNodes();
6347 const int dim = mesh.Dimension();
6348 DenseMatrix Winv(dim), T(dim), A(dim), dshape, pos;
6349 Array<int> pos_dofs, gf_dofs;
6350 DenseTensor W;
6351 Vector posV;
6352
6353 for (int i = 0; i < NE; i++)
6354 {
6355 const FiniteElement &fe_pos = *nodes.FESpace()->GetFE(i);
6356 const IntegrationRule &ir = metric_gf.FESpace()->GetFE(i)->GetNodes();
6357 const int nsp = ir.GetNPoints(), dof = fe_pos.GetDof();
6358
6359 dshape.SetSize(dof, dim);
6360 pos.SetSize(dof, dim);
6361 posV.SetDataAndSize(pos.Data(), dof * dim);
6362
6363 metric_gf.FESpace()->GetElementDofs(i, gf_dofs);
6364 nodes.FESpace()->GetElementVDofs(i, pos_dofs);
6365 nodes.GetSubVector(pos_dofs, posV);
6366
6367 W.SetSize(dim, dim, nsp);
6368 tc.ComputeElementTargets(i, fe_pos, ir, posV, W);
6369
6370 for (int j = 0; j < nsp; j++)
6371 {
6372 const DenseMatrix &Wj = W(j);
6373 metric.SetTargetJacobian(Wj);
6374 CalcInverse(Wj, Winv);
6375
6376 const IntegrationPoint &ip = ir.IntPoint(j);
6377 fe_pos.CalcDShape(ip, dshape);
6378 MultAtB(pos, dshape, A);
6379 Mult(A, Winv, T);
6380
6381 metric_gf(gf_dofs[j]) = metric.EvalW(T);
6382 }
6383 }
6384}
6385
6386} // namespace mfem
virtual ~AdaptivityEvaluator()
Definition tmop.cpp:3717
virtual void SetNewFieldFESpace(const FiniteElementSpace &fes)=0
virtual void SetInitialField(const Vector &init_nodes, const Vector &init_field)=0
virtual void ComputeAtGivenPositions(const Vector &positions, Vector &values, int p_ordering=Ordering::byNODES)=0
Using the source mesh and field given by SetInitialField(), compute corresponding values at specified...
void SetSerialMetaInfo(const Mesh &m, const FiniteElementSpace &f)
Definition tmop.cpp:3686
FiniteElementSpace * fes
Definition tmop.hpp:1514
void SetParMetaInfo(const ParMesh &m, const ParFiniteElementSpace &f)
Parallel version of SetSerialMetaInfo.
Definition tmop.cpp:3697
virtual void ComputeAtNewPosition(const Vector &new_mesh_nodes, Vector &new_field, int nodes_ordering=Ordering::byNODES)=0
Perform field transfer between the original and a new mesh. The source mesh and field are given by Se...
ParFiniteElementSpace * pfes
Definition tmop.hpp:1519
Coefficient * scalar_tspec
Definition tmop.hpp:1734
virtual void SetAnalyticTargetSpec(Coefficient *sspec, VectorCoefficient *vspec, TMOPMatrixCoefficient *mspec)
Definition tmop.cpp:2603
TMOPMatrixCoefficient * matrix_tspec
Definition tmop.hpp:1736
VectorCoefficient * vector_tspec
Definition tmop.hpp:1735
void ComputeElementTargets(int e_id, const FiniteElement &fe, const IntegrationRule &ir, const Vector &elfun, DenseTensor &Jtr) const override
Given an element and quadrature rule, computes ref->target transformation Jacobians for each quadratu...
Definition tmop.cpp:2612
void ComputeElementTargetsGradient(const IntegrationRule &ir, const Vector &elfun, IsoparametricTransformation &Tpr, DenseTensor &dJtr) const override
Definition tmop.cpp:2646
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition array.hpp:869
int Size() const
Return the logical size of the array.
Definition array.hpp:192
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Definition array.hpp:941
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:108
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:580
void MultTranspose(const real_t *x, real_t *y) const
Multiply a vector with the transpose matrix.
Definition densemat.cpp:158
void Transpose()
(*this) = (*this)^t
int TotalSize() const
Total size = width*height.
Definition densemat.hpp:122
real_t * Data() const
Returns the matrix data array. Warning: this method casts away constness.
Definition densemat.hpp:131
real_t * GetData() const
Returns the matrix data array. Warning: this method casts away constness.
Definition densemat.hpp:135
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
Definition densemat.hpp:125
real_t Trace() const
Trace of a square matrix.
Definition densemat.cpp:409
real_t & Elem(int i, int j) override
Returns reference to a_{ij}.
Definition densemat.cpp:98
void UseExternalData(real_t *d, int h, int w)
Change the data array and the size of the DenseMatrix.
Definition densemat.hpp:97
void Add(const real_t c, const DenseMatrix &A)
Adds the matrix A multiplied by the number c to the matrix.
Definition densemat.cpp:589
void GetColumn(int c, Vector &col) const
int Size() const
For backward compatibility define Size to be synonym of Width()
Definition densemat.hpp:119
real_t FNorm2() const
Compute the square of the Frobenius norm of the matrix.
Definition densemat.hpp:297
void GetRow(int r, Vector &row) const
real_t Det() const
Definition densemat.cpp:496
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
static MemoryType GetMemoryType()
(DEPRECATED) Equivalent to GetDeviceMemoryType().
Definition device.hpp:302
const Vector & GetTspecPert1H()
Definition tmop.hpp:1930
void UpdateTargetSpecification(const Vector &new_x, bool reuse_flag=false, int new_x_ordering=Ordering::byNODES)
Definition tmop.cpp:2923
virtual void SetSerialDiscreteTargetSkew(const GridFunction &tspec_)
Definition tmop.cpp:2841
virtual void SetParDiscreteTargetAspectRatio(const ParGridFunction &tspec_)
Definition tmop.cpp:2769
ParGridFunction * tspec_pgf
Definition tmop.hpp:1806
DenseTensor Jtrcomp
Definition tmop.hpp:1795
virtual void SetSerialDiscreteTargetAspectRatio(const GridFunction &tspec_)
Definition tmop.cpp:2851
const AdaptivityEvaluator * GetAdaptivityEvaluator() const
Definition tmop.hpp:1925
void SetTspecDataForDerefinement(FiniteElementSpace *fes)
Computes target specification data with respect to the coarse FE space.
Definition tmop.cpp:3000
const Vector & GetTspecPertMixH()
Definition tmop.hpp:1932
void ComputeElementTargetsGradient(const IntegrationRule &ir, const Vector &elfun, IsoparametricTransformation &Tpr, DenseTensor &dJtr) const override
Definition tmop.cpp:3223
virtual void SetParDiscreteTargetSpec(const ParGridFunction &tspec_)
Definition tmop.cpp:2789
AdaptivityEvaluator * adapt_eval
Definition tmop.hpp:1818
void FinalizeSerialDiscreteTargetSpec(const GridFunction &tspec_)
Definition tmop.cpp:2871
void FinalizeParDiscreteTargetSpec(const ParGridFunction &tspec_)
Definition tmop.cpp:2693
ParFiniteElementSpace * ptspec_fesv
Definition tmop.hpp:1804
GridFunction * tspec_gf
Definition tmop.hpp:1801
FiniteElementSpace * coarse_tspec_fesv
Definition tmop.hpp:1800
virtual ~DiscreteAdaptTC()
Definition tmop.cpp:3676
virtual void SetSerialDiscreteTargetSize(const GridFunction &tspec_)
Definition tmop.cpp:2831
virtual void SetParDiscreteTargetSize(const ParGridFunction &tspec_)
Definition tmop.cpp:2749
const Vector & GetTspecPert2H()
Definition tmop.hpp:1931
void ComputeElementTargets(int e_id, const FiniteElement &fe, const IntegrationRule &ir, const Vector &elfun, DenseTensor &Jtr) const override
Given an element and quadrature rule, computes ref->target transformation Jacobians for each quadratu...
Definition tmop.cpp:3008
void UpdateAfterMeshTopologyChange()
Update all discrete fields based on tspec and update for AMR.
Definition tmop.cpp:2906
virtual void SetSerialDiscreteTargetSpec(const GridFunction &tspec_)
Definition tmop.cpp:2917
virtual void SetParDiscreteTargetOrientation(const ParGridFunction &tspec_)
Definition tmop.cpp:2779
void ResetRefinementTspecData()
Definition tmop.hpp:1967
virtual void SetParDiscreteTargetSkew(const ParGridFunction &tspec_)
Definition tmop.cpp:2759
void ParUpdateAfterMeshTopologyChange()
Definition tmop.cpp:2718
void UpdateTargetSpecificationAtNode(const FiniteElement &el, ElementTransformation &T, int nodenum, int idir, const Vector &IntData)
Definition tmop.cpp:2943
void RestoreTargetSpecificationAtNode(ElementTransformation &T, int nodenum)
Definition tmop.cpp:2960
FiniteElementSpace * tspec_fesv
Definition tmop.hpp:1799
virtual void SetSerialDiscreteTargetOrientation(const GridFunction &tspec_)
Definition tmop.cpp:2861
void SetTspecAtIndex(int idx, const GridFunction &tspec_)
Definition tmop.cpp:2818
void SetRefinementSubElement(int amr_el_)
Definition tmop.hpp:1982
void GetDiscreteTargetSpec(GridFunction &tspec_, int idx)
Get one of the discrete fields from tspec.
Definition tmop.cpp:2892
void UpdateHessianTargetSpecification(const Vector &x, real_t dx, bool reuse_flag=false, int x_ordering=Ordering::byNODES)
Definition tmop.cpp:3608
void SetDiscreteTargetBase(const GridFunction &tspec_)
Definition tmop.cpp:2795
DenseMatrix tspec_refine
Definition tmop.hpp:1788
void UpdateGradientTargetSpecification(const Vector &x, real_t dx, bool reuse_flag=false, int x_ordering=Ordering::byNODES)
Definition tmop.cpp:3571
void SetTspecFromIntRule(int e_id, const IntegrationRule &intrule)
Definition tmop.cpp:2974
const Mesh * mesh
The Mesh object containing the element.
Definition eltrans.hpp:97
real_t Weight()
Return the weight of the Jacobian matrix of the transformation at the currently set IntegrationPoint....
Definition eltrans.hpp:144
void SetIntPoint(const IntegrationPoint *ip)
Set the integration point ip that weights and Jacobians will be evaluated at.
Definition eltrans.hpp:106
int GetOrder() const
Return the order (polynomial degree) of the FE collection, corresponding to the order/degree returned...
Definition fe_coll.hpp:248
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:210
bool IsVariableOrder() const
Returns true if the space contains elements of varying polynomial orders.
Definition fespace.hpp:673
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:3538
int GetNDofs() const
Returns number of degrees of freedom. This is the number of Local Degrees of Freedom.
Definition fespace.hpp:821
int VDofToDof(int vdof) const
Compute the inverse of the Dof to VDof mapping for a single index vdof.
Definition fespace.hpp:1131
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:299
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:3860
Ordering::Type GetOrdering() const
Return the ordering method.
Definition fespace.hpp:852
int GetNE() const
Returns number of elements in the mesh.
Definition fespace.hpp:867
const ElementRestrictionOperator * GetElementRestriction(ElementDofOrdering e_ordering) const
Return an Operator that converts L-vectors to E-vectors.
Definition fespace.cpp:1476
virtual void Update(bool want_transform=true)
Reflect changes in the mesh: update number of DOFs, etc. Also, calculate GridFunction transformation ...
Definition fespace.cpp:4192
const FiniteElementCollection * FEColl() const
Definition fespace.hpp:854
Mesh * GetMesh() const
Returns the mesh.
Definition fespace.hpp:639
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
Definition fespace.hpp:824
int GetVDim() const
Returns the vector dimension of the finite element space.
Definition fespace.hpp:817
bool IsDGSpace() const
Return whether or not the space is discontinuous (L2)
Definition fespace.hpp:1587
const FiniteElement * GetTypicalFE() const
Return GetFE(0) if the local mesh is not empty; otherwise return a typical FE based on the Geometry t...
Definition fespace.cpp:3896
const Operator * GetUpdateOperator()
Get the GridFunction update operator.
Definition fespace.hpp:1552
Abstract class for all finite elements.
Definition fe_base.hpp:294
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:171
int GetDim() const
Returns the reference space dimension for the finite element.
Definition fe_base.hpp:381
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
Definition fe_base.hpp:476
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:407
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:410
const DenseMatrix & GetGeomToPerfGeomJac(int GeomType) const
Definition geom.hpp:102
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:53
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:497
virtual void Update()
Transform by the Space UpdateMatrix (e.g., on Mesh change).
Definition gridfunc.cpp:169
void MakeOwner(FiniteElementCollection *fec_)
Make the GridFunction the owner of fec_owned and fes.
Definition gridfunc.hpp:160
virtual void GetElementDofValues(int el, Vector &dof_vals) const
FiniteElementSpace * FESpace()
int VectorDim() const
Shortcut for calling FiniteElementSpace::GetVectorDim() on the underlying fes.
Definition gridfunc.hpp:166
void GetVectorValues(int i, const IntegrationRule &ir, DenseMatrix &vals, DenseMatrix &tr) const
Definition gridfunc.cpp:687
Arbitrary order H1-conforming (continuous) finite elements.
Definition fe_coll.hpp:291
int GetBasisType() const
Definition fe_coll.hpp:317
Class for integration point with weight.
Definition intrules.hpp:35
Class for an integration rule - an Array of IntegrationPoint.
Definition intrules.hpp:96
int GetNPoints() const
Returns the number of the points in the integration rule.
Definition intrules.hpp:255
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
Definition intrules.hpp:258
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:629
int OrderJ() const override
Return the order of the elements of the Jacobian of the transformation.
Definition eltrans.cpp:477
void SetFE(const FiniteElement *FE)
Set the element that will be used to compute the transformations.
Definition eltrans.hpp:648
const FiniteElement * GetFE() const
Get the current element used to compute the transformations.
Definition eltrans.hpp:656
const DenseMatrix & GetPointMat() const
Return the stored point matrix.
Definition eltrans.hpp:671
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:67
int GetNE() const
Returns number of elements.
Definition mesh.hpp:1390
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1314
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:361
void GetNodes(Vector &node_coord) const
Definition mesh.cpp:10112
NCMesh * ncmesh
Optional nonconforming mesh extension.
Definition mesh.hpp:318
int GetNumGeometries(int dim) const
Return the number of geometries of the given dimension present in the mesh.
Definition mesh.cpp:8014
Geometry::Type GetElementBaseGeometry(int i) const
Definition mesh.hpp:1569
void DeleteGeometricFactors()
Destroy all GeometricFactors stored by the Mesh.
Definition mesh.cpp:1097
A class for non-conforming AMR. The class is not used directly by the user, rather it is an extension...
Definition ncmesh.hpp:190
int GetElementSizeReduction(int i) const
Definition ncmesh.cpp:5759
int GetNumRootElements()
Return the number of root elements.
Definition ncmesh.hpp:510
Class for standard nodal finite elements.
Definition fe_base.hpp:798
void ReorderLexToNative(int ncomp, Vector &dofs) const
Definition fe_base.cpp:996
Abstract operator.
Definition operator.hpp:27
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Definition operator.hpp:68
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
int NumCols() const
Get the number of columns (size of input) of the Operator. Synonym with Width().
Definition operator.hpp:77
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
Definition operator.hpp:74
Type
Ordering methods:
Definition ordering.hpp:17
Abstract parallel finite element space.
Definition pfespace.hpp:31
MPI_Comm GetComm() const
Definition pfespace.hpp:337
ParMesh * GetParMesh() const
Definition pfespace.hpp:341
void Update(bool want_transform=true) override
Class for parallel grid function.
Definition pgridfunc.hpp:50
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...
void GetDerivative(int comp, int der_comp, ParGridFunction &der) const
Parallel version of GridFunction::GetDerivative(); see its documentation.
ParFiniteElementSpace * ParFESpace() const
void Update() override
Transform by the Space UpdateMatrix (e.g., on Mesh change).
Definition pgridfunc.cpp:97
Class for parallel meshes.
Definition pmesh.hpp:35
virtual real_t GetDerefinementElementEnergy(const FiniteElement &el, ElementTransformation &T, const Vector &elfun)
Definition tmop.cpp:6245
void AssembleGradPA(const Vector &, const FiniteElementSpace &) override
Prepare the integrator for partial assembly (PA) gradient evaluations on the given FE space fes at th...
Definition tmop.cpp:6298
void EnableAdaptiveLimiting(const GridFunction &z0, Coefficient &coeff, AdaptivityEvaluator &ae, real_t delta_max=1.0)
Adds the adaptive limiting term to the first integrator.
Definition tmop.cpp:6138
void AssembleGradDiagonalPA(Vector &) const override
Method for computing the diagonal of the gradient with partial assembly.
Definition tmop.cpp:6307
real_t GetLocalStateEnergyPA(const Vector &) const override
Compute the local (to the MPI rank) energy with partial assembly.
Definition tmop.cpp:6331
void AddMultPA(const Vector &, Vector &) const override
Method for partially assembled action.
Definition tmop.cpp:6315
void ParEnableNormalization(const ParGridFunction &x)
Definition tmop.cpp:6274
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:6117
void AssembleElementGrad(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, DenseMatrix &elmat) override
Assemble the local gradient matrix.
Definition tmop.cpp:6216
real_t GetElementEnergy(const FiniteElement &el, ElementTransformation &T, const Vector &elfun) override
Compute the local energy.
Definition tmop.cpp:6188
void AddMultGradPA(const Vector &, Vector &) const override
Method for partially assembled gradient action.
Definition tmop.cpp:6323
virtual real_t GetRefinementElementEnergy(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, const IntegrationRule &irule)
Definition tmop.cpp:6232
void AssemblePA(const FiniteElementSpace &) override
Method defining partial assembly.
Definition tmop.cpp:6290
Array< TMOP_Integrator * > tmopi
Definition tmop.hpp:2615
void AssembleElementVector(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, Vector &elvect) override
Perform the local action of the NonlinearFormIntegrator.
Definition tmop.cpp:6200
void EnableNormalization(const GridFunction &x)
Normalization factor that considers all integrators in the combination.
Definition tmop.cpp:6258
void SetLimitingNodes(const GridFunction &n0)
Update the original/reference nodes used for limiting.
Definition tmop.cpp:6180
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 ...
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:2167
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:2193
void EvalPW(const DenseMatrix &Jpt, DenseMatrix &PW) const override
Definition tmop.cpp:2187
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:2181
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:2218
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:2230
void EvalPW(const DenseMatrix &Jpt, DenseMatrix &PW) const override
Definition tmop.cpp:2224
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:2204
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:2241
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:2267
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:2255
void EvalPW(const DenseMatrix &Jpt, DenseMatrix &PW) const override
Definition tmop.cpp:2261
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:2292
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:2304
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:2278
void EvalPW(const DenseMatrix &Jpt, DenseMatrix &PW) const override
Definition tmop.cpp:2298
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:2329
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:2315
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:2341
void EvalPW(const DenseMatrix &Jpt, DenseMatrix &PW) const override
Definition tmop.cpp:2335
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:2352
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:2366
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:2378
void EvalPW(const DenseMatrix &Jpt, DenseMatrix &PW) const override
Definition tmop.cpp:2372
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:595
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:537
void GetLocalEnergyPA_3D(const GridFunction &nodes, const TargetConstructor &tc, int m_index, real_t &energy, real_t &vol, const IntegrationRule &ir) const
void GetLocalEnergyPA_2D(const GridFunction &nodes, const TargetConstructor &tc, int m_index, real_t &energy, real_t &vol, const IntegrationRule &ir) const
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:547
void ComputeAvgMetrics(const GridFunction &nodes, const TargetConstructor &tc, Vector &averages, bool use_pa=false, const IntegrationRule *IntRule=nullptr) const
Definition tmop.cpp:639
AD2Type EvalW_AD2(const std::vector< AD2Type > &T, const std::vector< AD2Type > &W) const override
Second-derivative hook for AD-based computations.
Definition tmop.cpp:583
void ComputeBalancedWeights(const GridFunction &nodes, const TargetConstructor &tc, Vector &weights, bool use_pa=false, const IntegrationRule *IntRule=nullptr) const
Definition tmop.cpp:609
AD1Type EvalW_AD1(const std::vector< AD1Type > &T, const std::vector< AD1Type > &W) const override
First-derivative hook for AD-based computations.
Definition tmop.cpp:571
Array< TMOP_QualityMetric * > tmop_q_arr
Definition tmop.hpp:118
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:527
void EvalPW(const DenseMatrix &Jpt, DenseMatrix &P) const override
Definition tmop.cpp:559
real_t ComputeUntanglerMaxMuBarrier(const Vector &x, const FiniteElementSpace &fes)
Definition tmop.cpp:6007
void UpdateAfterMeshPositionChange(const Vector &d, const FiniteElementSpace &d_fes)
Definition tmop.cpp:5803
DenseMatrix Jpr
Definition tmop.hpp:2094
void AssembleElemVecAdaptLim(const FiniteElement &el, IsoparametricTransformation &Tpr, const IntegrationRule &ir, const Vector &weights, DenseMatrix &mat)
Definition tmop.cpp:4973
void AssembleElemGradAdaptLim(const FiniteElement &el, IsoparametricTransformation &Tpr, const IntegrationRule &ir, const Vector &weights, DenseMatrix &m)
Definition tmop.cpp:5019
void GetNormalizationFactors(real_t &metric_normal, real_t &lim_normal, real_t &surf_fit_normal)
Get the normalization factors of the metric.
Definition tmop.cpp:5541
TMOP_LimiterFunction * lim_func
Definition tmop.hpp:2036
void ComputeAllElementTargets(const Vector &xe=Vector()) const
Definition pa.cpp:172
void ParUpdateAfterMeshTopologyChange()
Definition tmop.cpp:4272
DenseMatrix PMatO
Definition tmop.hpp:2094
TMOP_QualityMetric * metric
Definition tmop.hpp:2015
void GetSurfaceFittingErrors(const Vector &d_loc, real_t &err_avg, real_t &err_max)
Definition tmop.cpp:4168
real_t ComputeMinDetT(const Vector &x, const FiniteElementSpace &fes)
Definition tmop.cpp:5964
AdaptivityEvaluator * surf_fit_eval
Definition tmop.hpp:2058
void EnableNormalization(const GridFunction &x)
Computes the normalization factors of the metric and limiting integrals using the mesh position given...
Definition tmop.cpp:5519
void ComputeMinJac(const Vector &x, const FiniteElementSpace &fes)
Definition tmop.cpp:5640
void AssembleElementVectorExact(const FiniteElement &el, ElementTransformation &T, const Vector &d_el, Vector &elvect)
Definition tmop.cpp:4667
TMOP_QualityMetric * h_metric
Definition tmop.hpp:2014
void AssembleElementGradFD(const FiniteElement &el, ElementTransformation &T, const Vector &d_el, DenseMatrix &elmat)
Definition tmop.cpp:5387
DiscreteAdaptTC * discr_tc
Definition tmop.hpp:2068
Coefficient * lim_coeff
Definition tmop.hpp:2032
GridFunction * surf_fit_gf
Definition tmop.hpp:2057
const GridFunction * lim_dist
Definition tmop.hpp:2034
struct mfem::TMOP_Integrator::@25 PA
Array< Vector * > ElemPertEnergy
Definition tmop.hpp:2082
void ComputeUntangleMetricQuantiles(const Vector &d, const FiniteElementSpace &fes)
Definition tmop.cpp:6069
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:4093
const TargetConstructor * targetC
Definition tmop.hpp:2016
AdaptivityEvaluator * surf_fit_eval_grad
Definition tmop.hpp:2064
const GridFunction * lim_nodes0
Definition tmop.hpp:2031
Array< Coefficient * > adapt_lim_coeff
Definition tmop.hpp:2049
const IntegrationRule * ir
Definition tmop.hpp:2159
TMOP_QuadraticLimiter * surf_fit_limiter
Definition tmop.hpp:2060
void EnableFiniteDifferences(const GridFunction &x)
Enables FD-based approximation and computes dx.
Definition tmop.cpp:5910
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:4498
real_t GetSurfaceFittingWeight()
Get the surface fitting weight.
Definition tmop.cpp:5508
void SetInitialMeshPos(const GridFunction *x0)
Definition tmop.cpp:3741
DenseMatrix DSh
Definition tmop.hpp:2094
const GridFunction * surf_fit_pos
Definition tmop.hpp:2061
Array< int > surf_fit_marker_dof_index
Definition tmop.hpp:2066
DenseTensor Jtr
Definition tmop.hpp:2148
void ParEnableNormalization(const ParGridFunction &x)
Definition tmop.cpp:5528
real_t GetElementEnergy(const FiniteElement &el, ElementTransformation &T, const Vector &d_el) override
Computes the integral of W(Jacobian(Trt)) over a target zone.
Definition tmop.cpp:4303
const FiniteElementSpace * fes
Definition tmop.hpp:2158
const IntegrationRule & EnergyIntegrationRule(const FiniteElement &el) const
Definition tmop.hpp:2219
GridFunction * surf_fit_grad
Definition tmop.hpp:2063
GridFunction * surf_fit_hess
Definition tmop.hpp:2063
void ReleasePADeviceMemory(bool copy_to_host=true)
Definition tmop.cpp:3727
virtual real_t GetDerefinementElementEnergy(const FiniteElement &el, ElementTransformation &T, const Vector &elfun)
Definition tmop.cpp:4584
void AssembleElementGrad(const FiniteElement &el, ElementTransformation &T, const Vector &d_el, DenseMatrix &elmat) override
Second derivative of GetElementEnergy() w.r.t. each local H1 DOF.
Definition tmop.cpp:4652
void AssembleElementVectorFD(const FiniteElement &el, ElementTransformation &T, const Vector &d_el, Vector &elvect)
Definition tmop.cpp:5309
Array< GridFunction * > adapt_lim_gf0
Definition tmop.hpp:2046
DenseMatrix PMatI
Definition tmop.hpp:2094
const IntegrationRule & GradientIntegrationRule(const FiniteElement &el) const
Definition tmop.hpp:2233
AdaptivityEvaluator * surf_fit_eval_hess
Definition tmop.hpp:2064
Coefficient * metric_coeff
Definition tmop.hpp:2024
Array< GridFunction * > adapt_lim_gf
Definition tmop.hpp:2047
void GetLocalNormalizationEnergiesPA_3D(const Vector &x, real_t &met_energy, real_t &lim_energy) const
const GridFunction * x_0
Definition tmop.hpp:2011
real_t GetFDDerivative(const FiniteElement &el, ElementTransformation &T, Vector &d_el, const int nodenum, const int idir, const real_t baseenergy, bool update_stored)
Definition tmop.cpp:5287
void UpdateAfterMeshTopologyChange()
Definition tmop.cpp:4242
void ComputeNormalizationEnergies(const GridFunction &x, real_t &metric_energy, real_t &lim_energy)
Definition tmop.cpp:5550
Vector adapt_lim_init_nodes
Definition tmop.hpp:2048
void RemapSurfaceFittingLevelSetAtNodes(const Vector &new_x, int new_x_ordering)
Definition tmop.cpp:5674
DenseMatrix Jrt
Definition tmop.hpp:2094
void UpdateCoefficientsPA(const Vector &d_loc)
Definition pa.cpp:189
Coefficient * surf_fit_coeff
Definition tmop.hpp:2055
Array< int > surf_fit_dof_count
Definition tmop.hpp:2065
DenseMatrix Jpt
Definition tmop.hpp:2094
Array< real_t > adapt_lim_delta_max
Definition tmop.hpp:2051
void AssembleElementGradExact(const FiniteElement &el, ElementTransformation &T, const Vector &d_el, DenseMatrix &elmat)
Definition tmop.cpp:4843
void EnableAdaptiveLimiting(const GridFunction &z0, Coefficient &coeff, AdaptivityEvaluator &ae, real_t delta_max=1.0)
Restriction of the node positions to certain regions.
Definition tmop.cpp:3799
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:3927
void AssembleElemGradSurfFit(const FiniteElement &el_x, IsoparametricTransformation &Tpr, DenseMatrix &mat)
Definition tmop.cpp:5172
void AssembleElementVector(const FiniteElement &el, ElementTransformation &T, const Vector &d_el, Vector &elvect) override
First defivative of GetElementEnergy() w.r.t. each local H1 DOF.
Definition tmop.cpp:4638
void UpdateSurfaceFittingWeight(real_t factor)
Update the surface fitting weight as surf_fit_coeff *= factor;.
Definition tmop.cpp:5496
Array< Vector * > ElemDer
Definition tmop.hpp:2081
const Array< bool > * surf_fit_marker
Definition tmop.hpp:2054
const IntegrationRule & ActionIntegrationRule(const FiniteElement &el) const
Definition tmop.hpp:2228
AdaptivityEvaluator * adapt_lim_eval
Definition tmop.hpp:2050
void ComputeFDh(const Vector &d, const FiniteElementSpace &fes)
Determines the perturbation, h, for FD-based approximation.
Definition tmop.cpp:5888
void AssembleElemVecSurfFit(const FiniteElement &el_x, IsoparametricTransformation &Tpr, DenseMatrix &mat)
Definition tmop.cpp:5091
void EnableLimiting(const GridFunction &n0, const GridFunction &dist, Coefficient &w0, TMOP_LimiterFunction *lfunc=NULL)
Limiting of the mesh displacements (general version).
Definition tmop.cpp:3774
void GetLocalNormalizationEnergiesPA_2D(const Vector &x, real_t &met_energy, real_t &lim_energy) const
Base class for limiting functions to be used in class TMOP_Integrator.
Definition tmop.hpp:1401
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.
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:829
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:292
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:823
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:817
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:988
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:377
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:976
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:971
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:982
AD1Type EvalW_AD1(const std::vector< AD1Type > &T, const std::vector< AD1Type > &W) const override
First-derivative hook for AD-based computations.
Definition tmop.cpp:1029
AD2Type EvalW_AD2(const std::vector< AD2Type > &T, const std::vector< AD2Type > &W) const override
Second-derivative hook for AD-based computations.
Definition tmop.cpp:1035
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:998
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1004
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:399
type EvalW_AD_impl(const std::vector< type > &T, const std::vector< type > &W) const
Definition tmop.cpp:1023
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1010
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1056
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1041
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1048
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:427
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1098
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1081
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:445
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1089
AD2Type EvalW_AD2(const std::vector< AD2Type > &T, const std::vector< AD2Type > &W) const override
Second-derivative hook for AD-based computations.
Definition tmop.cpp:1175
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1123
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:463
AD1Type EvalW_AD1(const std::vector< AD1Type > &T, const std::vector< AD1Type > &W) const override
First-derivative hook for AD-based computations.
Definition tmop.cpp:1169
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:1114
type EvalW_AD_impl(const std::vector< type > &T, const std::vector< type > &W) const
Definition tmop.cpp:1163
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1146
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1134
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1201
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:495
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1211
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1181
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:516
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1260
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1249
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:1238
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1268
AD2Type EvalW_AD2(const std::vector< AD2Type > &T, const std::vector< AD2Type > &W) const override
Second-derivative hook for AD-based computations.
Definition tmop.cpp:1323
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1281
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:538
type EvalW_AD_impl(const std::vector< type > &T, const std::vector< type > &W) const
Definition tmop.cpp:1311
AD1Type EvalW_AD1(const std::vector< AD1Type > &T, const std::vector< AD1Type > &W) const override
First-derivative hook for AD-based computations.
Definition tmop.cpp:1317
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1297
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1289
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1352
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:1329
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:568
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1344
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1336
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1377
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1385
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:589
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1393
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:1366
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:633
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1429
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:1406
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1420
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1412
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:1442
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1456
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1450
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1482
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1476
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:1468
const real_t eps
Definition tmop.hpp:753
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1507
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:754
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1502
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1493
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1523
InvariantsEvaluator2D< real_t > ie
Definition tmop.hpp:775
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1535
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1515
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:796
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1578
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1569
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1562
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:1553
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:1613
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1640
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:817
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1622
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1632
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1678
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:838
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:1656
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1670
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1663
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:1690
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1697
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:859
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1704
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1712
const real_t eps
Definition tmop.hpp:880
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1733
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1724
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1741
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:881
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1776
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:902
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1781
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1756
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1789
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1805
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:922
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1797
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1824
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1832
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:1818
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:940
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1840
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1877
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1869
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:961
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1861
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:1854
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1901
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:1891
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:982
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1912
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1923
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:1986
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:1970
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:1003
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:1949
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:1959
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:2023
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:2037
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:2030
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:1024
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:2046
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:2063
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:2071
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:2077
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:2108
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:2088
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:2096
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:1193
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:2131
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:2145
InvariantsEvaluator3D< real_t > ie
Definition tmop.hpp:1213
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:2138
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:2154
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:916
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:936
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:853
void EvalPW(const DenseMatrix &Jpt, DenseMatrix &PW) const override
Definition tmop.cpp:859
real_t EvalWMatrixForm(const DenseMatrix &Jpt) const override
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.cpp:839
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:865
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:876
Default limiter function in TMOP_Integrator.
Definition tmop.hpp:1422
void Eval_d1(const Vector &x, const Vector &x0, real_t dist, Vector &d1) const override
Returns the gradient of the limiting function f(x, x0, d) with respect to x.
Definition tmop.hpp:1431
void Eval_d2(const Vector &x, const Vector &x0, real_t dist, DenseMatrix &d2) const override
Returns the Hessian of the limiting function f(x, x0, d) with respect to x.
Definition tmop.hpp:1440
real_t Eval(const Vector &x, const Vector &x0, real_t dist) const override
Returns the limiting function, f(x, x0, d).
Definition tmop.hpp:1424
Abstract class for local mesh quality metrics in the target-matrix optimization paradigm (TMOP) by P....
Definition tmop.hpp:28
void DefaultAssembleH(const DenseTensor &H, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const
See AssembleH(). This is a default implementation for the case when the 2nd derivatives of the metric...
Definition tmop.cpp:492
const DenseMatrix * Jtr
Definition tmop.hpp:30
virtual void SetTargetJacobian(const DenseMatrix &Jtr_)
Specify the reference-element -> target-element Jacobian matrix for the point of interest.
Definition tmop.hpp:53
virtual AD1Type EvalW_AD1(const std::vector< AD1Type > &T, const std::vector< AD1Type > &W) const
First-derivative hook for AD-based computations.
Definition tmop.hpp:78
virtual AD2Type EvalW_AD2(const std::vector< AD2Type > &T, const std::vector< AD2Type > &W) const
Second-derivative hook for AD-based computations.
Definition tmop.hpp:86
virtual int Id() const
Return the metric ID.
Definition tmop.hpp:108
virtual void EvalPW(const DenseMatrix &Jpt, DenseMatrix &PW) const
Definition tmop.hpp:73
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,...
real_t EvalW(const DenseMatrix &Jpt) const override
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Definition tmop.cpp:726
AD1Type EvalW_AD1(const std::vector< AD1Type > &T, const std::vector< AD1Type > &W) const override
First-derivative hook for AD-based computations.
Definition tmop.cpp:759
void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const override
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition tmop.cpp:775
void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const real_t weight, DenseMatrix &A) const override
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition tmop.cpp:793
real_t EvalWBarrier(const DenseMatrix &Jpt) const
Definition tmop.cpp:743
AD2Type EvalW_AD2(const std::vector< AD2Type > &T, const std::vector< AD2Type > &W) const override
Second-derivative hook for AD-based computations.
Definition tmop.cpp:767
Base class representing target-matrix construction algorithms for mesh optimization via the target-ma...
Definition tmop.hpp:1586
const TargetType target_type
Definition tmop.hpp:1612
bool Parallel() const
Definition tmop.hpp:1659
void ComputeAvgVolume() const
Definition tmop.cpp:2389
virtual void ComputeElementTargetsGradient(const IntegrationRule &ir, const Vector &elfun, IsoparametricTransformation &Tpr, DenseTensor &dJtr) const
Definition tmop.cpp:2589
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:2518
bool UsesPhysicalCoordinates() const
Return true if the methods ComputeElementTargets(), ComputeAllElementTargets(), and ComputeElementTar...
Definition tmop.hpp:1683
const GridFunction * nodes
Definition tmop.hpp:1609
virtual bool ContainsVolumeInfo() const
Checks if the target matrices contain non-trivial size specification.
Definition tmop.cpp:2504
void ComputeAllElementTargets_Fallback(const FiniteElementSpace &fes, const IntegrationRule &ir, const Vector &xe, DenseTensor &Jtr) const
Definition tmop.cpp:2432
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:1353
Base class for vector Coefficients that optionally depend on time and space.
Vector data type.
Definition vector.hpp:82
void SetVector(const Vector &v, int offset)
(*this)[i + offset] = v[i]
Definition vector.cpp:353
virtual const real_t * HostRead() const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), false).
Definition vector.hpp:524
virtual const real_t * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
Definition vector.hpp:520
virtual real_t * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
Definition vector.hpp:536
void SetDataAndSize(real_t *d, int s)
Set the Vector data and size.
Definition vector.hpp:191
real_t Norml2() const
Returns the l2 norm of the vector.
Definition vector.cpp:968
int Size() const
Returns the size of the vector.
Definition vector.hpp:234
virtual void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
Definition vector.hpp:145
real_t Sum() const
Return the sum of the vector entries.
Definition vector.cpp:1246
void SetSize(int s)
Resize the vector to size s.
Definition vector.hpp:633
void NewDataAndSize(real_t *d, int s)
Set the Vector data and size, deleting the old data, if owned.
Definition vector.hpp:197
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
Definition vector.hpp:243
void SetData(real_t *d)
Definition vector.hpp:184
real_t Min() const
Returns the minimal element of the vector.
Definition vector.cpp:1154
void GetSubVector(const Array< int > &dofs, Vector &elemvect) const
Extract entries listed in dofs to the output Vector elemvect.
Definition vector.cpp:676
void MakeRef(Vector &base, int offset, int size)
Reset the Vector to be a reference to a sub-vector of base.
Definition vector.hpp:709
This file contains the declaration of a dual number class.
const real_t alpha
Definition ex15.cpp:369
int dim
Definition ex24.cpp:53
real_t omega
Definition ex25.cpp:142
real_t mu
Definition ex25.cpp:140
real_t a
Definition lissajous.cpp:41
real_t weight(const Vector &x)
type mu14_ad(const std::vector< type > &T, const std::vector< type > &W)
Definition tmop.cpp:154
void mult_aTa_2D(const std::vector< type > &in, std::vector< type > &outm)
Definition tmop.cpp:72
type nu51_ad(const std::vector< type > &T, const std::vector< type > &W)
Definition tmop.cpp:343
real_t u(const Vector &xvec)
Definition lor_mms.hpp:22
type make_one_type()
Definition tmop.cpp:197
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
Definition table.cpp:505
AD1Type make_one_type< AD1Type >()
Definition tmop.cpp:203
future::dual< AD1Type, AD1Type > AD2Type
MFEM native AD-type for second derivatives.
Definition tmop.cpp:27
void CalcAdjugateTranspose(const DenseMatrix &a, DenseMatrix &adjat)
Calculate the transposed adjugate of a matrix (for NxN matrices, N=1,2,3)
void add_3D(const scalartype &scalar, const std::vector< type > &u, const DenseMatrix *M, std::vector< type > &mat)
Definition tmop.cpp:124
Geometry Geometries
Definition fe.cpp:49
void ADGrad(std::function< AD1Type(std::vector< AD1Type > &, std::vector< AD1Type > &)>mu_ad, DenseMatrix &dmu, const DenseMatrix &X, const DenseMatrix *Y=nullptr, const bool dX=true)
Definition tmop.cpp:409
void add(const Vector &v1, const Vector &v2, Vector &v)
Definition vector.cpp:414
future::dual< real_t, real_t > AD1Type
MFEM native AD-type for first derivatives.
Definition tmop.cpp:25
void CalcInverse(const DenseMatrix &a, DenseMatrix &inva)
AD2Type make_one_type< AD2Type >()
Definition tmop.cpp:209
type mu98_ad(const std::vector< type > &T, const std::vector< type > &W)
Definition tmop.cpp:185
type wcuo_ad(type mu, const std::vector< type > &T, const std::vector< type > &W, real_t alpha, real_t min_detT, real_t detT_ep, int exponent, real_t max_muT, real_t muT_ep, TWCUO::BarrierType bt, TWCUO::WorstCaseType wct)
Definition tmop.cpp:216
type nu14_ad(const std::vector< type > &T, const std::vector< type > &W)
Definition tmop.cpp:291
void adjoint_2D(const std::vector< type > &in, std::vector< type > &outm)
Definition tmop.cpp:104
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:6341
void AddMultVWt(const Vector &v, const Vector &w, DenseMatrix &VWt)
VWt += v w^t.
type nu50_ad(const std::vector< type > &T, const std::vector< type > &W)
Definition tmop.cpp:318
void GetPeriodicPositions(const Vector &x_0, const Vector &dx, const FiniteElementSpace &fesL2, const FiniteElementSpace &fesH1, Vector &x)
type fnorm2_3D(const std::vector< type > &u)
Definition tmop.cpp:39
void AddMultABt(const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &ABt)
ABt += A * B^t.
type det_2D(const std::vector< type > &u)
Definition tmop.cpp:46
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)
type fnorm2_2D(const std::vector< type > &u)
Definition tmop.cpp:33
type mu55_ad(const std::vector< type > &T, const std::vector< type > &W)
Definition tmop.cpp:167
void ADHessian(std::function< AD2Type(std::vector< AD2Type > &, std::vector< AD2Type > &)> mu_ad, DenseTensor &d2mu_dX2, const DenseMatrix &X, const DenseMatrix *Y=nullptr)
Definition tmop.cpp:449
type nu11_ad(const std::vector< type > &T, const std::vector< type > &W)
Definition tmop.cpp:268
type skew2D_ad(const std::vector< type > &T, const std::vector< type > &W)
Definition tmop.cpp:385
type mu85_ad(const std::vector< type > &T, const std::vector< type > &W)
Definition tmop.cpp:175
type mu4_ad(const std::vector< type > &T, const std::vector< type > &W)
Definition tmop.cpp:145
ComplexDenseMatrix * MultAtB(const ComplexDenseMatrix &A, const ComplexDenseMatrix &B)
Multiply the complex conjugate transpose of a matrix A with a matrix B. A^H*B.
type mu342_ad(const std::vector< type > &T, const std::vector< type > &W)
Definition tmop.cpp:255
float real_t
Definition config.hpp:46
void AddMult(const DenseMatrix &b, const DenseMatrix &c, DenseMatrix &a)
Matrix matrix multiplication. A += B * C.
void transpose_2D(const std::vector< type > &in, std::vector< type > &outm)
Definition tmop.cpp:114
void mult_2D(const std::vector< type > &u, const std::vector< type > &M, std::vector< type > &mat)
Definition tmop.cpp:60
type det_3D(const std::vector< type > &u)
Definition tmop.cpp:52
ElementDofOrdering
Constants describing the possible orderings of the DOFs in one element.
Definition fespace.hpp:49
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:1134
void add_2D(const scalartype &scalar, const std::vector< type > &u, const DenseMatrix *M, std::vector< type > &mat)
Definition tmop.cpp:82
type nu107_ad(const std::vector< type > &T, const std::vector< type > &W)
Definition tmop.cpp:370
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:549
type nu36_ad(const std::vector< type > &T, const std::vector< type > &W)
Definition tmop.cpp:304
real_t p(const Vector &x, real_t t)
MFEM_HOST_DEVICE Complex exp(const Complex &q)
Helper struct to convert a C++ type to an MPI type.
Dual number struct (value plus gradient)
Definition dual.hpp:36
gradient_type gradient
the partial derivatives of value w.r.t. some other quantity
Definition dual.hpp:40
value_type value
the actual numerical value
Definition dual.hpp:38
std::array< int, NCMesh::MaxFaceNodes > nodes