MFEM v4.9.0
Finite element discretization library
Loading...
Searching...
No Matches
tmop.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#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());
836 ie.Assemble_ddI1(weight, A.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());
995 ie.Assemble_ddI1b(0.5*weight, A.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
1018 ie.Assemble_ddI1(weight, A.GetData());
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());
1108 ie.Assemble_TProd(weight, ie.Get_dI1(), ie.Get_dI2b(), A.GetData());
1109 ie.Assemble_ddI2b(weight*(ie.Get_I1()-4.0), A.GetData());
1110 ie.Assemble_ddI1(weight*ie.Get_I2b(), A.GetData());
1111 ie.Assemble_ddI1b(weight, 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());
1159 ie.Assemble_ddI1(weight, A.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());
1277 ie.Assemble_TProd(weight, ie.Get_dI1b(), A.GetData());
1278 ie.Assemble_ddI1b(weight*ie.Get_I1b(), A.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());
1306 ie.Assemble_TProd(2*weight, ie.Get_dI2b(), A.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());
1361 ie.Assemble_TProd(weight/(ie.Get_I2()*ie.Get_I2b()),
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());
1402 ie.Assemble_TProd(2*weight, ie.Get_dI1b(), A.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());
1687 ie.Assemble_ddI1b(weight/3., A.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));
1752 ie.Assemble_TProd(weight*c1, ie.Get_dI3b(), A.GetData());
1753 ie.Assemble_ddI3b(c2*weight, A.GetData());
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());
1814 ie.Assemble_TProd(2*weight, ie.Get_dI3b(), A.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());
1849 ie.Assemble_TProd(weight/(ie.Get_I3()*ie.Get_I3b()),
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();
1942 ie.Assemble_ddI1(weight, A.GetData());
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());
2164 ie.Assemble_ddI3b(-weight, 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 delete adapt_lim_gf;
3762 delete surf_fit_gf;
3763 delete surf_fit_limiter;
3764 delete surf_fit_grad;
3765 delete surf_fit_hess;
3766 for (int i = 0; i < ElemDer.Size(); i++)
3767 {
3768 delete ElemDer[i];
3769 delete ElemPertEnergy[i];
3770 }
3771}
3772
3774 const GridFunction &dist, Coefficient &w0,
3775 TMOP_LimiterFunction *lfunc)
3776{
3777 lim_nodes0 = &n0;
3778 lim_coeff = &w0;
3779 lim_dist = &dist;
3780 MFEM_VERIFY(lim_dist->FESpace()->GetVDim() == 1,
3781 "'dist' must be a scalar GridFunction!");
3782
3783 delete lim_func;
3784 lim_func = (lfunc) ? lfunc : new TMOP_QuadraticLimiter;
3785}
3786
3788 TMOP_LimiterFunction *lfunc)
3789{
3790 lim_nodes0 = &n0;
3791 lim_coeff = &w0;
3792 lim_dist = NULL;
3793
3794 delete lim_func;
3795 lim_func = (lfunc) ? lfunc : new TMOP_QuadraticLimiter;
3796}
3797
3799 Coefficient &coeff,
3801{
3802 adapt_lim_gf0 = &z0;
3803 delete adapt_lim_gf;
3804 adapt_lim_gf = new GridFunction(z0);
3805 adapt_lim_coeff = &coeff;
3806 adapt_lim_eval = &ae;
3807
3809 *z0.FESpace());
3812}
3813
3814#ifdef MFEM_USE_MPI
3816 Coefficient &coeff,
3818{
3819 adapt_lim_gf0 = &z0;
3820 adapt_lim_pgf0 = &z0;
3821 delete adapt_lim_gf;
3822 adapt_lim_gf = new GridFunction(z0);
3823 adapt_lim_coeff = &coeff;
3824 adapt_lim_eval = &ae;
3825
3827 *z0.ParFESpace());
3830}
3831#endif
3832
3834 const Array<bool> &smarker,
3835 Coefficient &coeff,
3837{
3838 // To have both we must duplicate the markers.
3839 MFEM_VERIFY(surf_fit_pos == NULL,
3840 "Using both fitting approaches is not supported.");
3841
3842 const bool per = s0.FESpace()->IsDGSpace();
3843 MFEM_VERIFY(per == false, "Fitting is not supported for periodic meshes.");
3844
3845 const int dim = s0.FESpace()->GetMesh()->Dimension();
3846 Mesh *mesh = s0.FESpace()->GetMesh();
3847 MFEM_VERIFY(mesh->GetNodes()->Size() == dim*s0.Size(),
3848 "Mesh and level-set polynomial order must be the same.");
3849 const H1_FECollection *fec = dynamic_cast<const H1_FECollection *>
3850 (s0.FESpace()->FEColl());
3851 MFEM_VERIFY(fec, "Only H1_FECollection is supported for the surface fitting "
3852 "grid function.");
3853
3854 delete surf_fit_gf;
3855 surf_fit_gf = new GridFunction(s0);
3857 surf_fit_marker = &smarker;
3858 surf_fit_coeff = &coeff;
3859 surf_fit_eval = &ae;
3860
3862 *s0.FESpace());
3865}
3866
3868 const Array<bool> &smarker,
3869 Coefficient &coeff)
3870{
3871 // To have both we must duplicate the markers.
3872 MFEM_VERIFY(surf_fit_gf == NULL,
3873 "Using both fitting approaches is not supported.");
3874 MFEM_VERIFY(pos.FESpace()->GetMesh()->GetNodes(),
3875 "Positions on a mesh without Nodes is not supported.");
3876 MFEM_VERIFY(pos.FESpace()->GetOrdering() ==
3877 pos.FESpace()->GetMesh()->GetNodes()->FESpace()->GetOrdering(),
3878 "Incompatible ordering of spaces!");
3879
3880 const bool per = pos.FESpace()->IsDGSpace();
3881 MFEM_VERIFY(per == false, "Fitting is not supported for periodic meshes.");
3882
3883 surf_fit_pos = &pos;
3885 surf_fit_marker = &smarker;
3886 surf_fit_coeff = &coeff;
3887 delete surf_fit_limiter;
3889}
3890
3891#ifdef MFEM_USE_MPI
3893 const Array<bool> &smarker,
3894 Coefficient &coeff,
3896 AdaptivityEvaluator *aegrad,
3897 AdaptivityEvaluator *aehess)
3898{
3899 // To have both we must duplicate the markers.
3900 MFEM_VERIFY(surf_fit_pos == NULL,
3901 "Using both fitting approaches is not supported.");
3902
3903 const bool per = s0.FESpace()->IsDGSpace();
3904 MFEM_VERIFY(per == false, "Fitting is not supported for periodic meshes.");
3905
3906 const int dim = s0.FESpace()->GetMesh()->Dimension();
3907 ParMesh *pmesh = s0.ParFESpace()->GetParMesh();
3908 MFEM_VERIFY(pmesh->GetNodes()->Size() == dim*s0.Size(),
3909 "Mesh and level-set polynomial order must be the same.");
3910 const H1_FECollection *fec = dynamic_cast<const H1_FECollection *>
3911 (s0.FESpace()->FEColl());
3912 MFEM_VERIFY(fec, "Only H1_FECollection is supported for the surface fitting "
3913 "grid function.");
3914
3915
3916 delete surf_fit_gf;
3917 surf_fit_gf = new GridFunction(s0);
3919 surf_fit_marker = &smarker;
3920 surf_fit_coeff = &coeff;
3921 surf_fit_eval = &ae;
3922
3923 surf_fit_eval->SetParMetaInfo(*pmesh, *s0.ParFESpace());
3926
3927 if (!aegrad) { return; }
3928
3929 MFEM_VERIFY(aehess, "AdaptivityEvaluator for Hessians must be provided too.");
3930
3932
3933 // FE space for gradients.
3934 delete surf_fit_grad;
3935 H1_FECollection *fec_grad = new H1_FECollection(fec->GetOrder(), dim,
3936 fec->GetBasisType());
3937 ParFiniteElementSpace *fes_grad = new ParFiniteElementSpace(pmesh, fec_grad,
3938 dim);
3939 // Initial gradients.
3940 surf_fit_grad = new GridFunction(fes_grad);
3941 surf_fit_grad->MakeOwner(fec_grad);
3942 for (int d = 0; d < dim; d++)
3943 {
3944 ParGridFunction surf_fit_grad_comp(fes, surf_fit_grad->GetData()+d*s0.Size());
3945 s0.GetDerivative(1, d, surf_fit_grad_comp);
3946 }
3947 surf_fit_eval_grad = aegrad;
3948 surf_fit_eval_grad->SetParMetaInfo(*pmesh, *fes_grad);
3950
3951 // FE space for Hessians.
3952 delete surf_fit_hess;
3953 H1_FECollection *fec_hess = new H1_FECollection(fec->GetOrder(), dim,
3954 fec->GetBasisType());
3955 ParFiniteElementSpace *fes_hess = new ParFiniteElementSpace(pmesh, fec_hess,
3956 dim*dim);
3957 // Initial Hessians.
3958 surf_fit_hess = new GridFunction(fes_hess);
3959 surf_fit_hess->MakeOwner(fec_hess);
3960 int id = 0;
3961 for (int d = 0; d < dim; d++)
3962 {
3963 for (int idir = 0; idir < dim; idir++)
3964 {
3965 ParGridFunction surf_fit_grad_comp(fes,
3966 surf_fit_grad->GetData()+d*s0.Size());
3967 ParGridFunction surf_fit_hess_comp(fes,
3968 surf_fit_hess->GetData()+id*s0.Size());
3969 surf_fit_grad_comp.GetDerivative(1, idir, surf_fit_hess_comp);
3970 id++;
3971 }
3972 }
3973 surf_fit_eval_hess = aehess;
3974 surf_fit_eval_hess->SetParMetaInfo(*pmesh, *fes_hess);
3976
3977 // Store DOF indices that are marked for fitting. Used to reduce work for
3978 // transferring information between source/background and current mesh.
3980#ifdef MFEM_USE_GSLIB
3981 if (dynamic_cast<InterpolatorFP *>(surf_fit_eval) &&
3982 dynamic_cast<InterpolatorFP *>(surf_fit_eval_grad) &&
3983 dynamic_cast<InterpolatorFP *>(surf_fit_eval_hess))
3984 {
3985 for (int i = 0; i < surf_fit_marker->Size(); i++)
3986 {
3987 if ((*surf_fit_marker)[i] == true)
3988 {
3990 }
3991 }
3992 }
3993#endif
3994
3995 *surf_fit_grad = 0.0;
3996 *surf_fit_hess = 0.0;
3997}
3998
4000 const ParGridFunction &s_bg, ParGridFunction &s0,
4001 const Array<bool> &smarker, Coefficient &coeff, AdaptivityEvaluator &ae,
4002 const ParGridFunction &s_bg_grad,
4003 ParGridFunction &s0_grad, AdaptivityEvaluator &age,
4004 const ParGridFunction &s_bg_hess,
4005 ParGridFunction &s0_hess, AdaptivityEvaluator &ahe)
4006{
4007#ifndef MFEM_USE_GSLIB
4008 MFEM_ABORT("Surface fitting from source requires GSLIB!");
4009#endif
4010
4011 const bool per = s0.FESpace()->IsDGSpace();
4012 MFEM_VERIFY(per == false, "Fitting is not supported for periodic meshes.");
4013
4014 // Setup for level set function
4015 delete surf_fit_gf;
4016 surf_fit_gf = new GridFunction(s0);
4017 surf_fit_marker = &smarker;
4018 surf_fit_coeff = &coeff;
4019 surf_fit_eval = &ae;
4021 *s_bg.ParFESpace());
4023 (*s_bg.FESpace()->GetMesh()->GetNodes(), s_bg);
4027 nodes->FESpace()->GetOrdering());
4028
4029 // Setup for gradient on background mesh
4030 MFEM_VERIFY(s_bg_grad.ParFESpace()->GetOrdering() ==
4031 s0_grad.ParFESpace()->GetOrdering(),
4032 "Nodal ordering for grid function on source mesh and current mesh"
4033 "should be the same.");
4034 delete surf_fit_grad;
4035 surf_fit_grad = new GridFunction(s0_grad);
4036 *surf_fit_grad = 0.0;
4037 surf_fit_eval_grad = &age;
4039 *s_bg_grad.ParFESpace());
4041 (*s_bg_grad.FESpace()->GetMesh()->GetNodes(), s_bg_grad);
4043
4044 // Setup for Hessian on background mesh
4045 MFEM_VERIFY(s_bg_hess.ParFESpace()->GetOrdering() ==
4046 s0_hess.ParFESpace()->GetOrdering(),
4047 "Nodal ordering for grid function on source mesh and current mesh"
4048 "should be the same.");
4049 delete surf_fit_hess;
4050 surf_fit_hess = new GridFunction(s0_hess);
4051 *surf_fit_hess = 0.0;
4052 surf_fit_eval_hess = &ahe;
4054 *s_bg_hess.ParFESpace());
4056 (*s_bg_hess.FESpace()->GetMesh()->GetNodes(), s_bg_hess);
4058
4059 // Count number of zones that share each of the DOFs
4061 // Store DOF indices that are marked for fitting. Used to reduce work for
4062 // transferring information between source/background and current mesh.
4064 for (int i = 0; i < surf_fit_marker->Size(); i++)
4065 {
4066 if ((*surf_fit_marker)[i] == true)
4067 {
4069 }
4070 }
4071}
4072#endif
4073
4075 real_t &err_avg, real_t &err_max)
4076{
4077 MFEM_VERIFY(periodic == false,
4078 "Fitting is not supported for periodic meshes.");
4079
4080 Vector pos(d_loc.Size());
4081 if (x_0) { add(*x_0, d_loc, pos); }
4082 else { pos = d_loc; }
4083
4084 MFEM_VERIFY(surf_fit_marker, "Surface fitting has not been enabled.");
4085
4086 const FiniteElementSpace *fes =
4088#ifdef MFEM_USE_MPI
4089 auto pfes = dynamic_cast<const ParFiniteElementSpace *>(fes);
4090 bool parallel = (pfes) ? true : false;
4091#endif
4092
4093 int dim = fes->GetMesh()->Dimension();
4094 const int node_cnt = surf_fit_marker->Size();
4095 err_max = 0.0;
4096 int dof_cnt = 0;
4097 real_t err_sum = 0.0;
4098 for (int i = 0; i < node_cnt; i++)
4099 {
4100 if ((*surf_fit_marker)[i] == false) { continue; }
4101
4102#ifdef MFEM_USE_MPI
4103 // Don't count the overlapping DOFs in parallel.
4104 // The pfes might be ordered byVDIM, while the loop goes consecutively.
4105 const int dof_i = pfes->DofToVDof(i, 0);
4106 if (parallel && pfes->GetLocalTDofNumber(dof_i) < 0) { continue; }
4107#endif
4108
4109 dof_cnt++;
4110 real_t sigma_s = 0.0;
4111 if (surf_fit_gf) { sigma_s = fabs((*surf_fit_gf)(i)); }
4112 if (surf_fit_pos)
4113 {
4114 Vector pos_s(dim), pos_s_target(dim);
4115 for (int d = 0; d < dim; d++)
4116 {
4117 pos_s(d) = (fes->GetOrdering() == Ordering::byNODES) ?
4118 pos(d*node_cnt + i) : pos(i*dim + d);
4119 pos_s_target(d) = (fes->GetOrdering() == Ordering::byNODES)
4120 ? (*surf_fit_pos)(d*node_cnt + i)
4121 : (*surf_fit_pos)(i*dim + d);
4122 }
4123 sigma_s = pos_s.DistanceTo(pos_s_target);
4124 }
4125
4126 err_max = std::max(err_max, sigma_s);
4127 err_sum += sigma_s;
4128 }
4129
4130#ifdef MFEM_USE_MPI
4131 if (parallel)
4132 {
4133 MPI_Comm comm = pfes->GetComm();
4134 MPI_Allreduce(MPI_IN_PLACE, &err_max, 1, MPITypeMap<real_t>::mpi_type, MPI_MAX,
4135 comm);
4136 MPI_Allreduce(MPI_IN_PLACE, &dof_cnt, 1, MPI_INT, MPI_SUM, comm);
4137 MPI_Allreduce(MPI_IN_PLACE, &err_sum, 1, MPITypeMap<real_t>::mpi_type, MPI_SUM,
4138 comm);
4139 }
4140#endif
4141
4142 err_avg = (dof_cnt > 0) ? err_sum / dof_cnt : 0.0;
4143}
4144
4156
4157#ifdef MFEM_USE_MPI
4169#endif
4170
4173 const Vector &d_el)
4174{
4175 const int dof = el.GetDof(), dim = el.GetDim();
4176 const int el_id = T.ElementNo;
4177
4178 // Form the Vector of node positions, depending on what's the input.
4179 Vector elfun;
4180 if (x_0)
4181 {
4182 // The input is the displacement.
4183 x_0->GetElementDofValues(el_id, elfun);
4184 if (periodic)
4185 {
4186 auto n_el = dynamic_cast<const NodalFiniteElement *>(&el);
4187 n_el->ReorderLexToNative(dim, elfun);
4188 }
4189 elfun += d_el;
4190 }
4191 else { elfun = d_el; }
4192
4193 real_t energy;
4194
4195 // No adaptive limiting / surface fitting terms if the function is called
4196 // as part of a FD derivative computation (because we include the exact
4197 // derivatives of these terms in FD computations).
4198 const bool adaptive_limiting = (adapt_lim_gf && fd_call_flag == false);
4199 const bool surface_fit = (surf_fit_marker && fd_call_flag == false);
4200
4201 DSh.SetSize(dof, dim);
4202 Jrt.SetSize(dim);
4203 Jpr.SetSize(dim);
4204 Jpt.SetSize(dim);
4205 PMatI.UseExternalData(elfun.GetData(), dof, dim);
4206
4208
4209 energy = 0.0;
4211 targetC->ComputeElementTargets(el_id, el, ir, elfun, Jtr);
4212
4213 // Limited case.
4214 Vector shape, p, p0, d_vals;
4215 DenseMatrix pos0;
4216 if (lim_coeff)
4217 {
4218 shape.SetSize(dof);
4219 p.SetSize(dim);
4220 p0.SetSize(dim);
4221 pos0.SetSize(dof, dim);
4222 Vector pos0V(pos0.Data(), dof * dim);
4223 Array<int> pos_dofs;
4224 lim_nodes0->FESpace()->GetElementVDofs(el_id, pos_dofs);
4225 lim_nodes0->GetSubVector(pos_dofs, pos0V);
4226 if (periodic)
4227 {
4228 auto n_el = dynamic_cast<const NodalFiniteElement *>(&el);
4229 n_el->ReorderLexToNative(dim, pos0V);
4230 }
4231 if (lim_dist)
4232 {
4233 lim_dist->GetValues(el_id, ir, d_vals);
4234 }
4235 else
4236 {
4237 d_vals.SetSize(ir.GetNPoints()); d_vals = 1.0;
4238 }
4239 }
4240
4241 // Define ref->physical transformation, when a Coefficient is specified.
4242 IsoparametricTransformation *Tpr = NULL;
4243 if (metric_coeff || lim_coeff || adaptive_limiting || surface_fit)
4244 {
4246 Tpr->SetFE(&el);
4247 Tpr->ElementNo = el_id;
4249 Tpr->Attribute = T.Attribute;
4250 Tpr->mesh = T.mesh;
4251 Tpr->GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
4252 }
4253 // TODO: computing the coefficients 'metric_coeff' and 'lim_coeff' in physical
4254 // coordinates means that, generally, the gradient and Hessian of the
4255 // TMOP_Integrator will depend on the derivatives of the coefficients.
4256 //
4257 // In some cases the coefficients are independent of any movement of
4258 // the physical coordinates (i.e. changes in 'elfun'), e.g. when the
4259 // coefficient is a ConstantCoefficient or a GridFunctionCoefficient.
4260
4261 Vector adapt_lim_gf_q, adapt_lim_gf0_q;
4262 if (adaptive_limiting)
4263 {
4264 adapt_lim_gf->GetValues(el_id, ir, adapt_lim_gf_q);
4265 adapt_lim_gf0->GetValues(el_id, ir, adapt_lim_gf0_q);
4266 }
4267
4268 for (int i = 0; i < ir.GetNPoints(); i++)
4269 {
4270 const IntegrationPoint &ip = ir.IntPoint(i);
4271
4273 CalcInverse(Jtr(i), Jrt);
4274 const real_t weight =
4275 (integ_over_target) ? ip.weight * Jtr(i).Det() : ip.weight;
4276
4277 el.CalcDShape(ip, DSh);
4278 MultAtB(PMatI, DSh, Jpr);
4279 Mult(Jpr, Jrt, Jpt);
4280
4282 if (metric_coeff) { val *= metric_coeff->Eval(*Tpr, ip); }
4283
4284 if (lim_coeff)
4285 {
4286 el.CalcShape(ip, shape);
4287 PMatI.MultTranspose(shape, p);
4288 pos0.MultTranspose(shape, p0);
4289 val += lim_normal *
4290 lim_func->Eval(p, p0, d_vals(i)) *
4291 lim_coeff->Eval(*Tpr, ip);
4292 }
4293
4294 // Contribution from the adaptive limiting term.
4295 if (adaptive_limiting)
4296 {
4297 const real_t diff = adapt_lim_gf_q(i) - adapt_lim_gf0_q(i);
4298 val += adapt_lim_coeff->Eval(*Tpr, ip) * lim_normal * diff * diff;
4299 }
4300
4301 energy += weight * val;
4302 }
4303
4304 // Contribution from the surface fitting term.
4305 if (surface_fit)
4306 {
4307 // Scalar for surf_fit_gf, vector for surf_fit_pos, but that's ok.
4308 const FiniteElementSpace *fes_fit =
4310 const IntegrationRule *ir_s = &fes_fit->GetFE(el_id)->GetNodes();
4311 Array<int> vdofs;
4312 fes_fit->GetElementVDofs(el_id, vdofs);
4313
4314 Vector sigma_e(dof);
4315 if (surf_fit_gf) { surf_fit_gf->GetSubVector(vdofs, sigma_e); }
4316
4317 for (int s = 0; s < dof; s++)
4318 {
4319 // Because surf_fit_pos.fes might be ordered byVDIM.
4320 const int scalar_dof_id = fes_fit->VDofToDof(vdofs[s]);
4321 if ((*surf_fit_marker)[scalar_dof_id] == false) { continue; }
4322
4323 const IntegrationPoint &ip_s = ir_s->IntPoint(s);
4324 Tpr->SetIntPoint(&ip_s);
4325 real_t w = surf_fit_coeff->Eval(*Tpr, ip_s) * surf_fit_normal *
4326 1.0 / surf_fit_dof_count[scalar_dof_id];
4327
4328 if (surf_fit_gf)
4329 {
4330 energy += w * sigma_e(s) * sigma_e(s);
4331 }
4332 if (surf_fit_pos)
4333 {
4334 // Fitting to exact positions.
4335 Vector pos(dim), pos_target(dim);
4336 for (int d = 0; d < dim; d++)
4337 {
4338 pos(d) = PMatI(s, d);
4339 pos_target(d) = (*surf_fit_pos)(vdofs[d*dof + s]);
4340 }
4341 energy += w * surf_fit_limiter->Eval(pos, pos_target, 1.0);
4342 }
4343 }
4344 }
4345
4346 delete Tpr;
4347 return energy;
4348}
4349
4352 const Vector &elfun,
4353 const IntegrationRule &irule)
4354{
4355 int dof = el.GetDof(), dim = el.GetDim(),
4356 NEsplit = elfun.Size() / (dof*dim), el_id = T.ElementNo;
4357 real_t energy = 0.;
4358
4359 TargetConstructor *tc = const_cast<TargetConstructor *>(targetC);
4360 DiscreteAdaptTC *dtc = dynamic_cast<DiscreteAdaptTC *>(tc);
4361 // For DiscreteAdaptTC the GridFunctions used to set the targets must be
4362 // mapped onto the fine elements.
4363 if (dtc) { dtc->SetTspecFromIntRule(el_id, irule); }
4364
4365 for (int e = 0; e < NEsplit; e++)
4366 {
4367 DSh.SetSize(dof, dim);
4368 Jrt.SetSize(dim);
4369 Jpr.SetSize(dim);
4370 Jpt.SetSize(dim);
4371 Vector elfun_child(dof*dim);
4372 for (int i = 0; i < dof; i++)
4373 {
4374 for (int d = 0; d < dim; d++)
4375 {
4376 // elfun is (xe1,xe2,...xen,ye1,ye2...yen) and has nodal coordinates
4377 // for all the children element of the parent element being considered.
4378 // So we must index and get (xek, yek) i.e. nodal coordinates for
4379 // the fine element being considered.
4380 elfun_child(i + d*dof) = elfun(i + e*dof + d*dof*NEsplit);
4381 }
4382 }
4383 PMatI.UseExternalData(elfun_child.GetData(), dof, dim);
4384
4386
4387 real_t el_energy = 0;
4389 if (dtc)
4390 {
4391 // This is used to index into the tspec vector inside DiscreteAdaptTC.
4393 }
4394 targetC->ComputeElementTargets(el_id, el, ir, elfun_child, Jtr);
4395
4396 // Define ref->physical transformation, wn a Coefficient is specified.
4397 IsoparametricTransformation *Tpr = NULL;
4398 if (metric_coeff || lim_coeff)
4399 {
4401 Tpr->SetFE(&el);
4402 Tpr->ElementNo = T.ElementNo;
4404 Tpr->Attribute = T.Attribute;
4405 Tpr->mesh = T.mesh;
4406 Tpr->GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
4407 }
4408
4409 for (int i = 0; i < ir.GetNPoints(); i++)
4410 {
4411 const IntegrationPoint &ip = ir.IntPoint(i);
4413 CalcInverse(Jtr(i), Jrt);
4414 const real_t weight =
4415 (integ_over_target) ? ip.weight * Jtr(i).Det() : ip.weight;
4416
4417 el.CalcDShape(ip, DSh);
4418 MultAtB(PMatI, DSh, Jpr);
4419 Mult(Jpr, Jrt, Jpt);
4420
4422 if (metric_coeff) { val *= metric_coeff->Eval(*Tpr, ip); }
4423
4424 el_energy += weight * val;
4425 delete Tpr;
4426 }
4427 energy += el_energy;
4428 }
4429 energy /= NEsplit;
4430
4431 if (dtc) { dtc->ResetRefinementTspecData(); }
4432
4433 return energy;
4434}
4435
4438 const Vector &elfun)
4439{
4440 int dof = el.GetDof(), dim = el.GetDim();
4441 real_t energy = 0.;
4442
4443 DSh.SetSize(dof, dim);
4444 Jrt.SetSize(dim);
4445 Jpr.SetSize(dim);
4446 Jpt.SetSize(dim);
4447 PMatI.UseExternalData(elfun.GetData(), dof, dim);
4448
4450
4451 energy = 0.0;
4453 targetC->ComputeElementTargets(T.ElementNo, el, ir, elfun, Jtr);
4454
4455 // Define ref->physical transformation, wn a Coefficient is specified.
4456 IsoparametricTransformation *Tpr = NULL;
4457 if (metric_coeff)
4458 {
4460 Tpr->SetFE(&el);
4461 Tpr->ElementNo = T.ElementNo;
4463 Tpr->Attribute = T.Attribute;
4464 Tpr->mesh = T.mesh;
4465 Tpr->GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
4466 }
4467
4468 for (int i = 0; i < ir.GetNPoints(); i++)
4469 {
4470 const IntegrationPoint &ip = ir.IntPoint(i);
4472 CalcInverse(Jtr(i), Jrt);
4473 const real_t weight =
4474 (integ_over_target) ? ip.weight * Jtr(i).Det() : ip.weight;
4475
4476 el.CalcDShape(ip, DSh);
4477 MultAtB(PMatI, DSh, Jpr);
4478 Mult(Jpr, Jrt, Jpt);
4479
4481 if (metric_coeff) { val *= metric_coeff->Eval(*Tpr, ip); }
4482
4483 energy += weight * val;
4484 }
4485
4486 delete Tpr;
4487 return energy;
4488}
4489
4492 const Vector &d_el, Vector &elvect)
4493{
4494 if (!fdflag)
4495 {
4496 AssembleElementVectorExact(el, T, d_el, elvect);
4497 }
4498 else
4499 {
4500 AssembleElementVectorFD(el, T, d_el, elvect);
4501 }
4502}
4503
4506 const Vector &d_el,
4507 DenseMatrix &elmat)
4508{
4509 if (!fdflag)
4510 {
4511 AssembleElementGradExact(el, T, d_el, elmat);
4512 }
4513 else
4514 {
4515 AssembleElementGradFD(el, T, d_el, elmat);
4516 }
4517}
4518
4521 const Vector &d_el,
4522 Vector &elvect)
4523{
4524 const int dof = el.GetDof(), dim = el.GetDim();
4525 const int el_id = T.ElementNo;
4526
4527 // Form the Vector of node positions, depending on what's the input.
4528 Vector elfun;
4529 if (x_0)
4530 {
4531 // The input is the displacement.
4532 x_0->GetElementDofValues(el_id, elfun);
4533 if (periodic)
4534 {
4535 auto n_el = dynamic_cast<const NodalFiniteElement *>(&el);
4536 n_el->ReorderLexToNative(dim, elfun);
4537 }
4538 elfun += d_el;
4539 }
4540 else { elfun = d_el; }
4541
4542 DenseMatrix Amat(dim), work1(dim), work2(dim);
4543 DSh.SetSize(dof, dim);
4544 DS.SetSize(dof, dim);
4545 Jrt.SetSize(dim);
4546 Jpt.SetSize(dim);
4547 P.SetSize(dim);
4548 PMatI.UseExternalData(elfun.GetData(), dof, dim);
4549 elvect.SetSize(dof*dim);
4550 PMatO.UseExternalData(elvect.GetData(), dof, dim);
4551
4553 const int nqp = ir.GetNPoints();
4554
4555 elvect = 0.0;
4556 Vector weights(nqp);
4557 DenseTensor Jtr(dim, dim, nqp);
4558 DenseTensor dJtr(dim, dim, dim*nqp);
4559 targetC->ComputeElementTargets(el_id, el, ir, elfun, Jtr);
4560
4561 // Limited case.
4562 DenseMatrix pos0;
4563 Vector shape, p, p0, d_vals, grad;
4564 shape.SetSize(dof);
4565 if (lim_coeff)
4566 {
4567 p.SetSize(dim);
4568 p0.SetSize(dim);
4569 pos0.SetSize(dof, dim);
4570 Vector pos0V(pos0.Data(), dof * dim);
4571 Array<int> pos_dofs;
4572 lim_nodes0->FESpace()->GetElementVDofs(el_id, pos_dofs);
4573 lim_nodes0->GetSubVector(pos_dofs, pos0V);
4574 if (periodic)
4575 {
4576 auto n_el = dynamic_cast<const NodalFiniteElement *>(&el);
4577 n_el->ReorderLexToNative(dim, pos0V);
4578 }
4579 if (lim_dist)
4580 {
4581 lim_dist->GetValues(el_id, ir, d_vals);
4582 }
4583 else
4584 {
4585 d_vals.SetSize(nqp); d_vals = 1.0;
4586 }
4587 }
4588
4589 // Define ref->physical transformation, when a Coefficient is specified.
4590 IsoparametricTransformation *Tpr = NULL;
4593 {
4595 Tpr->SetFE(&el);
4596 Tpr->ElementNo = el_id;
4598 Tpr->Attribute = T.Attribute;
4599 Tpr->mesh = T.mesh;
4600 Tpr->GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
4601 if (exact_action)
4602 {
4603 targetC->ComputeElementTargetsGradient(ir, elfun, *Tpr, dJtr);
4604 }
4605 }
4606
4607 Vector d_detW_dx(dim);
4608 Vector d_Winv_dx(dim);
4609
4610 for (int q = 0; q < nqp; q++)
4611 {
4612 const IntegrationPoint &ip = ir.IntPoint(q);
4614 CalcInverse(Jtr(q), Jrt);
4615 weights(q) = (integ_over_target) ? ip.weight * Jtr(q).Det() : ip.weight;
4616 real_t weight_m = weights(q) * metric_normal;
4617
4618 el.CalcDShape(ip, DSh);
4619 Mult(DSh, Jrt, DS);
4620 MultAtB(PMatI, DS, Jpt);
4621
4622 metric->EvalP(Jpt, P);
4623
4624 if (metric_coeff) { weight_m *= metric_coeff->Eval(*Tpr, ip); }
4625 P *= weight_m;
4626 AddMultABt(DS, P, PMatO); // w_q det(W) dmu/dx : dA/dx Winv
4627
4628 if (exact_action)
4629 {
4630 el.CalcShape(ip, shape);
4631 // Derivatives of adaptivity-based targets.
4632 // First term: w_q d*(Det W)/dx * mu(T)
4633 // d(Det W)/dx = det(W)*Tr[Winv*dW/dx]
4634 DenseMatrix dwdx(dim);
4635 for (int d = 0; d < dim; d++)
4636 {
4637 const DenseMatrix &dJtr_q = dJtr(q + d * nqp);
4638 Mult(Jrt, dJtr_q, dwdx);
4639 d_detW_dx(d) = dwdx.Trace();
4640 }
4641 d_detW_dx *= weight_m*metric->EvalW(Jpt); // *[w_q*det(W)]*mu(T)
4642
4643 // Second term: w_q det(W) dmu/dx : AdWinv/dx
4644 // dWinv/dx = -Winv*dW/dx*Winv
4645 MultAtB(PMatI, DSh, Amat);
4646 for (int d = 0; d < dim; d++)
4647 {
4648 const DenseMatrix &dJtr_q = dJtr(q + d*nqp);
4649 Mult(Jrt, dJtr_q, work1); // Winv*dw/dx
4650 Mult(work1, Jrt, work2); // Winv*dw/dx*Winv
4651 Mult(Amat, work2, work1); // A*Winv*dw/dx*Winv
4652 MultAtB(P, work1, work2); // dmu/dT^T*A*Winv*dw/dx*Winv
4653 d_Winv_dx(d) = work2.Trace(); // Tr[dmu/dT : AWinv*dw/dx*Winv]
4654 }
4655 d_Winv_dx *= -weight_m; // Include (-) factor as well
4656 d_detW_dx += d_Winv_dx;
4657
4658 AddMultVWt(shape, d_detW_dx, PMatO);
4659
4660 // For mu(T,W) we also need w_q dmu/dW:dW/dx det(W)
4661 // dmu/dW:dW/dx_i
4662 DenseMatrix PW(dim);
4663 Vector dmudxw(dim);
4664 metric->EvalPW(Jpt, PW);
4665 DenseMatrix Prod(dim);
4666
4667 for (int d = 0; d < dim; d++)
4668 {
4669 const DenseMatrix &dJtr_q = dJtr(q + d*nqp);
4670 Prod = 0.0;
4671 MultAtB(PW, dJtr_q, Prod); // dmu/dW:dW/dx_i
4672 dmudxw(d) = Prod.Trace();
4673 }
4674 dmudxw *= weight_m;
4675 AddMultVWt(shape, dmudxw, PMatO);
4676 }
4677
4678 if (lim_coeff)
4679 {
4680 if (!exact_action) { el.CalcShape(ip, shape); }
4681 PMatI.MultTranspose(shape, p);
4682 pos0.MultTranspose(shape, p0);
4683 lim_func->Eval_d1(p, p0, d_vals(q), grad);
4684 grad *= weights(q) * lim_normal * lim_coeff->Eval(*Tpr, ip);
4685 AddMultVWt(shape, grad, PMatO);
4686 }
4687 }
4688
4689 if (adapt_lim_gf) { AssembleElemVecAdaptLim(el, *Tpr, ir, weights, PMatO); }
4691
4692 delete Tpr;
4693}
4694
4697 const Vector &d_el,
4698 DenseMatrix &elmat)
4699{
4700 const int dof = el.GetDof(), dim = el.GetDim();
4701 const int el_id = T.ElementNo;
4702
4703 // Form the Vector of node positions, depending on what's the input.
4704 Vector elfun;
4705 if (x_0)
4706 {
4707 // The input is the displacement.
4708 x_0->GetElementDofValues(el_id, elfun);
4709 if (periodic)
4710 {
4711 auto n_el = dynamic_cast<const NodalFiniteElement *>(&el);
4712 n_el->ReorderLexToNative(dim, elfun);
4713 }
4714 elfun += d_el;
4715 }
4716 else { elfun = d_el; }
4717
4718 DSh.SetSize(dof, dim);
4719 DS.SetSize(dof, dim);
4720 Jrt.SetSize(dim);
4721 Jpt.SetSize(dim);
4722 PMatI.UseExternalData(elfun.GetData(), dof, dim);
4723 elmat.SetSize(dof*dim);
4724
4726 const int nqp = ir.GetNPoints();
4727
4728 elmat = 0.0;
4729 Vector weights(nqp);
4730 DenseTensor Jtr(dim, dim, nqp);
4731 targetC->ComputeElementTargets(el_id, el, ir, elfun, Jtr);
4732
4733 // Limited case.
4734 DenseMatrix pos0, hess;
4735 Vector shape, p, p0, d_vals;
4736 if (lim_coeff)
4737 {
4738 shape.SetSize(dof);
4739 p.SetSize(dim);
4740 p0.SetSize(dim);
4741 pos0.SetSize(dof, dim);
4742 Vector pos0V(pos0.Data(), dof * dim);
4743 Array<int> pos_dofs;
4744 lim_nodes0->FESpace()->GetElementVDofs(el_id, pos_dofs);
4745 lim_nodes0->GetSubVector(pos_dofs, pos0V);
4746 if (periodic)
4747 {
4748 auto n_el = dynamic_cast<const NodalFiniteElement *>(&el);
4749 n_el->ReorderLexToNative(dim, pos0V);
4750 }
4751 if (lim_dist)
4752 {
4753 lim_dist->GetValues(el_id, ir, d_vals);
4754 }
4755 else
4756 {
4757 d_vals.SetSize(nqp); d_vals = 1.0;
4758 }
4759 }
4760
4761 // Define ref->physical transformation, when a Coefficient is specified.
4762 IsoparametricTransformation *Tpr = NULL;
4764 {
4766 Tpr->SetFE(&el);
4767 Tpr->ElementNo = T.ElementNo;
4769 Tpr->Attribute = T.Attribute;
4770 Tpr->mesh = T.mesh;
4771 Tpr->GetPointMat().Transpose(PMatI);
4772 }
4773
4774 for (int q = 0; q < nqp; q++)
4775 {
4776 const IntegrationPoint &ip = ir.IntPoint(q);
4777 const DenseMatrix &Jtr_q = Jtr(q);
4778 metric->SetTargetJacobian(Jtr_q);
4779 CalcInverse(Jtr_q, Jrt);
4780 weights(q) = (integ_over_target) ? ip.weight * Jtr_q.Det() : ip.weight;
4781 real_t weight_m = weights(q) * metric_normal;
4782
4783 el.CalcDShape(ip, DSh);
4784 Mult(DSh, Jrt, DS);
4785 MultAtB(PMatI, DS, Jpt);
4786
4787 if (metric_coeff) { weight_m *= metric_coeff->Eval(*Tpr, ip); }
4788
4789 metric->AssembleH(Jpt, DS, weight_m, elmat);
4790
4791 // TODO: derivatives of adaptivity-based targets.
4792
4793 if (lim_coeff)
4794 {
4795 el.CalcShape(ip, shape);
4796 PMatI.MultTranspose(shape, p);
4797 pos0.MultTranspose(shape, p0);
4798 weight_m = weights(q) * lim_normal * lim_coeff->Eval(*Tpr, ip);
4799 lim_func->Eval_d2(p, p0, d_vals(q), hess);
4800 for (int i = 0; i < dof; i++)
4801 {
4802 const real_t w_shape_i = weight_m * shape(i);
4803 for (int j = 0; j < dof; j++)
4804 {
4805 const real_t w = w_shape_i * shape(j);
4806 for (int d1 = 0; d1 < dim; d1++)
4807 {
4808 for (int d2 = 0; d2 < dim; d2++)
4809 {
4810 elmat(d1*dof + i, d2*dof + j) += w * hess(d1, d2);
4811 }
4812 }
4813 }
4814 }
4815 }
4816 }
4817
4818 if (adapt_lim_gf) { AssembleElemGradAdaptLim(el, *Tpr, ir, weights, elmat); }
4819 if (surf_fit_gf || surf_fit_pos) { AssembleElemGradSurfFit(el, *Tpr, elmat);}
4820
4821 delete Tpr;
4822}
4823
4826 const IntegrationRule &ir,
4827 const Vector &weights,
4828 DenseMatrix &mat)
4829{
4830 const int dof = el.GetDof(), dim = el.GetDim(), nqp = weights.Size();
4831 Vector shape(dof), adapt_lim_gf_e, adapt_lim_gf_q, adapt_lim_gf0_q(nqp);
4832
4833 Array<int> dofs;
4835 adapt_lim_gf->GetSubVector(dofs, adapt_lim_gf_e);
4836 adapt_lim_gf->GetValues(Tpr.ElementNo, ir, adapt_lim_gf_q);
4837 adapt_lim_gf0->GetValues(Tpr.ElementNo, ir, adapt_lim_gf0_q);
4838
4839 // Project the gradient of adapt_lim_gf in the same space.
4840 // The FE coefficients of the gradient go in adapt_lim_gf_grad_e.
4841 DenseMatrix adapt_lim_gf_grad_e(dof, dim);
4842 DenseMatrix grad_phys; // This will be (dof x dim, dof).
4843 el.ProjectGrad(el, Tpr, grad_phys);
4844 Vector grad_ptr(adapt_lim_gf_grad_e.GetData(), dof*dim);
4845 grad_phys.Mult(adapt_lim_gf_e, grad_ptr);
4846
4847 Vector adapt_lim_gf_grad_q(dim);
4848
4849 for (int q = 0; q < nqp; q++)
4850 {
4851 const IntegrationPoint &ip = ir.IntPoint(q);
4852 el.CalcShape(ip, shape);
4853 adapt_lim_gf_grad_e.MultTranspose(shape, adapt_lim_gf_grad_q);
4854 adapt_lim_gf_grad_q *= 2.0 * (adapt_lim_gf_q(q) - adapt_lim_gf0_q(q));
4855 adapt_lim_gf_grad_q *= weights(q) * lim_normal * adapt_lim_coeff->Eval(Tpr, ip);
4856 AddMultVWt(shape, adapt_lim_gf_grad_q, mat);
4857 }
4858}
4859
4862 const IntegrationRule &ir,
4863 const Vector &weights,
4864 DenseMatrix &mat)
4865{
4866 const int dof = el.GetDof(), dim = el.GetDim(), nqp = weights.Size();
4867 Vector shape(dof), adapt_lim_gf_e, adapt_lim_gf_q, adapt_lim_gf0_q(nqp);
4868
4869 Array<int> dofs;
4871 adapt_lim_gf->GetSubVector(dofs, adapt_lim_gf_e);
4872 adapt_lim_gf->GetValues(Tpr.ElementNo, ir, adapt_lim_gf_q);
4873 adapt_lim_gf0->GetValues(Tpr.ElementNo, ir, adapt_lim_gf0_q);
4874
4875 // Project the gradient of adapt_lim_gf in the same space.
4876 // The FE coefficients of the gradient go in adapt_lim_gf_grad_e.
4877 DenseMatrix adapt_lim_gf_grad_e(dof, dim);
4878 DenseMatrix grad_phys; // This will be (dof x dim, dof).
4879 el.ProjectGrad(el, Tpr, grad_phys);
4880 Vector grad_ptr(adapt_lim_gf_grad_e.GetData(), dof*dim);
4881 grad_phys.Mult(adapt_lim_gf_e, grad_ptr);
4882
4883 // Project the gradient of each gradient of adapt_lim_gf in the same space.
4884 // The FE coefficients of the second derivatives go in adapt_lim_gf_hess_e.
4885 DenseMatrix adapt_lim_gf_hess_e(dof*dim, dim);
4886 Mult(grad_phys, adapt_lim_gf_grad_e, adapt_lim_gf_hess_e);
4887 // Reshape to be more convenient later (no change in the data).
4888 adapt_lim_gf_hess_e.SetSize(dof, dim*dim);
4889
4890 Vector adapt_lim_gf_grad_q(dim);
4891 DenseMatrix adapt_lim_gf_hess_q(dim, dim);
4892
4893 for (int q = 0; q < nqp; q++)
4894 {
4895 const IntegrationPoint &ip = ir.IntPoint(q);
4896 el.CalcShape(ip, shape);
4897
4898 adapt_lim_gf_grad_e.MultTranspose(shape, adapt_lim_gf_grad_q);
4899 Vector gg_ptr(adapt_lim_gf_hess_q.GetData(), dim*dim);
4900 adapt_lim_gf_hess_e.MultTranspose(shape, gg_ptr);
4901
4902 const real_t w = weights(q) * lim_normal * adapt_lim_coeff->Eval(Tpr, ip);
4903 for (int i = 0; i < dof * dim; i++)
4904 {
4905 const int idof = i % dof, idim = i / dof;
4906 for (int j = 0; j <= i; j++)
4907 {
4908 const int jdof = j % dof, jdim = j / dof;
4909 const real_t entry =
4910 w * ( 2.0 * adapt_lim_gf_grad_q(idim) * shape(idof) *
4911 /* */ adapt_lim_gf_grad_q(jdim) * shape(jdof) +
4912 2.0 * (adapt_lim_gf_q(q) - adapt_lim_gf0_q(q)) *
4913 adapt_lim_gf_hess_q(idim, jdim) * shape(idof) * shape(jdof));
4914 mat(i, j) += entry;
4915 if (i != j) { mat(j, i) += entry; }
4916 }
4917 }
4918 }
4919}
4920
4923 DenseMatrix &mat)
4924{
4925 const int el_id = Tpr.ElementNo;
4926
4927 // Scalar for surf_fit_gf, vector for surf_fit_pos, but that's ok.
4928 const FiniteElementSpace *fes_fit =
4930 const FiniteElement &el_s = *fes_fit->GetFE(el_id);
4931 const int dof_s = el_s.GetDof(), dim = el_x.GetDim();
4932
4933 // Check if the element has any DOFs marked for surface fitting.
4934 Array<int> dofs, vdofs;
4935 fes_fit->GetElementVDofs(el_id, vdofs);
4936 int count = 0;
4937 for (int s = 0; s < dof_s; s++)
4938 {
4939 // Because surf_fit_pos.fes might be ordered byVDIM.
4940 const int scalar_dof_id = fes_fit->VDofToDof(vdofs[s]);
4941 count += ((*surf_fit_marker)[scalar_dof_id]) ? 1 : 0;
4942 }
4943 if (count == 0) { return; }
4944
4945 Vector sigma_e(dof_s);
4946 DenseMatrix surf_fit_grad_e(dof_s, dim);
4947 if (surf_fit_gf)
4948 {
4949 surf_fit_gf->GetSubVector(vdofs, sigma_e);
4950
4951 // Project the gradient of sigma in the same space.
4952 // The FE coefficients of the gradient go in surf_fit_grad_e.
4953 Vector grad_ptr(surf_fit_grad_e.GetData(), dof_s * dim);
4954 DenseMatrix grad_phys; // This will be (dof x dim, dof).
4955 if (surf_fit_grad)
4956 {
4957 surf_fit_grad->FESpace()->GetElementVDofs(el_id, dofs);
4958 surf_fit_grad->GetSubVector(dofs, grad_ptr);
4959 }
4960 else
4961 {
4962 el_s.ProjectGrad(el_s, Tpr, grad_phys);
4963 grad_phys.Mult(sigma_e, grad_ptr);
4964 }
4965 }
4966 else { Tpr.GetPointMat().Transpose(PMatI); }
4967
4968 const IntegrationRule &ir = el_s.GetNodes();
4969
4970 for (int s = 0; s < dof_s; s++)
4971 {
4972 // Because surf_fit_pos.fes might be ordered byVDIM.
4973 const int scalar_dof_id = fes_fit->VDofToDof(vdofs[s]);
4974 if ((*surf_fit_marker)[scalar_dof_id] == false) { continue; }
4975
4976 const IntegrationPoint &ip = ir.IntPoint(s);
4977 Tpr.SetIntPoint(&ip);
4978 real_t w = surf_fit_normal * surf_fit_coeff->Eval(Tpr, ip) *
4979 1.0 / surf_fit_dof_count[vdofs[s]];
4980
4981 if (surf_fit_gf) { w *= 2.0 * sigma_e(s); }
4982 if (surf_fit_pos)
4983 {
4984 Vector pos(dim), pos_target(dim);
4985 for (int d = 0; d < dim; d++)
4986 {
4987 pos(d) = PMatI(s, d);
4988 pos_target(d) = (*surf_fit_pos)(vdofs[d*dof_s + s]);
4989 }
4990 Vector grad_s(dim);
4991 surf_fit_limiter->Eval_d1(pos, pos_target, 1.0, grad_s);
4992 for (int d = 0; d < dim; d++) { surf_fit_grad_e(s, d) = grad_s(d); }
4993 }
4994
4995 for (int d = 0; d < dim; d++)
4996 {
4997 mat(s, d) += w * surf_fit_grad_e(s, d);
4998 }
4999 }
5000}
5001
5004 DenseMatrix &mat)
5005{
5006 const int el_id = Tpr.ElementNo;
5007
5008 // Scalar for surf_fit_gf, vector for surf_fit_pos, but that's ok.
5009 const FiniteElementSpace *fes_fit =
5011 const FiniteElement &el_s = *fes_fit->GetFE(el_id);
5012 const int dof_s = el_s.GetDof(), dim = el_x.GetDim();
5013
5014 // Check if the element has any DOFs marked for surface fitting.
5015 Array<int> dofs, vdofs;
5016 fes_fit->GetElementVDofs(el_id, vdofs);
5017 int count = 0;
5018 for (int s = 0; s < dof_s; s++)
5019 {
5020 // Because surf_fit_pos.fes might be ordered byVDIM.
5021 const int scalar_dof_id = fes_fit->VDofToDof(vdofs[s]);
5022 count += ((*surf_fit_marker)[scalar_dof_id]) ? 1 : 0;
5023 }
5024 if (count == 0) { return; }
5025
5026 Vector sigma_e(dof_s);
5027 DenseMatrix surf_fit_grad_e(dof_s, dim);
5028 DenseMatrix surf_fit_hess_e(dof_s, dim*dim);
5029 if (surf_fit_gf)
5030 {
5031 surf_fit_gf->GetSubVector(vdofs, sigma_e);
5032
5033 // Project the gradient of sigma in the same space.
5034 // The FE coefficients of the gradient go in surf_fit_grad_e.
5035 Vector grad_ptr(surf_fit_grad_e.GetData(), dof_s * dim);
5036 DenseMatrix grad_phys; // This will be (dof x dim, dof).
5037 if (surf_fit_grad)
5038 {
5039 surf_fit_grad->FESpace()->GetElementVDofs(el_id, dofs);
5040 surf_fit_grad->GetSubVector(dofs, grad_ptr);
5041 }
5042 else
5043 {
5044 el_s.ProjectGrad(el_s, Tpr, grad_phys);
5045 grad_phys.Mult(sigma_e, grad_ptr);
5046 }
5047
5048 // Project the Hessian of sigma in the same space.
5049 // The FE coefficients of the Hessian go in surf_fit_hess_e.
5050 Vector hess_ptr(surf_fit_hess_e.GetData(), dof_s*dim*dim);
5051 if (surf_fit_hess)
5052 {
5053 surf_fit_hess->FESpace()->GetElementVDofs(el_id, dofs);
5054 surf_fit_hess->GetSubVector(dofs, hess_ptr);
5055 }
5056 else
5057 {
5058 surf_fit_hess_e.SetSize(dof_s*dim, dim);
5059 Mult(grad_phys, surf_fit_grad_e, surf_fit_hess_e);
5060 surf_fit_hess_e.SetSize(dof_s, dim * dim);
5061 }
5062 }
5063 else { Tpr.GetPointMat().Transpose(PMatI); }
5064
5065 const IntegrationRule &ir = el_s.GetNodes();
5066
5067 DenseMatrix surf_fit_hess_s(dim, dim);
5068 for (int s = 0; s < dof_s; s++)
5069 {
5070 // Because surf_fit_pos.fes might be ordered byVDIM.
5071 const int scalar_dof_id = fes_fit->VDofToDof(vdofs[s]);
5072 if ((*surf_fit_marker)[scalar_dof_id] == false) { continue; }
5073
5074 const IntegrationPoint &ip = ir.IntPoint(s);
5075 Tpr.SetIntPoint(&ip);
5076 real_t w = surf_fit_normal * surf_fit_coeff->Eval(Tpr, ip);
5077
5078 if (surf_fit_gf)
5079 {
5080 Vector gg_ptr(surf_fit_hess_s.GetData(), dim * dim);
5081 surf_fit_hess_e.GetRow(s, gg_ptr);
5082 w *= 2.0;
5083 }
5084 if (surf_fit_pos)
5085 {
5086 Vector pos(dim), pos_target(dim);
5087 for (int d = 0; d < dim; d++)
5088 {
5089 pos(d) = PMatI(s, d);
5090 pos_target(d) = (*surf_fit_pos)(vdofs[d*dof_s + s]);
5091 }
5092 // Eval_d2 returns the full Hessian, but we still use the general
5093 // computation that's in the dim x dim loop below.
5094 sigma_e(s) = 1.0;
5095 for (int d = 0; d < dim; d++) { surf_fit_grad_e(s, d) = 0.0; }
5096 surf_fit_limiter->Eval_d2(pos, pos_target, 1.0, surf_fit_hess_s);
5097 }
5098
5099 // Loops over the local matrix.
5100 for (int idim = 0; idim < dim; idim++)
5101 {
5102 for (int jdim = 0; jdim <= idim; jdim++)
5103 {
5104 real_t entry = w * ( surf_fit_grad_e(s, idim) *
5105 surf_fit_grad_e(s, jdim) +
5106 sigma_e(s) * surf_fit_hess_s(idim, jdim));
5107 entry *= 1.0 / surf_fit_dof_count[vdofs[s]];
5108 int idx = s + idim*dof_s;
5109 int jdx = s + jdim*dof_s;
5110 mat(idx, jdx) += entry;
5111 if (idx != jdx) { mat(jdx, idx) += entry; }
5112 }
5113 }
5114 }
5115}
5116
5119 Vector &d_el, const int dofidx,
5120 const int dir, const real_t e_fx,
5121 bool update_stored)
5122{
5123 int dof = el.GetDof();
5124 int idx = dir*dof+dofidx;
5125 d_el[idx] += fd_h;
5126 real_t e_fxph = GetElementEnergy(el, T, d_el);
5127 d_el[idx] -= fd_h;
5128 real_t dfdx = (e_fxph - e_fx) / fd_h;
5129
5130 if (update_stored)
5131 {
5132 (*(ElemPertEnergy[T.ElementNo]))(idx) = e_fxph;
5133 (*(ElemDer[T.ElementNo]))(idx) = dfdx;
5134 }
5135
5136 return dfdx;
5137}
5138
5141 const Vector &d_el,
5142 Vector &elvect)
5143{
5144 // Form the Vector of node positions, depending on what's the input.
5145 Vector elfun;
5146 if (x_0)
5147 {
5148 // The input is the displacement.
5150 elfun += d_el;
5151 }
5152 else { elfun = d_el; }
5153
5154 const int dof = el.GetDof(), dim = el.GetDim(), elnum = T.ElementNo;
5155 if (elnum >= ElemDer.Size())
5156 {
5157 ElemDer.Append(new Vector);
5158 ElemPertEnergy.Append(new Vector);
5159 ElemDer[elnum]->SetSize(dof*dim);
5160 ElemPertEnergy[elnum]->SetSize(dof*dim);
5161 }
5162
5163 elvect.SetSize(dof*dim);
5164
5165 // In GetElementEnergy(), skip terms that have exact derivative calculations.
5166 fd_call_flag = true;
5167
5168 // Energy for unperturbed configuration.
5169 const real_t e_fx = GetElementEnergy(el, T, d_el);
5170
5171 Vector d_el_mod(d_el);
5172 for (int j = 0; j < dim; j++)
5173 {
5174 for (int i = 0; i < dof; i++)
5175 {
5176 if (discr_tc)
5177 {
5179 el, T, i, j, discr_tc->GetTspecPert1H());
5180 }
5181 elvect(j*dof+i) = GetFDDerivative(el, T, d_el_mod, i, j, e_fx, true);
5183 }
5184 }
5185 fd_call_flag = false;
5186
5187 // Contributions from adaptive limiting, surface fitting (exact derivatives).
5189 {
5191 const int nqp = ir.GetNPoints();
5192 DenseTensor Jtr(dim, dim, nqp);
5193 targetC->ComputeElementTargets(T.ElementNo, el, ir, elfun, Jtr);
5194
5196 Tpr.SetFE(&el);
5197 Tpr.ElementNo = T.ElementNo;
5198 Tpr.Attribute = T.Attribute;
5199 Tpr.mesh = T.mesh;
5200 PMatI.UseExternalData(elfun.GetData(), dof, dim);
5201 Tpr.GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
5202
5203 Vector weights(nqp);
5204 for (int q = 0; q < nqp; q++)
5205 {
5206 weights(q) = (integ_over_target) ?
5207 ir.IntPoint(q).weight * Jtr(q).Det() :
5208 ir.IntPoint(q).weight;
5209 }
5210
5211 PMatO.UseExternalData(elvect.GetData(), dof, dim);
5212 if (adapt_lim_gf) { AssembleElemVecAdaptLim(el, Tpr, ir, weights, PMatO); }
5214 }
5215}
5216
5219 const Vector &d_el,
5220 DenseMatrix &elmat)
5221{
5222 // Form the Vector of node positions, depending on what's the input.
5223 Vector elfun;
5224 if (x_0)
5225 {
5226 // The input is the displacement.
5228 elfun += d_el;
5229 }
5230 else { elfun = d_el; }
5231
5232 const int dof = el.GetDof(), dim = el.GetDim();
5233
5234 elmat.SetSize(dof*dim);
5235
5236 const Vector &ElemDerLoc = *(ElemDer[T.ElementNo]);
5237 const Vector &ElemPertLoc = *(ElemPertEnergy[T.ElementNo]);
5238
5239 // In GetElementEnergy(), skip terms that have exact derivative calculations.
5240 Vector d_el_mod(d_el);
5241 fd_call_flag = true;
5242 for (int i = 0; i < dof; i++)
5243 {
5244 for (int j = 0; j < i+1; j++)
5245 {
5246 for (int k1 = 0; k1 < dim; k1++)
5247 {
5248 for (int k2 = 0; k2 < dim; k2++)
5249 {
5250 d_el_mod(k2 * dof + j) += fd_h;
5251
5252 if (discr_tc)
5253 {
5255 el, T, j, k2, discr_tc->GetTspecPert1H());
5256 if (j != i)
5257 {
5259 el, T, i, k1, discr_tc->GetTspecPert1H());
5260 }
5261 else // j==i
5262 {
5263 if (k1 != k2)
5264 {
5265 int idx = k1+k2-1;
5267 el, T, i, idx, discr_tc->GetTspecPertMixH());
5268 }
5269 else // j==i && k1==k2
5270 {
5272 el, T, i, k1, discr_tc->GetTspecPert2H());
5273 }
5274 }
5275 }
5276
5277 real_t e_fx = ElemPertLoc(k2 * dof + j);
5278 real_t e_fpxph = GetFDDerivative(el, T, d_el_mod, i, k1, e_fx,
5279 false);
5280 d_el_mod(k2 * dof + j) -= fd_h;
5281 real_t e_fpx = ElemDerLoc(k1*dof+i);
5282
5283 elmat(k1*dof+i, k2*dof+j) = (e_fpxph - e_fpx) / fd_h;
5284 elmat(k2*dof+j, k1*dof+i) = (e_fpxph - e_fpx) / fd_h;
5285
5286 if (discr_tc)
5287 {
5290 }
5291 }
5292 }
5293 }
5294 }
5295 fd_call_flag = false;
5296
5297 // Contributions from adaptive limiting.
5299 {
5301 const int nqp = ir.GetNPoints();
5302 DenseTensor Jtr(dim, dim, nqp);
5303 targetC->ComputeElementTargets(T.ElementNo, el, ir, elfun, Jtr);
5304
5306 Tpr.SetFE(&el);
5307 Tpr.ElementNo = T.ElementNo;
5308 Tpr.Attribute = T.Attribute;
5309 Tpr.mesh = T.mesh;
5310 PMatI.UseExternalData(elfun.GetData(), dof, dim);
5311 Tpr.GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
5312
5313 Vector weights(nqp);
5314 for (int q = 0; q < nqp; q++)
5315 {
5316 weights(q) = (integ_over_target) ?
5317 ir.IntPoint(q).weight * Jtr(q).Det() :
5318 ir.IntPoint(q).weight;
5319 }
5320
5321 if (adapt_lim_gf) { AssembleElemGradAdaptLim(el, Tpr, ir, weights, elmat); }
5322 if (surf_fit_gf || surf_fit_pos) { AssembleElemGradSurfFit(el, Tpr, elmat); }
5323 }
5324}
5325
5327{
5328 if (!surf_fit_coeff) { return; }
5329
5330 if (surf_fit_coeff)
5331 {
5332 auto cf = dynamic_cast<ConstantCoefficient *>(surf_fit_coeff);
5333 MFEM_VERIFY(cf, "Dynamic weight works only with a ConstantCoefficient.");
5334 cf->constant *= factor;
5335 }
5336}
5337
5339{
5340 if (surf_fit_coeff)
5341 {
5342 auto cf = dynamic_cast<ConstantCoefficient *>(surf_fit_coeff);
5343 MFEM_VERIFY(cf, "Dynamic weight works only with a ConstantCoefficient.");
5344 return cf->constant;
5345 }
5346 return 0.0;
5347}
5348
5356
5357#ifdef MFEM_USE_MPI
5359{
5360 real_t loc[2];
5361 ComputeNormalizationEnergies(x, loc[0], loc[1]);
5362 real_t rdc[2];
5363 MPI_Allreduce(loc, rdc, 2, MPITypeMap<real_t>::mpi_type, MPI_SUM,
5364 x.ParFESpace()->GetComm());
5365 metric_normal = 1.0 / rdc[0];
5366 lim_normal = 1.0 / rdc[1];
5368}
5369#endif
5370
5372 real_t &l_normal,
5373 real_t &s_normal)
5374{
5375 m_normal = this->metric_normal;
5376 l_normal = this->lim_normal;
5377 s_normal = this->surf_fit_normal;
5378}
5379
5381 real_t &metric_energy,
5382 real_t &lim_energy)
5383{
5384 metric_energy = 0.0;
5385 lim_energy = 0.0;
5386 if (PA.enabled)
5387 {
5388 MFEM_VERIFY(PA.E.Size() > 0, "Must be called after AssemblePA!");
5389 MFEM_VERIFY(surf_fit_gf == nullptr,
5390 "Normalization + PA + Fitting is not implemented!");
5391
5393 auto R = x.FESpace()->GetElementRestriction(ord);
5394 Vector xe(R->Height());
5395 R->Mult(x, xe);
5396
5397 // Force update of the target Jacobian.
5399
5400 if (PA.dim == 2)
5401 {
5402 GetLocalNormalizationEnergiesPA_2D(xe, metric_energy, lim_energy);
5403 }
5404 else
5405 {
5406 GetLocalNormalizationEnergiesPA_3D(xe, metric_energy, lim_energy);
5407 }
5408
5409 // Cases when integration is not over the target element, or when the
5410 // targets don't contain volumetric information.
5411 if (integ_over_target == false || targetC->ContainsVolumeInfo() == false)
5412 {
5413 lim_energy = x.FESpace()->GetNE();
5414 }
5415
5416 return;
5417 }
5418
5419 Array<int> vdofs;
5420 Vector x_vals;
5421 const FiniteElementSpace* const fes = x.FESpace();
5422
5423 const int dim = fes->GetMesh()->Dimension();
5424 Jrt.SetSize(dim);
5425 Jpr.SetSize(dim);
5426 Jpt.SetSize(dim);
5427
5428 for (int i = 0; i < fes->GetNE(); i++)
5429 {
5430 const FiniteElement *fe = fes->GetFE(i);
5432 const int nqp = ir.GetNPoints();
5433 DenseTensor Jtr(dim, dim, nqp);
5434 const int dof = fe->GetDof();
5435 DSh.SetSize(dof, dim);
5436
5437 fes->GetElementVDofs(i, vdofs);
5438 x.GetSubVector(vdofs, x_vals);
5439 PMatI.UseExternalData(x_vals.GetData(), dof, dim);
5440
5441 targetC->ComputeElementTargets(i, *fe, ir, x_vals, Jtr);
5442
5443 for (int q = 0; q < nqp; q++)
5444 {
5445 const IntegrationPoint &ip = ir.IntPoint(q);
5447 CalcInverse(Jtr(q), Jrt);
5448 const real_t weight =
5449 (integ_over_target) ? ip.weight * Jtr(q).Det() : ip.weight;
5450
5451 fe->CalcDShape(ip, DSh);
5452 MultAtB(PMatI, DSh, Jpr);
5453 Mult(Jpr, Jrt, Jpt);
5454
5455 metric_energy += weight * metric->EvalW(Jpt);
5456 lim_energy += weight;
5457 }
5458
5459 // TODO: Normalization of the surface fitting term.
5460 }
5461
5462 // Cases when integration is not over the target element, or when the
5463 // targets don't contain volumetric information.
5464 if (integ_over_target == false || targetC->ContainsVolumeInfo() == false)
5465 {
5466 lim_energy = fes->GetNE();
5467 }
5468}
5469
5471 const FiniteElementSpace &fes)
5472{
5473 const FiniteElement *fe = fes.GetTypicalFE();
5475 const int NE = fes.GetMesh()->GetNE(), dim = fe->GetDim(),
5476 dof = fe->GetDof(), nsp = ir.GetNPoints();
5477
5478 Array<int> xdofs(dof * dim);
5479 DenseMatrix dshape(dof, dim), pos(dof, dim);
5480 Vector posV(pos.Data(), dof * dim);
5481 Jpr.SetSize(dim);
5482
5483 fd_h = std::numeric_limits<float>::max();
5484
5485 real_t detv_sum;
5486 real_t detv_avg_min = std::numeric_limits<float>::max();
5487 for (int i = 0; i < NE; i++)
5488 {
5489 fes.GetElementVDofs(i, xdofs);
5490 x.GetSubVector(xdofs, posV);
5491 detv_sum = 0.;
5492 for (int j = 0; j < nsp; j++)
5493 {
5494 fes.GetFE(i)->CalcDShape(ir.IntPoint(j), dshape);
5495 MultAtB(pos, dshape, Jpr);
5496 detv_sum += std::fabs(Jpr.Det());
5497 }
5498 real_t detv_avg = pow(detv_sum/nsp, 1./dim);
5499 detv_avg_min = std::min(detv_avg, detv_avg_min);
5500 }
5501 fd_h = detv_avg_min / fd_h_scale;
5502}
5503
5505 int new_x_ordering)
5506{
5507 MFEM_VERIFY(periodic == false, "Periodic not implemented yet.");
5508
5509 if (!surf_fit_gf) { return; }
5510
5512 {
5513 // Interpolate information only at DOFs marked for fitting.
5514 const int dim = surf_fit_gf->FESpace()->GetMesh()->Dimension();
5515 const int cnt = surf_fit_marker_dof_index.Size();
5516 const int total_cnt = new_x.Size()/dim;
5517 Vector new_x_sorted(cnt*dim);
5518 if (new_x_ordering == 0)
5519 {
5520 for (int d = 0; d < dim; d++)
5521 {
5522 for (int i = 0; i < cnt; i++)
5523 {
5524 int dof_index = surf_fit_marker_dof_index[i];
5525 new_x_sorted(i + d*cnt) = new_x(dof_index + d*total_cnt);
5526 }
5527 }
5528 }
5529 else
5530 {
5531 for (int i = 0; i < cnt; i++)
5532 {
5533 int dof_index = surf_fit_marker_dof_index[i];
5534 for (int d = 0; d < dim; d++)
5535 {
5536 new_x_sorted(d + i*dim) = new_x(d + dof_index*dim);
5537 }
5538 }
5539 }
5540
5541 // Interpolate values of the LS.
5542 Vector surf_fit_gf_int, surf_fit_grad_int, surf_fit_hess_int;
5543 surf_fit_eval->ComputeAtGivenPositions(new_x_sorted, surf_fit_gf_int,
5544 new_x_ordering);
5545 for (int i = 0; i < cnt; i++)
5546 {
5547 int dof_index = surf_fit_marker_dof_index[i];
5548 (*surf_fit_gf)[dof_index] = surf_fit_gf_int(i);
5549 }
5550
5551 // Interpolate gradients of the LS.
5553 surf_fit_grad_int,
5554 new_x_ordering);
5555 // Assumes surf_fit_grad and surf_fit_gf share the same space
5556 const int grad_dim = surf_fit_grad->VectorDim();
5557 const int grad_cnt = surf_fit_grad->Size()/grad_dim;
5559 {
5560 for (int d = 0; d < grad_dim; d++)
5561 {
5562 for (int i = 0; i < cnt; i++)
5563 {
5564 int dof_index = surf_fit_marker_dof_index[i];
5565 (*surf_fit_grad)[dof_index + d*grad_cnt] =
5566 surf_fit_grad_int(i + d*cnt);
5567 }
5568 }
5569 }
5570 else
5571 {
5572 for (int i = 0; i < cnt; i++)
5573 {
5574 int dof_index = surf_fit_marker_dof_index[i];
5575 for (int d = 0; d < grad_dim; d++)
5576 {
5577 (*surf_fit_grad)[dof_index*grad_dim + d] =
5578 surf_fit_grad_int(i*grad_dim + d);
5579 }
5580 }
5581 }
5582
5583 // Interpolate Hessians of the LS.
5585 surf_fit_hess_int,
5586 new_x_ordering);
5587 // Assumes surf_fit_hess and surf_fit_gf share the same space
5588 const int hess_dim = surf_fit_hess->VectorDim();
5589 const int hess_cnt = surf_fit_hess->Size()/hess_dim;
5591 {
5592 for (int d = 0; d < hess_dim; d++)
5593 {
5594 for (int i = 0; i < cnt; i++)
5595 {
5596 int dof_index = surf_fit_marker_dof_index[i];
5597 (*surf_fit_hess)[dof_index + d*hess_cnt] =
5598 surf_fit_hess_int(i + d*cnt);
5599 }
5600 }
5601 }
5602 else
5603 {
5604 for (int i = 0; i < cnt; i++)
5605 {
5606 int dof_index = surf_fit_marker_dof_index[i];
5607 for (int d = 0; d < hess_dim; d++)
5608 {
5609 (*surf_fit_hess)[dof_index*hess_dim + d] =
5610 surf_fit_hess_int(i*hess_dim + d);
5611 }
5612 }
5613 }
5614
5615 }
5616 else
5617 {
5618 surf_fit_eval->ComputeAtNewPosition(new_x, *surf_fit_gf, new_x_ordering);
5620 {
5622 new_x_ordering);
5623 }
5625 {
5627 new_x_ordering);
5628 }
5629 }
5630}
5631
5634{
5635 if (discr_tc) { PA.Jtr_needs_update = true; }
5636
5637 if (PA.enabled) { UpdateCoefficientsPA(d); }
5638
5639 Ordering::Type ordering = d_fes.GetOrdering();
5640
5641 // Update the finite difference delta if FD are used.
5642 if (fdflag) { ComputeFDh(d, d_fes); }
5643
5644 Vector x_loc;
5645 if (periodic)
5646 {
5647 GetPeriodicPositions(*x_0, d, *x_0->FESpace(), d_fes, x_loc);
5648 }
5649 else
5650 {
5651 x_loc.SetSize(x_0->Size());
5652 add(*x_0, d, x_loc);
5653 }
5654
5655 // Update the target constructor if it's a discrete one.
5656 if (discr_tc)
5657 {
5658 discr_tc->UpdateTargetSpecification(x_loc, true, ordering);
5659 if (fdflag)
5660 {
5661 if (periodic) { MFEM_ABORT("Periodic not implemented yet."); }
5662 discr_tc->UpdateGradientTargetSpecification(x_loc, fd_h, true, ordering);
5663 discr_tc->UpdateHessianTargetSpecification(x_loc, fd_h, true, ordering);
5664 }
5665 }
5666
5667 // Update adapt_lim_gf if adaptive limiting is enabled.
5668 if (adapt_lim_gf)
5669 {
5671 }
5672
5673 // Update surf_fit_gf (and optionally its gradients) if surface
5674 // fitting is enabled.
5675 if (surf_fit_gf)
5676 {
5677 RemapSurfaceFittingLevelSetAtNodes(x_loc, ordering);
5678 }
5679}
5680
5682{
5683 if (periodic) { MFEM_ABORT("Periodic not implemented yet."); }
5684
5685 Vector x_loc(*x_0);
5686 x_loc += d;
5687
5688 if (!fdflag) { return; }
5689 ComputeMinJac(x_loc, fes);
5690#ifdef MFEM_USE_MPI
5691 const ParFiniteElementSpace *pfes =
5692 dynamic_cast<const ParFiniteElementSpace *>(&fes);
5693 if (pfes)
5694 {
5695 real_t min_jac_all;
5696 MPI_Allreduce(&fd_h, &min_jac_all, 1, MPITypeMap<real_t>::mpi_type,
5697 MPI_MIN, pfes->GetComm());
5698 fd_h = min_jac_all;
5699 }
5700#endif
5701}
5702
5704{
5705 fdflag = true;
5706 const FiniteElementSpace *fes = x.FESpace();
5707
5708 const bool per = fes->IsDGSpace();
5709 MFEM_VERIFY(per == false, "FD is not supported for periodic meshes.");
5710
5711 if (discr_tc)
5712 {
5713#ifdef MFEM_USE_GSLIB
5715 if (dynamic_cast<const InterpolatorFP *>(ae))
5716 {
5717 MFEM_ABORT("Using GSLIB-based interpolation with finite differences"
5718 "requires careful consideration. Contact TMOP team.");
5719 }
5720#endif
5723 fes->GetOrdering());
5725 fes->GetOrdering());
5726 }
5727}
5728
5729#ifdef MFEM_USE_MPI
5731{
5732 fdflag = true;
5733 const ParFiniteElementSpace *pfes = x.ParFESpace();
5734
5735 const bool per = pfes->IsDGSpace();
5736 MFEM_VERIFY(per == false, "FD is not supported for periodic meshes.");
5737
5738 if (discr_tc)
5739 {
5740#ifdef MFEM_USE_GSLIB
5742 if (dynamic_cast<const InterpolatorFP *>(ae))
5743 {
5744 MFEM_ABORT("Using GSLIB-based interpolation with finite differences"
5745 "requires careful consideration. Contact TMOP team.");
5746 }
5747#endif
5750 pfes->GetOrdering());
5752 pfes->GetOrdering());
5753 }
5754}
5755#endif
5756
5758 const FiniteElementSpace &fes)
5759{
5760 real_t min_detT = std::numeric_limits<real_t>::infinity();
5761 const int NE = fes.GetMesh()->GetNE();
5762 const int dim = fes.GetMesh()->Dimension();
5763 Array<int> xdofs;
5764 Jpr.SetSize(dim);
5765 Jpt.SetSize(dim);
5766 Jrt.SetSize(dim);
5767
5768 for (int i = 0; i < NE; i++)
5769 {
5770 const FiniteElement *fe = fes.GetFE(i);
5772 const int dof = fe->GetDof(), nsp = ir.GetNPoints();
5773
5774 DSh.SetSize(dof, dim);
5775 Vector posV(dof * dim);
5776 PMatI.UseExternalData(posV.GetData(), dof, dim);
5777
5778 fes.GetElementVDofs(i, xdofs);
5779 x.GetSubVector(xdofs, posV);
5780
5782 targetC->ComputeElementTargets(i, *fe, ir, posV, Jtr);
5783
5784 for (int q = 0; q < nsp; q++)
5785 {
5786 const IntegrationPoint &ip = ir.IntPoint(q);
5787 const DenseMatrix &Jtr_q = Jtr(q);
5788 CalcInverse(Jtr_q, Jrt);
5789 fe->CalcDShape(ip, DSh);
5790 MultAtB(PMatI, DSh, Jpr);
5791 Mult(Jpr, Jrt, Jpt);
5792 real_t detT = Jpt.Det();
5793 min_detT = std::min(min_detT, detT);
5794 }
5795 }
5796 return min_detT;
5797}
5798
5801{
5802 real_t max_muT = -std::numeric_limits<real_t>::infinity();
5803 const int NE = fes.GetMesh()->GetNE();
5804 const int dim = fes.GetMesh()->Dimension();
5805 Array<int> xdofs;
5806 Jpr.SetSize(dim);
5807 Jpt.SetSize(dim);
5808 Jrt.SetSize(dim);
5809
5812
5813 if (!wcuo || wcuo->GetWorstCaseType() !=
5815 {
5816 return 0.0;
5817 }
5818
5819 for (int i = 0; i < NE; i++)
5820 {
5821 const FiniteElement *fe = fes.GetFE(i);
5823 const int dof = fe->GetDof(), nsp = ir.GetNPoints();
5824 Jpr.SetSize(dim);
5825 Jrt.SetSize(dim);
5826 Jpt.SetSize(dim);
5827
5828 DSh.SetSize(dof, dim);
5829 Vector posV(dof * dim);
5830 PMatI.UseExternalData(posV.GetData(), dof, dim);
5831
5832 fes.GetElementVDofs(i, xdofs);
5833 x.GetSubVector(xdofs, posV);
5834
5836 targetC->ComputeElementTargets(i, *fe, ir, posV, Jtr);
5837
5838 for (int q = 0; q < nsp; q++)
5839 {
5840 const IntegrationPoint &ip = ir.IntPoint(q);
5841 const DenseMatrix &Jtr_q = Jtr(q);
5842 CalcInverse(Jtr_q, Jrt);
5843
5844 fe->CalcDShape(ip, DSh);
5845 MultAtB(PMatI, DSh, Jpr);
5846 Mult(Jpr, Jrt, Jpt);
5847
5848 real_t metric_val = 0.0;
5849 if (wcuo)
5850 {
5851 wcuo->SetTargetJacobian(Jtr_q);
5852 metric_val = wcuo->EvalWBarrier(Jpt);
5853 }
5854
5855 max_muT = std::max(max_muT, metric_val);
5856 }
5857 }
5858 return max_muT;
5859}
5860
5863{
5866
5867 if (!wcuo) { return; }
5868
5869 if (periodic) { MFEM_ABORT("Periodic not implemented yet."); }
5870
5871 Vector x_loc(d.Size());
5872 if (x_0)
5873 {
5874 add(*x_0, d, x_loc);
5875 }
5876 else { x_loc = d; }
5877
5878#ifdef MFEM_USE_MPI
5879 const ParFiniteElementSpace *pfes =
5880 dynamic_cast<const ParFiniteElementSpace *>(&fes);
5881#endif
5882
5883 if (wcuo && wcuo->GetBarrierType() ==
5885 {
5886 real_t min_detT = ComputeMinDetT(x_loc, fes);
5887 real_t min_detT_all = min_detT;
5888#ifdef MFEM_USE_MPI
5889 if (pfes)
5890 {
5891 MPI_Allreduce(&min_detT, &min_detT_all, 1,
5892 MPITypeMap<real_t>::mpi_type, MPI_MIN, pfes->GetComm());
5893 }
5894#endif
5895 if (wcuo) { wcuo->SetMinDetT(min_detT_all); }
5896 }
5897
5898 real_t max_muT = ComputeUntanglerMaxMuBarrier(x_loc, fes);
5899 real_t max_muT_all = max_muT;
5900#ifdef MFEM_USE_MPI
5901 if (pfes)
5902 {
5903 MPI_Allreduce(&max_muT, &max_muT_all, 1, MPITypeMap<real_t>::mpi_type,
5904 MPI_MAX, pfes->GetComm());
5905 }
5906#endif
5907 wcuo->SetMaxMuT(max_muT_all);
5908}
5909
5911 const GridFunction &dist,
5912 Coefficient &w0,
5913 TMOP_LimiterFunction *lfunc)
5914{
5915 MFEM_VERIFY(tmopi.Size() > 0, "No TMOP_Integrators were added.");
5916
5917 tmopi[0]->EnableLimiting(n0, dist, w0, lfunc);
5918 for (int i = 1; i < tmopi.Size(); i++) { tmopi[i]->DisableLimiting(); }
5919}
5920
5922 Coefficient &w0,
5923 TMOP_LimiterFunction *lfunc)
5924{
5925 MFEM_VERIFY(tmopi.Size() > 0, "No TMOP_Integrators were added.");
5926
5927 tmopi[0]->EnableLimiting(n0, w0, lfunc);
5928 for (int i = 1; i < tmopi.Size(); i++) { tmopi[i]->DisableLimiting(); }
5929}
5930
5932{
5933 MFEM_VERIFY(tmopi.Size() > 0, "No TMOP_Integrators were added.");
5934
5935 tmopi[0]->SetLimitingNodes(n0);
5936 for (int i = 1; i < tmopi.Size(); i++) { tmopi[i]->DisableLimiting(); }
5937}
5938
5941 const Vector &elfun)
5942{
5943 real_t energy= 0.0;
5944 for (int i = 0; i < tmopi.Size(); i++)
5945 {
5946 energy += tmopi[i]->GetElementEnergy(el, T, elfun);
5947 }
5948 return energy;
5949}
5950
5953 const Vector &elfun,
5954 Vector &elvect)
5955{
5956 MFEM_VERIFY(tmopi.Size() > 0, "No TMOP_Integrators were added.");
5957
5958 tmopi[0]->AssembleElementVector(el, T, elfun, elvect);
5959 for (int i = 1; i < tmopi.Size(); i++)
5960 {
5961 Vector elvect_i;
5962 tmopi[i]->AssembleElementVector(el, T, elfun, elvect_i);
5963 elvect += elvect_i;
5964 }
5965}
5966
5969 const Vector &elfun,
5970 DenseMatrix &elmat)
5971{
5972 MFEM_VERIFY(tmopi.Size() > 0, "No TMOP_Integrators were added.");
5973
5974 tmopi[0]->AssembleElementGrad(el, T, elfun, elmat);
5975 for (int i = 1; i < tmopi.Size(); i++)
5976 {
5977 DenseMatrix elmat_i;
5978 tmopi[i]->AssembleElementGrad(el, T, elfun, elmat_i);
5979 elmat += elmat_i;
5980 }
5981}
5982
5985 const Vector &elfun,
5986 const IntegrationRule &irule)
5987{
5988 real_t energy= 0.0;
5989 for (int i = 0; i < tmopi.Size(); i++)
5990 {
5991 energy += tmopi[i]->GetRefinementElementEnergy(el, T, elfun, irule);
5992 }
5993 return energy;
5994}
5995
5997 const FiniteElement &el,
5999 const Vector &elfun)
6000{
6001 real_t energy= 0.0;
6002 for (int i = 0; i < tmopi.Size(); i++)
6003 {
6004 energy += tmopi[i]->GetDerefinementElementEnergy(el, T, elfun);
6005 }
6006 return energy;
6007}
6008
6010{
6011 const int cnt = tmopi.Size();
6012 real_t total_integral = 0.0;
6013 for (int i = 0; i < cnt; i++)
6014 {
6015 tmopi[i]->EnableNormalization(x);
6016 total_integral += 1.0 / tmopi[i]->metric_normal;
6017 }
6018 for (int i = 0; i < cnt; i++)
6019 {
6020 tmopi[i]->metric_normal = 1.0 / total_integral;
6021 }
6022}
6023
6024#ifdef MFEM_USE_MPI
6026{
6027 const int cnt = tmopi.Size();
6028 real_t total_integral = 0.0;
6029 for (int i = 0; i < cnt; i++)
6030 {
6031 tmopi[i]->ParEnableNormalization(x);
6032 total_integral += 1.0 / tmopi[i]->metric_normal;
6033 }
6034 for (int i = 0; i < cnt; i++)
6035 {
6036 tmopi[i]->metric_normal = 1.0 / total_integral;
6037 }
6038}
6039#endif
6040
6042{
6043 for (int i = 0; i < tmopi.Size(); i++)
6044 {
6045 tmopi[i]->AssemblePA(fes);
6046 }
6047}
6048
6050 const FiniteElementSpace &fes)
6051{
6052 for (int i = 0; i < tmopi.Size(); i++)
6053 {
6054 tmopi[i]->AssembleGradPA(xe,fes);
6055 }
6056}
6057
6059{
6060 for (int i = 0; i < tmopi.Size(); i++)
6061 {
6062 tmopi[i]->AssembleGradDiagonalPA(de);
6063 }
6064}
6065
6067{
6068 for (int i = 0; i < tmopi.Size(); i++)
6069 {
6070 tmopi[i]->AddMultPA(xe, ye);
6071 }
6072}
6073
6075{
6076 for (int i = 0; i < tmopi.Size(); i++)
6077 {
6078 tmopi[i]->AddMultGradPA(re, ce);
6079 }
6080}
6081
6083{
6084 real_t energy = 0.0;
6085 for (int i = 0; i < tmopi.Size(); i++)
6086 {
6087 energy += tmopi[i]->GetLocalStateEnergyPA(xe);
6088 }
6089 return energy;
6090}
6091
6093 const TargetConstructor &tc,
6094 const Mesh &mesh, GridFunction &metric_gf)
6095{
6096 const int NE = mesh.GetNE();
6097 const GridFunction &nodes = *mesh.GetNodes();
6098 const int dim = mesh.Dimension();
6099 DenseMatrix Winv(dim), T(dim), A(dim), dshape, pos;
6100 Array<int> pos_dofs, gf_dofs;
6101 DenseTensor W;
6102 Vector posV;
6103
6104 for (int i = 0; i < NE; i++)
6105 {
6106 const FiniteElement &fe_pos = *nodes.FESpace()->GetFE(i);
6107 const IntegrationRule &ir = metric_gf.FESpace()->GetFE(i)->GetNodes();
6108 const int nsp = ir.GetNPoints(), dof = fe_pos.GetDof();
6109
6110 dshape.SetSize(dof, dim);
6111 pos.SetSize(dof, dim);
6112 posV.SetDataAndSize(pos.Data(), dof * dim);
6113
6114 metric_gf.FESpace()->GetElementDofs(i, gf_dofs);
6115 nodes.FESpace()->GetElementVDofs(i, pos_dofs);
6116 nodes.GetSubVector(pos_dofs, posV);
6117
6118 W.SetSize(dim, dim, nsp);
6119 tc.ComputeElementTargets(i, fe_pos, ir, posV, W);
6120
6121 for (int j = 0; j < nsp; j++)
6122 {
6123 const DenseMatrix &Wj = W(j);
6124 metric.SetTargetJacobian(Wj);
6125 CalcInverse(Wj, Winv);
6126
6127 const IntegrationPoint &ip = ir.IntPoint(j);
6128 fe_pos.CalcDShape(ip, dshape);
6129 MultAtB(pos, dshape, A);
6130 Mult(A, Winv, T);
6131
6132 metric_gf(gf_dofs[j]) = metric.EvalW(T);
6133 }
6134 }
6135}
6136
6137} // 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:1513
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:1518
Coefficient * scalar_tspec
Definition tmop.hpp:1733
virtual void SetAnalyticTargetSpec(Coefficient *sspec, VectorCoefficient *vspec, TMOPMatrixCoefficient *mspec)
Definition tmop.cpp:2603
TMOPMatrixCoefficient * matrix_tspec
Definition tmop.hpp:1735
VectorCoefficient * vector_tspec
Definition tmop.hpp:1734
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:840
int Size() const
Return the logical size of the array.
Definition array.hpp:166
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Definition array.hpp:912
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:113
real_t * Data() const
Returns the matrix data array. Warning: this method casts away constness.
Definition densemat.hpp:122
real_t * GetData() const
Returns the matrix data array. Warning: this method casts away constness.
Definition densemat.hpp:126
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
Definition densemat.hpp:116
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:88
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:110
real_t FNorm2() const
Compute the square of the Frobenius norm of the matrix.
Definition densemat.hpp:288
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:281
const Vector & GetTspecPert1H()
Definition tmop.hpp:1929
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:1805
DenseTensor Jtrcomp
Definition tmop.hpp:1794
virtual void SetSerialDiscreteTargetAspectRatio(const GridFunction &tspec_)
Definition tmop.cpp:2851
const AdaptivityEvaluator * GetAdaptivityEvaluator() const
Definition tmop.hpp:1924
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:1931
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:1817
void FinalizeSerialDiscreteTargetSpec(const GridFunction &tspec_)
Definition tmop.cpp:2871
void FinalizeParDiscreteTargetSpec(const ParGridFunction &tspec_)
Definition tmop.cpp:2693
ParFiniteElementSpace * ptspec_fesv
Definition tmop.hpp:1803
GridFunction * tspec_gf
Definition tmop.hpp:1800
FiniteElementSpace * coarse_tspec_fesv
Definition tmop.hpp:1799
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:1930
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:1966
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:1798
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:1981
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:1787
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:244
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:208
bool IsVariableOrder() const
Returns true if the space contains elements of varying polynomial orders.
Definition fespace.hpp:678
DofTransformation * GetElementDofs(int elem, Array< int > &dofs) const
Returns indices of degrees of freedom of element 'elem'. The returned indices are offsets into an ldo...
Definition fespace.cpp:3502
int GetNDofs() const
Returns number of degrees of freedom. This is the number of Local Degrees of Freedom.
Definition fespace.hpp:823
int VDofToDof(int vdof) const
Compute the inverse of the Dof to VDof mapping for a single index vdof.
Definition fespace.hpp:1133
DofTransformation * GetElementVDofs(int i, Array< int > &vdofs) const
Returns indices of degrees of freedom for the i'th element. The returned indices are offsets into an ...
Definition fespace.cpp:304
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
Definition fespace.cpp:3824
Ordering::Type GetOrdering() const
Return the ordering method.
Definition fespace.hpp:854
int GetNE() const
Returns number of elements in the mesh.
Definition fespace.hpp:869
const ElementRestrictionOperator * GetElementRestriction(ElementDofOrdering e_ordering) const
Return an Operator that converts L-vectors to E-vectors.
Definition fespace.cpp:1480
virtual void Update(bool want_transform=true)
Reflect changes in the mesh: update number of DOFs, etc. Also, calculate GridFunction transformation ...
Definition fespace.cpp:4146
const FiniteElementCollection * FEColl() const
Definition fespace.hpp:856
Mesh * GetMesh() const
Returns the mesh.
Definition fespace.hpp:644
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
Definition fespace.hpp:826
int GetVDim() const
Returns the vector dimension of the finite element space.
Definition fespace.hpp:819
bool IsDGSpace() const
Return whether or not the space is discontinuous (L2)
Definition fespace.hpp:1503
const FiniteElement * GetTypicalFE() const
Return GetFE(0) if the local mesh is not empty; otherwise return a typical FE based on the Geometry t...
Definition fespace.cpp:3860
const Operator * GetUpdateOperator()
Get the GridFunction update operator.
Definition fespace.hpp:1468
Abstract class for all finite elements.
Definition fe_base.hpp:247
virtual void 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:324
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
Definition fe_base.hpp:403
virtual void CalcDShape(const IntegrationPoint &ip, DenseMatrix &dshape) const =0
Evaluate the gradients of all shape functions of a scalar finite element in reference space at the gi...
Geometry::Type GetGeomType() const
Returns the Geometry::Type of the reference element.
Definition fe_base.hpp:334
virtual void 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:337
const DenseMatrix & GetGeomToPerfGeomJac(int GeomType) const
Definition geom.hpp:102
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:32
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:517
virtual void Update()
Transform by the Space UpdateMatrix (e.g., on Mesh change).
Definition gridfunc.cpp:168
void MakeOwner(FiniteElementCollection *fec_)
Make the GridFunction the owner of fec_owned and fes.
Definition gridfunc.hpp:123
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.cpp:347
void GetVectorValues(int i, const IntegrationRule &ir, DenseMatrix &vals, DenseMatrix &tr) const
Definition gridfunc.cpp:707
Arbitrary order H1-conforming (continuous) finite elements.
Definition fe_coll.hpp:279
int GetBasisType() const
Definition fe_coll.hpp:305
Class for integration point with weight.
Definition intrules.hpp:35
Class for an integration rule - an Array of IntegrationPoint.
Definition intrules.hpp:100
int GetNPoints() const
Returns the number of the points in the integration rule.
Definition intrules.hpp:256
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
Definition intrules.hpp:259
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
const scalar_t * Get_dI1b()
void Assemble_ddI1(scalar_t w, scalar_t *A)
void SetJacobian(const scalar_t *Jac)
The Jacobian should use column-major storage.
void Assemble_ddI1b(scalar_t w, scalar_t *A)
const scalar_t * Get_dI2()
void SetDerivativeMatrix(int height, const scalar_t *Deriv)
The Deriv matrix is dof x 2, using column-major storage.
void Assemble_ddI2b(scalar_t w, scalar_t *A)
const scalar_t * Get_dI2b()
void Assemble_TProd(scalar_t w, const scalar_t *X, const scalar_t *Y, scalar_t *A)
void Assemble_ddI2(scalar_t w, scalar_t *A)
const scalar_t * Get_dI1()
void SetJacobian(const scalar_t *Jac)
The Jacobian should use column-major storage.
const scalar_t * Get_dI2()
const scalar_t * Get_dI2b()
const scalar_t * Get_dI3()
void Assemble_TProd(scalar_t w, const scalar_t *X, const scalar_t *Y, scalar_t *A)
const scalar_t * Get_dI1()
void SetDerivativeMatrix(int height, const scalar_t *Deriv)
The Deriv matrix is dof x 3, using column-major storage.
const scalar_t * Get_dI3b()
void Assemble_ddI1(scalar_t w, scalar_t *A)
void Assemble_ddI2(scalar_t w, scalar_t *A)
const scalar_t * Get_dI1b()
void Assemble_ddI3(scalar_t w, scalar_t *A)
void Assemble_ddI2b(scalar_t w, scalar_t *A)
void Assemble_ddI3b(scalar_t w, scalar_t *A)
void Assemble_ddI1b(scalar_t w, scalar_t *A)
A standard isoparametric element transformation.
Definition eltrans.hpp: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:65
int GetNE() const
Returns number of elements.
Definition mesh.hpp:1377
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1306
void GetElementTransformation(int i, IsoparametricTransformation *ElTr) const
Builds the transformation defining the i-th element in ElTr. ElTr must be allocated in advance and wi...
Definition mesh.cpp:360
void GetNodes(Vector &node_coord) const
Definition mesh.cpp:9627
NCMesh * ncmesh
Optional nonconforming mesh extension.
Definition mesh.hpp:313
int GetNumGeometries(int dim) const
Return the number of geometries of the given dimension present in the mesh.
Definition mesh.cpp:7558
Geometry::Type GetElementBaseGeometry(int i) const
Definition mesh.hpp:1556
void DeleteGeometricFactors()
Destroy all GeometricFactors stored by the Mesh.
Definition mesh.cpp:1022
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:724
void ReorderLexToNative(int ncomp, Vector &dofs) const
Definition fe_base.cpp:999
Abstract operator.
Definition operator.hpp:25
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Definition operator.hpp:66
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
int NumCols() const
Get the number of columns (size of input) of the Operator. Synonym with Width().
Definition operator.hpp:75
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
Definition operator.hpp:72
Type
Ordering methods:
Definition 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:85
Class for parallel meshes.
Definition pmesh.hpp:34
virtual real_t GetDerefinementElementEnergy(const FiniteElement &el, ElementTransformation &T, const Vector &elfun)
Definition tmop.cpp:5996
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:6049
void AssembleGradDiagonalPA(Vector &) const override
Method for computing the diagonal of the gradient with partial assembly.
Definition tmop.cpp:6058
real_t GetLocalStateEnergyPA(const Vector &) const override
Compute the local (to the MPI rank) energy with partial assembly.
Definition tmop.cpp:6082
void AddMultPA(const Vector &, Vector &) const override
Method for partially assembled action.
Definition tmop.cpp:6066
void ParEnableNormalization(const ParGridFunction &x)
Definition tmop.cpp:6025
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:5910
void AssembleElementGrad(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, DenseMatrix &elmat) override
Assemble the local gradient matrix.
Definition tmop.cpp:5967
real_t GetElementEnergy(const FiniteElement &el, ElementTransformation &T, const Vector &elfun) override
Compute the local energy.
Definition tmop.cpp:5939
void AddMultGradPA(const Vector &, Vector &) const override
Method for partially assembled gradient action.
Definition tmop.cpp:6074
virtual real_t GetRefinementElementEnergy(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, const IntegrationRule &irule)
Definition tmop.cpp:5983
void AssemblePA(const FiniteElementSpace &) override
Method defining partial assembly.
Definition tmop.cpp:6041
Array< TMOP_Integrator * > tmopi
Definition tmop.hpp:2561
void AssembleElementVector(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, Vector &elvect) override
Perform the local action of the NonlinearFormIntegrator.
Definition tmop.cpp:5951
void EnableNormalization(const GridFunction &x)
Normalization factor that considers all integrators in the combination.
Definition tmop.cpp:6009
void SetLimitingNodes(const GridFunction &n0)
Update the original/reference nodes used for limiting.
Definition tmop.cpp:5931
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:5800
void UpdateAfterMeshPositionChange(const Vector &d, const FiniteElementSpace &d_fes)
Definition tmop.cpp:5633
DenseMatrix Jpr
Definition tmop.hpp:2089
void AssembleElemVecAdaptLim(const FiniteElement &el, IsoparametricTransformation &Tpr, const IntegrationRule &ir, const Vector &weights, DenseMatrix &mat)
Definition tmop.cpp:4824
void AssembleElemGradAdaptLim(const FiniteElement &el, IsoparametricTransformation &Tpr, const IntegrationRule &ir, const Vector &weights, DenseMatrix &m)
Definition tmop.cpp:4860
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:5371
TMOP_LimiterFunction * lim_func
Definition tmop.hpp:2035
void ComputeAllElementTargets(const Vector &xe=Vector()) const
Definition pa.cpp:170
void ParUpdateAfterMeshTopologyChange()
Definition tmop.cpp:4158
DenseMatrix PMatO
Definition tmop.hpp:2089
TMOP_QualityMetric * metric
Definition tmop.hpp:2014
const ParGridFunction * adapt_lim_pgf0
Definition tmop.hpp:2042
void GetSurfaceFittingErrors(const Vector &d_loc, real_t &err_avg, real_t &err_max)
Definition tmop.cpp:4074
real_t ComputeMinDetT(const Vector &x, const FiniteElementSpace &fes)
Definition tmop.cpp:5757
AdaptivityEvaluator * surf_fit_eval
Definition tmop.hpp:2053
void EnableNormalization(const GridFunction &x)
Computes the normalization factors of the metric and limiting integrals using the mesh position given...
Definition tmop.cpp:5349
void ComputeMinJac(const Vector &x, const FiniteElementSpace &fes)
Definition tmop.cpp:5470
void AssembleElementVectorExact(const FiniteElement &el, ElementTransformation &T, const Vector &d_el, Vector &elvect)
Definition tmop.cpp:4519
TMOP_QualityMetric * h_metric
Definition tmop.hpp:2013
void AssembleElementGradFD(const FiniteElement &el, ElementTransformation &T, const Vector &d_el, DenseMatrix &elmat)
Definition tmop.cpp:5217
DiscreteAdaptTC * discr_tc
Definition tmop.hpp:2063
Coefficient * lim_coeff
Definition tmop.hpp:2031
GridFunction * surf_fit_gf
Definition tmop.hpp:2052
const GridFunction * lim_dist
Definition tmop.hpp:2033
Array< Vector * > ElemPertEnergy
Definition tmop.hpp:2077
const GridFunction * adapt_lim_gf0
Definition tmop.hpp:2040
void ComputeUntangleMetricQuantiles(const Vector &d, const FiniteElementSpace &fes)
Definition tmop.cpp:5862
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:3999
const TargetConstructor * targetC
Definition tmop.hpp:2015
AdaptivityEvaluator * surf_fit_eval_grad
Definition tmop.hpp:2059
const GridFunction * lim_nodes0
Definition tmop.hpp:2030
const IntegrationRule * ir
Definition tmop.hpp:2139
TMOP_QuadraticLimiter * surf_fit_limiter
Definition tmop.hpp:2055
void EnableFiniteDifferences(const GridFunction &x)
Enables FD-based approximation and computes dx.
Definition tmop.cpp:5703
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:4350
real_t GetSurfaceFittingWeight()
Get the surface fitting weight.
Definition tmop.cpp:5338
void SetInitialMeshPos(const GridFunction *x0)
Definition tmop.cpp:3741
DenseMatrix DSh
Definition tmop.hpp:2089
const GridFunction * surf_fit_pos
Definition tmop.hpp:2056
Array< int > surf_fit_marker_dof_index
Definition tmop.hpp:2061
DenseTensor Jtr
Definition tmop.hpp:2131
void ParEnableNormalization(const ParGridFunction &x)
Definition tmop.cpp:5358
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:4171
Coefficient * adapt_lim_coeff
Definition tmop.hpp:2045
const FiniteElementSpace * fes
Definition tmop.hpp:2138
const IntegrationRule & EnergyIntegrationRule(const FiniteElement &el) const
Definition tmop.hpp:2199
GridFunction * surf_fit_grad
Definition tmop.hpp:2058
GridFunction * surf_fit_hess
Definition tmop.hpp:2058
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:4436
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:4504
void AssembleElementVectorFD(const FiniteElement &el, ElementTransformation &T, const Vector &d_el, Vector &elvect)
Definition tmop.cpp:5139
DenseMatrix PMatI
Definition tmop.hpp:2089
const IntegrationRule & GradientIntegrationRule(const FiniteElement &el) const
Definition tmop.hpp:2213
void EnableAdaptiveLimiting(const GridFunction &z0, Coefficient &coeff, AdaptivityEvaluator &ae)
Restriction of the node positions to certain regions.
Definition tmop.cpp:3798
struct mfem::TMOP_Integrator::@26 PA
AdaptivityEvaluator * surf_fit_eval_hess
Definition tmop.hpp:2059
Coefficient * metric_coeff
Definition tmop.hpp:2023
void GetLocalNormalizationEnergiesPA_3D(const Vector &x, real_t &met_energy, real_t &lim_energy) const
const GridFunction * x_0
Definition tmop.hpp:2010
GridFunction * adapt_lim_gf
Definition tmop.hpp:2044
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:5117
void UpdateAfterMeshTopologyChange()
Definition tmop.cpp:4145
void ComputeNormalizationEnergies(const GridFunction &x, real_t &metric_energy, real_t &lim_energy)
Definition tmop.cpp:5380
void RemapSurfaceFittingLevelSetAtNodes(const Vector &new_x, int new_x_ordering)
Definition tmop.cpp:5504
DenseMatrix Jrt
Definition tmop.hpp:2089
void UpdateCoefficientsPA(const Vector &d_loc)
Definition pa.cpp:187
Coefficient * surf_fit_coeff
Definition tmop.hpp:2050
Array< int > surf_fit_dof_count
Definition tmop.hpp:2060
DenseMatrix Jpt
Definition tmop.hpp:2089
void AssembleElementGradExact(const FiniteElement &el, ElementTransformation &T, const Vector &d_el, DenseMatrix &elmat)
Definition tmop.cpp:4695
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:3833
void AssembleElemGradSurfFit(const FiniteElement &el_x, IsoparametricTransformation &Tpr, DenseMatrix &mat)
Definition tmop.cpp:5002
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:4490
void UpdateSurfaceFittingWeight(real_t factor)
Update the surface fitting weight as surf_fit_coeff *= factor;.
Definition tmop.cpp:5326
Array< Vector * > ElemDer
Definition tmop.hpp:2076
const Array< bool > * surf_fit_marker
Definition tmop.hpp:2049
const IntegrationRule & ActionIntegrationRule(const FiniteElement &el) const
Definition tmop.hpp:2208
AdaptivityEvaluator * adapt_lim_eval
Definition tmop.hpp:2046
void ComputeFDh(const Vector &d, const FiniteElementSpace &fes)
Determines the perturbation, h, for FD-based approximation.
Definition tmop.cpp:5681
void AssembleElemVecSurfFit(const FiniteElement &el_x, IsoparametricTransformation &Tpr, DenseMatrix &mat)
Definition tmop.cpp:4921
void EnableLimiting(const GridFunction &n0, const GridFunction &dist, Coefficient &w0, TMOP_LimiterFunction *lfunc=NULL)
Limiting of the mesh displacements (general version).
Definition tmop.cpp:3773
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:1585
const TargetType target_type
Definition tmop.hpp:1611
bool Parallel() const
Definition tmop.hpp:1658
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:1682
const GridFunction * nodes
Definition tmop.hpp:1608
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:1276
Base class for vector Coefficients that optionally depend on time and space.
Vector data type.
Definition vector.hpp:82
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:584
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
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
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:6092
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:47
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:839
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:492
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