16 #include "../general/forall.hpp" 82 Vector products_no_m(m_cnt); products_no_m = 1.0;
83 for (
int m_p = 0; m_p < m_cnt; m_p++)
85 for (
int m_a = 0; m_a < m_cnt; m_a++)
87 if (m_p != m_a) { products_no_m(m_p) *= averages(m_a); }
90 const double pnm_sum = products_no_m.
Sum();
92 if (pnm_sum == 0.0) { weights = 1.0 / m_cnt;
return; }
93 for (
int m = 0; m < m_cnt; m++) { weights(m) = products_no_m(m) / pnm_sum; }
95 MFEM_ASSERT(fabs(weights.
Sum() - 1.0) < 1e-14,
96 "Error: sum should be 1 always: " << weights.
Sum());
113 for (
int e = 0; e < NE; e++)
132 for (
int q = 0; q < nsp; q++)
142 const double w_detA = ip.
weight * A.
Det();
143 for (
int m = 0; m < m_cnt; m++)
146 averages(m) +=
tmop_q_arr[m]->EvalW(T) * w_detA;
157 MPI_Allreduce(MPI_IN_PLACE, averages.
GetData(), m_cnt,
158 MPI_DOUBLE, MPI_SUM, par_nodes->ParFESpace()->GetComm());
159 MPI_Allreduce(MPI_IN_PLACE, &volume, 1, MPI_DOUBLE, MPI_SUM,
160 par_nodes->ParFESpace()->GetComm());
171 double metric = metric_tilde;
174 metric = std::pow(metric_tilde,
exponent);
179 metric = metric_tilde/(
beta-metric_tilde);
187 double denominator = 1.0;
194 double detT = Jpt.
Det();
224 MFEM_VERIFY(
Jtr != NULL,
225 "Requires a target Jacobian, use SetTargetJacobian().");
234 const double cos_Jpr = (col1 * col2) / norm_prod,
235 sin_Jpr = fabs(Jpr.
Det()) / norm_prod;
240 const double cos_Jtr = (col1 * col2) / norm_prod,
241 sin_Jtr = fabs(
Jtr->
Det()) / norm_prod;
243 return 0.5 * (1.0 - cos_Jpr * cos_Jtr - sin_Jpr * sin_Jtr);
248 MFEM_VERIFY(
Jtr != NULL,
249 "Requires a target Jacobian, use SetTargetJacobian().");
258 double norm_c1 = col1.
Norml2(),
261 double cos_Jpr_12 = (col1 * col2) / (norm_c1 * norm_c2),
262 cos_Jpr_13 = (col1 * col3) / (norm_c1 * norm_c3),
263 cos_Jpr_23 = (col2 * col3) / (norm_c2 * norm_c3);
264 double sin_Jpr_12 = std::sqrt(1.0 - cos_Jpr_12 * cos_Jpr_12),
265 sin_Jpr_13 = std::sqrt(1.0 - cos_Jpr_13 * cos_Jpr_13),
266 sin_Jpr_23 = std::sqrt(1.0 - cos_Jpr_23 * cos_Jpr_23);
274 double cos_Jtr_12 = (col1 * col2) / (norm_c1 * norm_c2),
275 cos_Jtr_13 = (col1 * col3) / (norm_c1 * norm_c3),
276 cos_Jtr_23 = (col2 * col3) / (norm_c2 * norm_c3);
277 double sin_Jtr_12 = std::sqrt(1.0 - cos_Jtr_12 * cos_Jtr_12),
278 sin_Jtr_13 = std::sqrt(1.0 - cos_Jtr_13 * cos_Jtr_13),
279 sin_Jtr_23 = std::sqrt(1.0 - cos_Jtr_23 * cos_Jtr_23);
281 return (3.0 - cos_Jpr_12 * cos_Jtr_12 - sin_Jpr_12 * sin_Jtr_12
282 - cos_Jpr_13 * cos_Jtr_13 - sin_Jpr_13 * sin_Jtr_13
283 - cos_Jpr_23 * cos_Jtr_23 - sin_Jpr_23 * sin_Jtr_23) / 6.0;
288 MFEM_VERIFY(
Jtr != NULL,
289 "Requires a target Jacobian, use SetTargetJacobian().");
303 return 0.5 * (ratio_Jpr / ratio_Jtr + ratio_Jtr / ratio_Jpr) - 1.0;
308 MFEM_VERIFY(
Jtr != NULL,
309 "Requires a target Jacobian, use SetTargetJacobian().");
318 double norm_c1 = col1.
Norml2(),
321 double ratio_Jpr_1 = norm_c1 / std::sqrt(norm_c2 * norm_c3),
322 ratio_Jpr_2 = norm_c2 / std::sqrt(norm_c1 * norm_c3),
323 ratio_Jpr_3 = norm_c3 / std::sqrt(norm_c1 * norm_c2);
331 double ratio_Jtr_1 = norm_c1 / std::sqrt(norm_c2 * norm_c3),
332 ratio_Jtr_2 = norm_c2 / std::sqrt(norm_c1 * norm_c3),
333 ratio_Jtr_3 = norm_c3 / std::sqrt(norm_c1 * norm_c2);
335 return ( 0.5 * (ratio_Jpr_1 / ratio_Jtr_1 + ratio_Jtr_1 / ratio_Jpr_1) +
336 0.5 * (ratio_Jpr_2 / ratio_Jtr_2 + ratio_Jtr_2 / ratio_Jpr_2) +
337 0.5 * (ratio_Jpr_3 / ratio_Jtr_3 + ratio_Jtr_3 / ratio_Jpr_3) - 3.0
343 return 0.5 * Jpt.
FNorm2() / Jpt.
Det() - 1.0;
424 const double c2 = weight*c1*c1;
468 MFEM_VERIFY(
Jtr != NULL,
469 "Requires a target Jacobian, use SetTargetJacobian().");
473 Id(0,0) = 1;
Id(0,1) = 0;
474 Id(1,0) = 0;
Id(1,1) = 1;
530 const double c2 = weight*c1/2;
531 const double c3 = c1*c2;
545 double det = Jpt.
Det();
547 return 0.5 * JtJ.
FNorm2()/(det*det) - 1.0;
558 return 0.5*I1b*I1b - 2.0;
614 const double d = Jpt.
Det();
615 return 0.5 * (d + 1.0 / d) - 1.0;
623 return 0.5*(I2b + 1.0/I2b) - 1.0;
654 double det = Jpt.
Det();
656 return JtJ.
FNorm2()/(det*det) - 2*Jpt.
FNorm2()/det + 2.0;
664 return I1b*(I1b - 2.0);
691 const double d = Jpt.
Det();
692 return 0.5 * (d*d + 1.0/(d*d)) - 1.0;
699 return 0.5*(I2 + 1.0/I2) - 1.0;
718 const double I2 =
ie.
Get_I2(), I2inv_sq = 1.0 / (I2 * I2);
726 MFEM_VERIFY(
Jtr != NULL,
727 "Requires a target Jacobian, use SetTargetJacobian().");
733 Id(0,0) = 1;
Id(0,1) = 0;
734 Id(1,0) = 0;
Id(1,1) = 1;
735 Id *=
Mat.FNorm()/pow(2,0.5);
744 MFEM_VERIFY(
Jtr != NULL,
745 "Requires a target Jacobian, use SetTargetJacobian().");
749 Id(0,0) = 1;
Id(0,1) = 0;
750 Id(1,0) = 0;
Id(1,1) = 1;
764 return (I2b - 1.0)*(I2b - 1.0) - I2b + std::sqrt(I2b*I2b +
eps);
769 MFEM_ABORT(
"Metric not implemented yet. Use metric mu_55 instead.");
777 MFEM_ABORT(
"Metric not implemented yet. Use metric mu_55 instead.");
785 return 0.5*(I2b - 1.0)*(I2b - 1.0)/(I2b -
tau0);
796 const double c = (I2b - 1.0)/(I2b -
tau0);
812 const double c0 = 1.0/(I2b -
tau0);
813 const double c = c0*(I2b - 1.0);
824 return Jpt.FNorm() * inv.FNorm() / 3.0 - 1.0;
872 const double a = weight/(6*std::sqrt(I1b_I2b));
915 const double c1 = weight/9;
925 return Jpt.
FNorm2() / 3.0 / pow(Jpt.
Det(), 2.0 / 3.0) - 1.0;
958 const double fnorm = Jpt.FNorm();
959 return fnorm * fnorm * fnorm / pow(3.0, 1.5) / Jpt.
Det() - 1.0;
995 return (I3b - 1.0)*(I3b - 1.0) - I3b + std::sqrt(I3b*I3b +
eps);
1002 const double c = 2*I3b-3+(I3b)/(std::pow((I3b*I3b+
eps),0.5));
1008 const double weight,
1014 const double c0 = I3b*I3b+
eps;
1015 const double c1 = 2 + 1/(pow(c0,0.5)) - I3b*I3b/(pow(c0,1.5));
1016 const double c2 = 2*I3b - 3 + I3b/(pow(c0,0.5));
1036 const double c = std::pow(d, -2.0/3.0);
1043 MFEM_ABORT(
"Metric not implemented yet.");
1048 const double weight,
1051 MFEM_ABORT(
"Metric not implemented yet.");
1072 const double weight,
1086 return 0.5 * (Jpt.
Det() + 1.0 / Jpt.
Det()) - 1.0;
1094 return 0.5*(I3b + 1.0/I3b) - 1.0;
1107 const double weight,
1122 double d = Jpt.
Det();
1123 return 0.5 * (d*d + 1.0 / (d*d)) - 1.0;
1131 return 0.5*(I3 + 1.0/I3) - 1.0;
1144 const double weight,
1162 invt.
Add(-1.0, Jpt);
1190 const double weight,
1204 const double c1 = weight*c0*c0;
1205 const double c2 = -2*c0*c1;
1220 adj_J_t.
Add(1.0, Jpt);
1221 return 1.0 / 6.0 / Jpt.
Det() * adj_J_t.
FNorm2();
1266 const double p13 = weight * pow(
ie.
Get_I3b(), 1.0/3.0),
1267 m13 = weight * pow(
ie.
Get_I3b(), -1.0/3.0),
1268 m23 = weight * pow(
ie.
Get_I3b(), -2.0/3.0),
1269 m43 = weight * pow(
ie.
Get_I3b(), -4.0/3.0),
1270 m53 = weight * pow(
ie.
Get_I3b(), -5.0/3.0),
1271 m73 = weight * pow(
ie.
Get_I3b(), -7.0/3.0);
1291 double fnorm = Jpt.FNorm();
1292 return fnorm * fnorm * fnorm - 3.0 * sqrt(3.0) * (log(Jpt.
Det()) + 1.0);
1332 return 0.5*(I3b - 1.0)*(I3b - 1.0)/(I3b -
tau0);
1343 const double c = (I3b - 1.0)/(I3b -
tau0);
1349 const double weight,
1364 const double c0 = 1.0/(I3b -
tau0);
1365 const double c = c0*(I3b - 1.0);
1376 const double fnorm = Jpt.FNorm();
1377 return fnorm * fnorm * fnorm / pow(3.0, 1.5) - Jpt.
Det();
1411 MFEM_VERIFY(
Jtr != NULL,
1412 "Requires a target Jacobian, use SetTargetJacobian().");
1427 Mult(AdjAt, WtW, WRK);
1437 MFEM_VERIFY(
Jtr != NULL,
1438 "Requires a target Jacobian, use SetTargetJacobian().");
1445 double sqalpha = pow(Jpr.
Det(), 0.5),
1446 sqomega = pow(
Jtr->
Det(), 0.5);
1448 return 0.5*pow(sqalpha/sqomega - sqomega/sqalpha, 2.);
1453 MFEM_VERIFY(
Jtr != NULL,
1454 "Requires a target Jacobian, use SetTargetJacobian().");
1469 MFEM_VERIFY(
Jtr != NULL,
1470 "Requires a target Jacobian, use SetTargetJacobian().");
1478 aw = Jpr.FNorm()/
Jtr->FNorm();
1490 MFEM_VERIFY(
nodes,
"Nodes are not given!");
1491 MFEM_ASSERT(
avg_volume == 0.0,
"The average volume is already computed!");
1494 const int NE = mesh->
GetNE();
1496 double volume = 0.0;
1498 for (
int i = 0; i < NE; i++)
1522 area_NE[0] = volume; area_NE[1] = NE;
1523 MPI_Allreduce(area_NE, area_NE + 2, 2, MPI_DOUBLE, MPI_SUM,
comm);
1542 const int NE = mesh->
GetNE();
1544 if (NE == 0) {
return; }
1547 "mixed meshes are not supported");
1548 MFEM_VERIFY(!fes.
IsVariableOrder(),
"variable orders are not supported");
1550 const int sdim = fes.
GetVDim();
1551 const int nvdofs = sdim*fe.GetDof();
1553 xe.
Size() == NE*nvdofs,
"invalid input Vector 'xe'!");
1563 if (dof_map->
Size() == 0) { dof_map =
nullptr; }
1567 Vector elfun_lex, elfun_nat;
1575 for (
int e = 0; e < NE; e++)
1586 const int ndofs = fe.GetDof();
1587 for (
int d = 0; d < sdim; d++)
1589 for (
int i_lex = 0; i_lex < ndofs; i_lex++)
1591 elfun_nat[(*dof_map)[i_lex]+d*ndofs] =
1592 elfun_lex[i_lex+d*ndofs];
1611 default: MFEM_ABORT(
"TargetType not added to ContainsVolumeInfo.");
1621 MFEM_CONTRACT_VAR(elfun);
1629 MFEM_ASSERT(Wideal.
Width() == Jtr.
SizeJ(),
"");
1635 for (
int i = 0; i < ir.
GetNPoints(); i++) { Jtr(i) = Wideal; }
1647 el_volume =
avg_volume / ncmesh->GetElementSizeReduction(e_id);
1651 1./W.Height()), Wideal);
1652 for (
int i = 0; i < ir.
GetNPoints(); i++) { Jtr(i) = W; }
1675 const double det = Jtr(i).Det();
1676 MFEM_VERIFY(det > 0.0,
"The given mesh is inverted!");
1677 Jtr(i).Set(std::pow(det / detW, 1./
dim), Wideal);
1683 MFEM_ABORT(
"invalid target type!");
1693 MFEM_CONTRACT_VAR(elfun);
1723 "Target type GIVEN_FULL requires a MatrixCoefficient.");
1740 MFEM_ABORT(
"Incompatible target type for analytic adaptation!");
1758 "Target type GIVEN_FULL requires a TMOPMatrixCoefficient.");
1760 for (
int d = 0; d < fe->
GetDim(); d++)
1773 MFEM_ABORT(
"Incompatible target type for analytic adaptation!");
1783 static inline void device_copy(
double *d_dest,
const double *d_src,
int size)
1785 mfem::forall(size, [=] MFEM_HOST_DEVICE (
int i) { d_dest[i] = d_src[i]; });
1793 MFEM_VERIFY(
adapt_eval,
"SetAdaptivityEvaluator() has not been called!")
1794 MFEM_VERIFY(
ncomp > 0,
"No target specifications have been set!");
1838 MFEM_VERIFY(ndof ==
tspec.
Size()/
ncomp,
"Inconsistency in SetTspecAtIndex.");
1840 const auto tspec__d = tspec_.
Read();
1842 const int offset = idx*ndof;
1843 internal::device_copy(tspec_d + offset, tspec__d, ndof*vdim);
1850 "Discrete target size should be ordered byNodes.");
1860 "Discrete target skewness should be ordered byNodes.");
1870 "Discrete target aspect ratio should be ordered byNodes.");
1880 "Discrete target orientation should be ordered byNodes.");
1891 #endif // MFEM_USE_MPI 1908 const auto tspec_temp_d = tspec_temp.
Read();
1910 internal::device_copy(tspec_d, tspec_temp_d, tspec_temp.
Size());
1912 const auto tspec__d = tspec_.
Read();
1913 const int offset = (
ncomp-vdim)*ndof;
1914 internal::device_copy(tspec_d + offset, tspec__d, ndof*vdim);
1921 MFEM_VERIFY(ndof ==
tspec.
Size()/
ncomp,
"Inconsistency in SetTargetSpec.");
1923 const auto tspec__d = tspec_.
Read();
1925 const int offset = idx*ndof;
1926 internal::device_copy(tspec_d + offset, tspec__d, ndof*vdim);
1933 "Discrete target size should be ordered byNodes.");
1943 "Discrete target skewness should be ordered byNodes.");
1953 "Discrete target aspect ratio should be ordered byNodes.");
1963 "Discrete target orientation should be ordered byNodes.");
1972 MFEM_VERIFY(
adapt_eval,
"SetAdaptivityEvaluator() has not been called!")
1973 MFEM_VERIFY(
ncomp > 0,
"No target specifications have been set!");
1993 if (idx < 0) {
return; }
1997 "Inconsistency in GetSerialDiscreteTargetSpec.");
1999 for (
int i = 0; i < ndof*vdim; i++)
2001 tspec_(i) =
tspec(i + idx*ndof);
2028 MFEM_VERIFY(
tspec.
Size() > 0,
"Target specification is not set!");
2044 int dofidx,
int dir,
2047 MFEM_VERIFY(
tspec.
Size() > 0,
"Target specification is not set!");
2053 for (
int i = 0; i <
ncomp; i++)
2055 tspec(dofs[dofidx]+i*cnt) = IntData(dofs[dofidx] + i*cnt + dir*cnt*
ncomp);
2062 MFEM_VERIFY(
tspec.
Size() > 0,
"Target specification is not set!");
2067 for (
int i = 0; i <
ncomp; i++)
2082 ntspec_dofs = ndofs*
ncomp;
2084 Vector tspec_vals(ntspec_dofs);
2095 MFEM_ABORT(
"Incompatible target type for discrete adaptation!");
2112 MFEM_VERIFY(
tspec_fesv,
"No target specifications have been set.");
2127 ntspec_dofs = ndofs*
ncomp;
2129 Vector shape(ndofs), tspec_vals(ntspec_dofs), par_vals,
2130 par_vals_c1, par_vals_c2, par_vals_c3;
2139 MFEM_VERIFY(
amr_el >= 0,
" Target being constructed for an AMR element.");
2140 for (
int i = 0; i <
ncomp; i++)
2142 for (
int j = 0; j < ndofs; j++)
2156 for (
int q = 0; q < nqp; q++)
2161 for (
int d = 0; d < 4; d++)
2170 double min_size = par_vals.
Min();
2172 MFEM_VERIFY(min_size > 0.0,
2173 "Non-positive size propagated in the target definition.");
2175 double size = fmax(shape * par_vals, min_size);
2181 Jtr(q).Set(std::pow(size, 1.0/
dim), Jtr(q));
2194 const double min_size = par_vals.
Min();
2195 MFEM_VERIFY(min_size > 0.0,
2196 "Non-positive aspect-ratio propagated in the target definition.");
2198 const double aspectratio = shape * par_vals;
2200 D_rho(0,0) = 1./pow(aspectratio,0.5);
2201 D_rho(1,1) = pow(aspectratio,0.5);
2211 const double rho1 = shape * par_vals_c1;
2212 const double rho2 = shape * par_vals_c2;
2213 const double rho3 = shape * par_vals_c3;
2215 D_rho(0,0) = pow(rho1,2./3.);
2216 D_rho(1,1) = pow(rho2,2./3.);
2217 D_rho(2,2) = pow(rho3,2./3.);
2222 Mult(D_rho, Temp, Jtr(q));
2232 const double skew = shape * par_vals;
2236 Q_phi(0,1) = cos(skew);
2237 Q_phi(1,1) = sin(skew);
2247 const double phi12 = shape * par_vals_c1;
2248 const double phi13 = shape * par_vals_c2;
2249 const double chi = shape * par_vals_c3;
2253 Q_phi(0,1) = cos(phi12);
2254 Q_phi(0,2) = cos(phi13);
2256 Q_phi(1,1) = sin(phi12);
2257 Q_phi(1,2) = sin(phi13)*cos(chi);
2259 Q_phi(2,2) = sin(phi13)*sin(chi);
2264 Mult(Q_phi, Temp, Jtr(q));
2274 const double theta = shape * par_vals;
2275 R_theta(0,0) = cos(theta);
2276 R_theta(0,1) = -sin(theta);
2277 R_theta(1,0) = sin(theta);
2278 R_theta(1,1) = cos(theta);
2288 const double theta = shape * par_vals_c1;
2289 const double psi = shape * par_vals_c2;
2290 const double beta = shape * par_vals_c3;
2292 double ct = cos(theta), st = sin(theta),
2293 cp = cos(psi), sp = sin(psi),
2297 R_theta(0,0) = ct*sp;
2298 R_theta(1,0) = st*sp;
2301 R_theta(0,1) = -st*cb + ct*cp*sb;
2302 R_theta(1,1) = ct*cb + st*cp*sb;
2303 R_theta(2,1) = -sp*sb;
2305 R_theta(0,0) = -st*sb - ct*cp*cb;
2306 R_theta(1,0) = ct*sb - st*cp*cb;
2307 R_theta(2,0) = sp*cb;
2310 Jtrcomp_q = R_theta;
2312 Mult(R_theta, Temp, Jtr(q));
2318 MFEM_ABORT(
"Incompatible target type for discrete adaptation!");
2329 MFEM_VERIFY(
tspec_fesv,
"No target specifications have been set.");
2344 ntspec_dofs = ndofs*
ncomp;
2346 Vector shape(ndofs), tspec_vals(ntspec_dofs), par_vals,
2347 par_vals_c1(ndofs), par_vals_c2(ndofs), par_vals_c3(ndofs);
2357 grad_e_c2(ndofs,
dim),
2358 grad_e_c3(ndofs,
dim);
2359 Vector grad_ptr_c1(grad_e_c1.GetData(), ndofs*
dim),
2360 grad_ptr_c2(grad_e_c2.GetData(), ndofs*
dim),
2379 grad_phys.Mult(par_vals, grad_ptr_c1);
2382 grad_e_c1.MultTranspose(shape, grad_q);
2384 const double min_size = par_vals.
Min();
2385 MFEM_VERIFY(min_size > 0.0,
2386 "Non-positive size propagated in the target definition.");
2387 const double size = std::max(shape * par_vals, min_size);
2388 double dz_dsize = (1./
dim)*pow(size, 1./
dim - 1.);
2390 Mult(Jtrcomp_q, Jtrcomp_d, work1);
2391 Mult(Jtrcomp_r, work1, work2);
2393 for (
int d = 0; d <
dim; d++)
2397 work1.
Set(dz_dsize, work1);
2399 AddMult(work1, work2, dJtr_i);
2412 grad_phys.Mult(par_vals, grad_ptr_c1);
2415 grad_e_c1.MultTranspose(shape, grad_q);
2417 const double aspectratio = shape * par_vals;
2419 dD_rho(0,0) = -0.5*pow(aspectratio,-1.5);
2420 dD_rho(1,1) = 0.5*pow(aspectratio,-0.5);
2422 Mult(Jtrcomp_s, Jtrcomp_r, work1);
2423 Mult(work1, Jtrcomp_q, work2);
2425 for (
int d = 0; d <
dim; d++)
2430 AddMult(work2, work1, dJtr_i);
2437 par_vals_c1.SetData(par_vals.
GetData());
2438 par_vals_c2.SetData(par_vals.
GetData()+ndofs);
2441 grad_phys.Mult(par_vals_c1, grad_ptr_c1);
2442 grad_phys.Mult(par_vals_c2, grad_ptr_c2);
2443 grad_phys.Mult(par_vals_c3, grad_ptr_c3);
2446 grad_e_c1.MultTranspose(shape, grad_q1);
2447 grad_e_c2.MultTranspose(shape, grad_q2);
2450 const double rho1 = shape * par_vals_c1;
2451 const double rho2 = shape * par_vals_c2;
2452 const double rho3 = shape * par_vals_c3;
2454 dD_rho(0,0) = (2./3.)*pow(rho1,-1./3.);
2455 dD_rho(1,1) = (2./3.)*pow(rho2,-1./3.);
2456 dD_rho(2,2) = (2./3.)*pow(rho3,-1./3.);
2458 Mult(Jtrcomp_s, Jtrcomp_r, work1);
2459 Mult(work1, Jtrcomp_q, work2);
2462 for (
int d = 0; d <
dim; d++)
2466 work1(0,0) *= grad_q1(d);
2467 work1(1,2) *= grad_q2(d);
2468 work1(2,2) *= grad_q3(d);
2470 AddMult(work2, work1, dJtr_i);
2482 grad_phys.Mult(par_vals, grad_ptr_c1);
2485 grad_e_c1.MultTranspose(shape, grad_q);
2487 const double skew = shape * par_vals;
2491 dQ_phi(0,1) = -sin(skew);
2492 dQ_phi(1,1) = cos(skew);
2494 Mult(Jtrcomp_s, Jtrcomp_r, work2);
2496 for (
int d = 0; d <
dim; d++)
2501 Mult(work1, Jtrcomp_d, work3);
2502 AddMult(work2, work3, dJtr_i);
2509 par_vals_c1.SetData(par_vals.
GetData());
2510 par_vals_c2.SetData(par_vals.
GetData()+ndofs);
2513 grad_phys.Mult(par_vals_c1, grad_ptr_c1);
2514 grad_phys.Mult(par_vals_c2, grad_ptr_c2);
2515 grad_phys.Mult(par_vals_c3, grad_ptr_c3);
2518 grad_e_c1.MultTranspose(shape, grad_q1);
2519 grad_e_c2.MultTranspose(shape, grad_q2);
2522 const double phi12 = shape * par_vals_c1;
2523 const double phi13 = shape * par_vals_c2;
2524 const double chi = shape * par_vals_c3;
2528 dQ_phi(0,1) = -sin(phi12);
2529 dQ_phi(1,1) = cos(phi12);
2532 dQ_phi13(0,2) = -sin(phi13);
2533 dQ_phi13(1,2) = cos(phi13)*cos(chi);
2534 dQ_phi13(2,2) = cos(phi13)*sin(chi);
2537 dQ_phichi(1,2) = -sin(phi13)*sin(chi);
2538 dQ_phichi(2,2) = sin(phi13)*cos(chi);
2540 Mult(Jtrcomp_s, Jtrcomp_r, work2);
2542 for (
int d = 0; d <
dim; d++)
2546 work1 *= grad_q1(d);
2547 work1.Add(grad_q2(d), dQ_phi13);
2548 work1.Add(grad_q3(d), dQ_phichi);
2549 Mult(work1, Jtrcomp_d, work3);
2550 AddMult(work2, work3, dJtr_i);
2562 grad_phys.Mult(par_vals, grad_ptr_c1);
2565 grad_e_c1.MultTranspose(shape, grad_q);
2567 const double theta = shape * par_vals;
2568 dR_theta(0,0) = -sin(theta);
2569 dR_theta(0,1) = -cos(theta);
2570 dR_theta(1,0) = cos(theta);
2571 dR_theta(1,1) = -sin(theta);
2573 Mult(Jtrcomp_q, Jtrcomp_d, work1);
2574 Mult(Jtrcomp_s, work1, work2);
2575 for (
int d = 0; d <
dim; d++)
2580 AddMult(work1, work2, dJtr_i);
2587 par_vals_c1.SetData(par_vals.
GetData());
2588 par_vals_c2.SetData(par_vals.
GetData()+ndofs);
2591 grad_phys.Mult(par_vals_c1, grad_ptr_c1);
2592 grad_phys.Mult(par_vals_c2, grad_ptr_c2);
2593 grad_phys.Mult(par_vals_c3, grad_ptr_c3);
2596 grad_e_c1.MultTranspose(shape, grad_q1);
2597 grad_e_c2.MultTranspose(shape, grad_q2);
2600 const double theta = shape * par_vals_c1;
2601 const double psi = shape * par_vals_c2;
2602 const double beta = shape * par_vals_c3;
2604 const double ct = cos(theta), st = sin(theta),
2605 cp = cos(psi), sp = sin(psi),
2609 dR_theta(0,0) = -st*sp;
2610 dR_theta(1,0) = ct*sp;
2613 dR_theta(0,1) = -ct*cb - st*cp*sb;
2614 dR_theta(1,1) = -st*cb + ct*cp*sb;
2617 dR_theta(0,0) = -ct*sb + st*cp*cb;
2618 dR_theta(1,0) = -st*sb - ct*cp*cb;
2626 dR_beta(0,1) = st*sb + ct*cp*cb;
2627 dR_beta(1,1) = -ct*sb + st*cp*cb;
2628 dR_beta(2,1) = -sp*cb;
2630 dR_beta(0,0) = -st*cb + ct*cp*sb;
2631 dR_beta(1,0) = ct*cb + st*cp*sb;
2635 dR_psi(0,0) = ct*cp;
2636 dR_psi(1,0) = st*cp;
2639 dR_psi(0,1) = 0. - ct*sp*sb;
2640 dR_psi(1,1) = 0. + st*sp*sb;
2641 dR_psi(2,1) = -cp*sb;
2643 dR_psi(0,0) = 0. + ct*sp*cb;
2644 dR_psi(1,0) = 0. + st*sp*cb;
2645 dR_psi(2,0) = cp*cb;
2647 Mult(Jtrcomp_q, Jtrcomp_d, work1);
2648 Mult(Jtrcomp_s, work1, work2);
2649 for (
int d = 0; d <
dim; d++)
2653 work1 *= grad_q1(d);
2654 work1.Add(grad_q2(d), dR_psi);
2655 work1.Add(grad_q3(d), dR_beta);
2656 AddMult(work1, work2, dJtr_i);
2664 MFEM_ABORT(
"Incompatible target type for discrete adaptation!");
2683 for (
int j = 0; j <
dim; j++)
2685 for (
int i = 0; i < cnt; i++)
2694 for (
int i = 0; i < cnt; i++)
2706 bool reuse_flag,
int x_ordering)
2713 totmix = 1+2*(
dim-2);
2722 for (
int j = 0; j <
dim; j++)
2724 for (
int i = 0; i < cnt; i++)
2733 for (
int i = 0; i < cnt; i++)
2742 for (
int k1 = 0; k1 <
dim; k1++)
2744 for (
int k2 = 0; (k1 != k2) && (k2 <
dim); k2++)
2746 for (
int i = 0; i < cnt; i++)
2757 for (
int i = 0; i < cnt; i++)
2788 f.GetVDim(),
f.GetOrdering());
2799 f.GetVDim(),
f.GetOrdering());
2826 PA.H.GetMemory().DeleteDevice(copy_to_host);
2827 PA.H0.GetMemory().DeleteDevice(copy_to_host);
2828 if (!copy_to_host && !
PA.Jtr.GetMemory().HostIsValid())
2830 PA.Jtr_needs_update =
true;
2832 PA.Jtr.GetMemory().DeleteDevice(copy_to_host);
2844 for (
int i = 0; i <
ElemDer.Size(); i++)
2859 "'dist' must be a scalar GridFunction!");
2918 "Using both fitting approaches is not supported.");
2939 "Using both fitting approaches is not supported.");
2941 "Positions on a mesh without Nodes is not supported.");
2944 "Incompatible ordering of spaces!");
2962 "Using both fitting approaches is not supported.");
2986 #ifndef MFEM_USE_GSLIB 2987 MFEM_ABORT(
"Surface fitting from source requires GSLIB!");
3007 "Nodal ordering for gridfunction on source mesh and current mesh" 3008 "should be the same.");
3022 "Nodal ordering for gridfunction on source mesh and current mesh" 3023 "should be the same.");
3048 double &err_avg,
double &err_max)
3050 MFEM_VERIFY(
surf_fit_marker,
"Surface fitting has not been enabled.");
3056 bool parallel = (pfes) ?
true :
false;
3063 double err_sum = 0.0;
3064 for (
int i = 0; i < node_cnt; i++)
3071 const int dof_i = pfes->DofToVDof(i, 0);
3072 if (parallel && pfes->GetLocalTDofNumber(dof_i) < 0) {
continue; }
3076 double sigma_s = 0.0;
3081 for (
int d = 0; d <
dim; d++)
3084 pos(d*node_cnt + i) : pos(i*
dim + d);
3092 err_max = fmax(err_max, sigma_s);
3099 MPI_Comm comm = pfes->GetComm();
3100 MPI_Allreduce(MPI_IN_PLACE, &err_max, 1, MPI_DOUBLE, MPI_MAX, comm);
3101 MPI_Allreduce(MPI_IN_PLACE, &dof_cnt, 1, MPI_INT, MPI_SUM, comm);
3102 MPI_Allreduce(MPI_IN_PLACE, &err_sum, 1, MPI_DOUBLE, MPI_SUM, comm);
3106 err_avg = (dof_cnt > 0) ? err_sum / dof_cnt : 0.0;
3140 const int el_id = T.ElementNo;
3204 Vector adapt_lim_gf_q, adapt_lim_gf0_q;
3205 if (adaptive_limiting)
3217 const double weight =
3238 if (adaptive_limiting)
3240 const double diff = adapt_lim_gf_q(i) - adapt_lim_gf0_q(i);
3244 energy += weight * val;
3260 for (
int s = 0;
s < dof;
s++)
3263 const int scalar_dof_id = fes_fit->
VDofToDof(vdofs[
s]);
3272 sigma_e(
s) * sigma_e(
s);
3278 for (
int d = 0; d <
dim; d++)
3281 pos_target(d) = (*surf_fit_pos)(vdofs[d*dof +
s]);
3299 NEsplit = elfun.
Size() / (dof*
dim), el_id = T.ElementNo;
3308 for (
int e = 0; e < NEsplit; e++)
3315 for (
int i = 0; i < dof; i++)
3317 for (
int d = 0; d <
dim; d++)
3323 elfun_child(i + d*dof) = elfun(i + e*dof + d*dof*NEsplit);
3330 double el_energy = 0;
3357 const double weight =
3367 el_energy += weight * val;
3370 energy += el_energy;
3416 const double weight =
3426 energy += weight * val;
3490 Vector shape,
p, p0, d_vals, grad;
3507 d_vals.
SetSize(nqp); d_vals = 1.0;
3532 for (
int q = 0; q < nqp; q++)
3558 for (
int d = 0; d <
dim; d++)
3562 d_detW_dx(d) = dwdx.
Trace();
3569 for (
int d = 0; d <
dim; d++)
3574 Mult(Amat, work2, work1);
3576 d_Winv_dx(d) = work2.
Trace();
3578 d_Winv_dx *= -weight_m;
3580 d_detW_dx += d_Winv_dx;
3642 d_vals.
SetSize(nqp); d_vals = 1.0;
3659 for (
int q = 0; q < nqp; q++)
3685 for (
int i = 0; i < dof; i++)
3687 const double w_shape_i = weight_m * shape(i);
3688 for (
int j = 0; j < dof; j++)
3690 const double w = w_shape_i * shape(j);
3691 for (
int d1 = 0; d1 <
dim; d1++)
3693 for (
int d2 = 0; d2 <
dim; d2++)
3695 elmat(d1*dof + i, d2*dof + j) += w * hess(d1, d2);
3716 Vector shape(dof), adapt_lim_gf_e, adapt_lim_gf_q, adapt_lim_gf0_q(nqp);
3730 grad_phys.
Mult(adapt_lim_gf_e, grad_ptr);
3734 for (
int q = 0; q < nqp; q++)
3738 adapt_lim_gf_grad_e.
MultTranspose(shape, adapt_lim_gf_grad_q);
3739 adapt_lim_gf_grad_q *= 2.0 * (adapt_lim_gf_q(q) - adapt_lim_gf0_q(q));
3752 Vector shape(dof), adapt_lim_gf_e, adapt_lim_gf_q, adapt_lim_gf0_q(nqp);
3766 grad_phys.
Mult(adapt_lim_gf_e, grad_ptr);
3771 Mult(grad_phys, adapt_lim_gf_grad_e, adapt_lim_gf_hess_e);
3778 for (
int q = 0; q < nqp; q++)
3783 adapt_lim_gf_grad_e.
MultTranspose(shape, adapt_lim_gf_grad_q);
3788 for (
int i = 0; i < dof *
dim; i++)
3790 const int idof = i % dof, idim = i / dof;
3791 for (
int j = 0; j <= i; j++)
3793 const int jdof = j % dof, jdim = j / dof;
3794 const double entry =
3795 w * ( 2.0 * adapt_lim_gf_grad_q(idim) * shape(idof) *
3796 adapt_lim_gf_grad_q(jdim) * shape(jdof) +
3797 2.0 * (adapt_lim_gf_q(q) - adapt_lim_gf0_q(q)) *
3798 adapt_lim_gf_hess_q(idim, jdim) * shape(idof) * shape(jdof));
3800 if (i != j) { mat(j, i) += entry; }
3822 for (
int s = 0;
s < dof_s;
s++)
3825 const int scalar_dof_id = fes_fit->
VDofToDof(vdofs[
s]);
3826 count += ((*surf_fit_marker)[scalar_dof_id]) ? 1 : 0;
3828 if (count == 0) {
return; }
3848 grad_phys.Mult(sigma_e, grad_ptr);
3855 for (
int s = 0;
s < dof_s;
s++)
3858 const int scalar_dof_id = fes_fit->
VDofToDof(vdofs[
s]);
3870 for (
int d = 0; d <
dim; d++)
3873 pos_target(d) = (*surf_fit_pos)(vdofs[d*dof_s +
s]);
3877 for (
int d = 0; d <
dim; d++) { surf_fit_grad_e(
s, d) = grad_s(d); }
3880 for (
int d = 0; d <
dim; d++)
3882 mat(
s, d) += w * surf_fit_grad_e(
s, d);
3903 for (
int s = 0;
s < dof_s;
s++)
3906 const int scalar_dof_id = fes_fit->
VDofToDof(vdofs[
s]);
3907 count += ((*surf_fit_marker)[scalar_dof_id]) ? 1 : 0;
3909 if (count == 0) {
return; }
3930 grad_phys.Mult(sigma_e, grad_ptr);
3944 Mult(grad_phys, surf_fit_grad_e, surf_fit_hess_e);
3953 for (
int s = 0;
s < dof_s;
s++)
3956 const int scalar_dof_id = fes_fit->
VDofToDof(vdofs[
s]);
3966 surf_fit_hess_e.
GetRow(
s, gg_ptr);
3972 for (
int d = 0; d <
dim; d++)
3975 pos_target(d) = (*surf_fit_pos)(vdofs[d*dof_s +
s]);
3980 for (
int d = 0; d <
dim; d++) { surf_fit_grad_e(
s, d) = 0.0; }
3985 for (
int idim = 0; idim <
dim; idim++)
3987 for (
int jdim = 0; jdim <= idim; jdim++)
3989 double entry = w * ( surf_fit_grad_e(
s, idim) *
3990 surf_fit_grad_e(
s, jdim) +
3991 sigma_e(
s) * surf_fit_hess_s(idim, jdim));
3993 int idx =
s + idim*dof_s;
3994 int jdx =
s + jdim*dof_s;
3995 mat(idx, jdx) += entry;
3996 if (idx != jdx) { mat(jdx, idx) += entry; }
4004 Vector &elfun,
const int dofidx,
4005 const int dir,
const double e_fx,
4009 int idx = dir*dof+dofidx;
4013 double dfdx = (e_fxph-e_fx)/
dx;
4018 (*(
ElemDer[T.ElementNo]))(idx) = dfdx;
4047 for (
int j = 0; j <
dim; j++)
4049 for (
int i = 0; i < dof; i++)
4079 for (
int q = 0; q < nqp; q++)
4107 for (
int i = 0; i < dof; i++)
4109 for (
int j = 0; j < i+1; j++)
4111 for (
int k1 = 0; k1 <
dim; k1++)
4113 for (
int k2 = 0; k2 <
dim; k2++)
4115 elfunmod(k2*dof+j) +=
dx;
4142 double e_fx = ElemPertLoc(k2*dof+j);
4145 elfunmod(k2*dof+j) -=
dx;
4146 double e_fpx = ElemDerLoc(k1*dof+i);
4148 elmat(k1*dof+i, k2*dof+j) = (e_fpxph - e_fpx) /
dx;
4149 elmat(k2*dof+j, k1*dof+i) = (e_fpxph - e_fpx) /
dx;
4179 for (
int q = 0; q < nqp; q++)
4198 MFEM_VERIFY(cf,
"Dynamic weight works only with a ConstantCoefficient.");
4199 cf->constant *= factor;
4208 MFEM_VERIFY(cf,
"Dynamic weight works only with a ConstantCoefficient.");
4209 return cf->constant;
4238 double &metric_energy,
4240 double &surf_fit_gf_energy)
4251 metric_energy = 0.0;
4253 surf_fit_gf_energy = 0.0;
4254 for (
int i = 0; i <
fes->
GetNE(); i++)
4260 const int dof = fe->
GetDof();
4269 for (
int q = 0; q < nqp; q++)
4274 const double weight =
4282 lim_energy += weight;
4292 for (
int s = 0;
s < dofs.
Size();
s++)
4296 surf_fit_gf_energy += sigma_e(
s) * sigma_e(
s);
4323 dx = std::numeric_limits<float>::max();
4326 double detv_avg_min = std::numeric_limits<float>::max();
4327 for (
int i = 0; i < NE; i++)
4332 for (
int j = 0; j < nsp; j++)
4336 detv_sum += std::fabs(
Jpr.
Det());
4338 double detv_avg = pow(detv_sum/nsp, 1./
dim);
4339 detv_avg_min = std::min(detv_avg, detv_avg_min);
4348 if (
discr_tc) {
PA.Jtr_needs_update =
true; }
4380 const int total_cnt = x_new.
Size()/
dim;
4384 for (
int d = 0; d <
dim; d++)
4386 for (
int i = 0; i < cnt; i++)
4389 new_x_sorted(i + d*cnt) = x_new(dof_index + d*total_cnt);
4395 for (
int i = 0; i < cnt; i++)
4398 for (
int d = 0; d <
dim; d++)
4400 new_x_sorted(d + i*
dim) = x_new(d + dof_index*
dim);
4405 Vector surf_fit_gf_int, surf_fit_grad_int, surf_fit_hess_int;
4407 new_x_sorted, surf_fit_gf_int, ordering);
4408 for (
int i = 0; i < cnt; i++)
4411 (*surf_fit_gf)[dof_index] = surf_fit_gf_int(i);
4415 new_x_sorted, surf_fit_grad_int, ordering);
4421 for (
int d = 0; d < grad_dim; d++)
4423 for (
int i = 0; i < cnt; i++)
4426 (*surf_fit_grad)[dof_index + d*grad_cnt] =
4427 surf_fit_grad_int(i + d*cnt);
4433 for (
int i = 0; i < cnt; i++)
4436 for (
int d = 0; d < grad_dim; d++)
4438 (*surf_fit_grad)[dof_index*
dim + d] =
4439 surf_fit_grad_int(i*
dim + d);
4445 new_x_sorted, surf_fit_hess_int, ordering);
4451 for (
int d = 0; d < hess_dim; d++)
4453 for (
int i = 0; i < cnt; i++)
4456 (*surf_fit_hess)[dof_index + d*hess_cnt] =
4457 surf_fit_hess_int(i + d*cnt);
4463 for (
int i = 0; i < cnt; i++)
4466 for (
int d = 0; d < hess_dim; d++)
4468 (*surf_fit_hess)[dof_index*
dim + d] =
4469 surf_fit_hess_int(i*
dim + d);
4491 MPI_Allreduce(&
dx, &min_jac_all, 1, MPI_DOUBLE, MPI_MIN, pfes->
GetComm());
4504 #ifdef MFEM_USE_GSLIB 4506 if (dynamic_cast<const InterpolatorFP *>(ae))
4508 MFEM_ABORT(
"Using GSLIB-based interpolation with finite differences" 4509 "requires careful consideration. Contact TMOP team.");
4526 #ifdef MFEM_USE_GSLIB 4528 if (dynamic_cast<const InterpolatorFP *>(ae))
4530 MFEM_ABORT(
"Using GSLIB-based interpolation with finite differences" 4531 "requires careful consideration. Contact TMOP team.");
4552 for (
int i = 0; i < NE; i++)
4568 for (
int q = 0; q < nsp; q++)