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