35 #ifndef UTILITIES_NEKMESH_NODEOPTI_EVALUATOR 36 #define UTILITIES_NEKMESH_NODEOPTI_EVALUATOR 56 boost::ignore_unused(jac);
62 return jac[0][0] * jac[1][1] - jac[0][1] * jac[1][0];
67 return jac[0][0] * (jac[1][1] * jac[2][2] - jac[2][1] * jac[1][2]) -
68 jac[0][1] * (jac[1][0] * jac[2][2] - jac[1][2] * jac[2][0]) +
69 jac[0][2] * (jac[1][0] * jac[2][1] - jac[1][1] * jac[2][0]);
83 boost::ignore_unused(in,out);
90 out[0][0] = in[1][1] * invDet;
91 out[1][0] = -in[0][1] * invDet;
92 out[0][1] = -in[1][0] * invDet;
93 out[1][1] = in[0][0] * invDet;
100 out[0][0] = (in[1][1] * in[2][2] - in[2][1] * in[1][2]) * invdet;
101 out[1][0] = -(in[0][1] * in[2][2] - in[0][2] * in[2][1]) * invdet;
102 out[2][0] = (in[0][1] * in[1][2] - in[0][2] * in[1][1]) * invdet;
103 out[0][1] = -(in[1][0] * in[2][2] - in[1][2] * in[2][0]) * invdet;
104 out[1][1] = (in[0][0] * in[2][2] - in[0][2] * in[2][0]) * invdet;
105 out[2][1] = -(in[0][0] * in[1][2] - in[1][0] * in[0][2]) * invdet;
106 out[0][2] = (in[1][0] * in[2][1] - in[2][0] * in[1][1]) * invdet;
107 out[1][2] = -(in[0][0] * in[2][1] - in[2][0] * in[0][1]) * invdet;
108 out[2][2] = (in[0][0] * in[1][1] - in[1][0] * in[0][1]) * invdet;
135 boost::ignore_unused(in1,in2);
142 return in1[0] * in2[0]
148 return in1[0] * in2[0]
166 boost::ignore_unused(in,out);
171 out[0][0] = 0.5 * (in[0][0] * in[0][0] + in[1][0] * in[1][0] - 1.0);
172 out[1][0] = 0.5 * (in[0][0] * in[0][1] + in[1][0] * in[1][1]);
173 out[0][1] = 0.5 * (in[0][0] * in[0][1] + in[1][0] * in[1][1]);
174 out[1][1] = 0.5 * (in[1][1] * in[1][1] + in[0][1] * in[0][1] - 1.0);
179 out[0][0] = 0.5 * (in[0][0] * in[0][0] + in[1][0] * in[1][0] +
180 in[2][0] * in[2][0] - 1.0);
181 out[1][0] = 0.5 * (in[0][0] * in[1][0] + in[1][0] * in[1][1] +
182 in[2][0] * in[2][1]);
183 out[0][1] = out[1][0];
184 out[2][0] = 0.5 * (in[0][0] * in[0][2] + in[1][0] * in[1][2] +
185 in[2][0] * in[2][2]);
186 out[0][2] = out[2][0];
187 out[1][1] = 0.5 * (in[0][1] * in[0][1] + in[1][1] * in[1][1] +
188 in[2][1] * in[2][1] - 1.0);
189 out[1][2] = 0.5 * (in[0][1] * in[0][2] + in[1][1] * in[1][2] +
190 in[2][1] * in[2][2]);
191 out[2][1] = out[1][2];
192 out[2][2] = 0.5 * (in[0][2] * in[0][2] + in[1][2] * in[1][2] +
193 in[2][2] * in[2][2] - 1.0);
205 boost::ignore_unused(in1,in2);
212 return in1[0][0] * in2[0][0]
213 + in1[0][1] * in2[0][1]
214 + in1[1][0] * in2[1][0]
215 + in1[1][1] * in2[1][1] ;
221 return in1[0][0] * in2[0][0]
222 + in1[0][1] * in2[0][1]
223 + in1[0][2] * in2[0][2]
224 + in1[1][0] * in2[1][0]
225 + in1[1][1] * in2[1][1]
226 + in1[1][2] * in2[1][2]
227 + in1[2][0] * in2[2][0]
228 + in1[2][1] * in2[2][1]
229 + in1[2][2] * in2[2][2] ;
240 boost::ignore_unused(inarray);
247 return inarray[0][0] * inarray[0][0]
248 + inarray[0][1] * inarray[0][1]
249 + inarray[1][0] * inarray[1][0]
250 + inarray[1][1] * inarray[1][1] ;
256 return inarray[0][0] * inarray[0][0]
257 + inarray[0][1] * inarray[0][1]
258 + inarray[0][2] * inarray[0][2]
259 + inarray[1][0] * inarray[1][0]
260 + inarray[1][1] * inarray[1][1]
261 + inarray[1][2] * inarray[1][2]
262 + inarray[2][0] * inarray[2][0]
263 + inarray[2][1] * inarray[2][1]
264 + inarray[2][2] * inarray[2][2] ;
276 for (
auto &typeIt : m_data)
278 const int ptsStd = m_derivUtils[typeIt.first]->ptsStd;
279 const int pts = m_derivUtils[typeIt.first]->pts;
280 const int nElmt = typeIt.second.size();
285 for (
int i = 0, cnt = 0; i < nElmt; ++i)
287 for (
int j = 0; j < ptsStd; ++j)
289 for (
int d = 0; d < DIM; ++d)
291 X[cnt + d * ptsStd + j] =
292 *(typeIt.second[i]->nodes[j][d]);
305 for (
int d = 0; d < DIM; ++d)
307 Blas::Dgemm(
'N',
'N', pts, DIM * nElmt, ptsStd, 1.0,
308 m_derivUtils[typeIt.first]->VdmD[d].GetRawPtr(),
310 &m_derivs[typeIt.first][d][0][0][0], pts);
314 minJacNew = std::numeric_limits<double>::max();
317 m_minJac < 0.0 ? sqrt(1e-8 + 0.04 * m_minJac * m_minJac) : 1e-4;
319 m_grad = vector<NekDouble>(DIM == 2 ? 5 : 9, 0.0);
326 const NekDouble mu = 1.0 / 2.0 / (1.0 + nu);
327 const NekDouble K = 1.0 / 3.0 / (1.0 - 2.0 * nu);
329 for (
auto &typeIt : m_data)
331 const int nElmt = typeIt.second.size();
332 const int pts = m_derivUtils[typeIt.first]->pts;
335 m_derivUtils[typeIt.first]->quadW;
337 for (
int i = 0; i < nElmt; ++i)
339 for (
int k = 0; k < pts; ++k)
342 for (
int l = 0; l < DIM; ++l)
344 for (
int n = 0; n < DIM; ++n)
347 m_derivs[typeIt.first][l][i][n][k];
352 for (
int m = 0; m < DIM; ++m)
354 for (
int n = 0; n < DIM; ++n)
356 jacIdeal[n][m] = 0.0;
357 for (
int l = 0; l < DIM; ++l)
359 jacIdeal[n][m] += phiM[n][l] *
360 typeIt.second[i]->maps[k][m * 3 + l];
367 NekDouble absIdealMapDet = fabs(typeIt.second[i]->maps[k][9]);
368 minJacNew = min(minJacNew, jacDet);
371 EMatrix<DIM>(jacIdeal, Emat);
373 NekDouble trEtE = FrobProd<DIM>(Emat, Emat);
376 (jacDet + sqrt(jacDet * jacDet + 4.0 * ep * ep));
378 if (sigma < numeric_limits<double>::min() && !gradient)
380 return numeric_limits<double>::max();
382 ASSERTL0(sigma > numeric_limits<double>::min(),
383 std::string(
"dividing by zero ") +
384 boost::lexical_cast<string>(sigma) +
" " +
385 boost::lexical_cast<string>(jacDet) +
" " +
386 boost::lexical_cast<string>(ep));
389 integral += quadW[k] *
391 (K * 0.5 * lsigma * lsigma + mu * trEtE);
398 NekDouble derivDet = Determinant<DIM>(phiM);
400 InvTrans<DIM>(phiM, jacInvTrans);
403 for (
int m = 0; m < DIM; ++m)
406 m_derivUtils[typeIt.first]->VdmD[m])(
407 k, typeIt.second[i]->NodeId(m_node->m_id));
414 for (
int l = 0; l < DIM; ++l)
416 jacDeriv[l] = basisDeriv[l];
421 for (
int n = 0; n < DIM; ++n)
423 jacDerivPhi[n] = 0.0;
424 for (
int l = 0; l < DIM; ++l)
426 jacDerivPhi[n] += jacDeriv[l] *
427 typeIt.second[i]->maps[k][l + 3 * n];
431 for (
int m = 0; m < DIM; ++m)
433 jacDetDeriv[m] = 0.0;
434 for (
int n = 0; n < DIM; ++n)
436 jacDetDeriv[m] += jacInvTrans[m][n] * basisDeriv[n];
438 jacDetDeriv[m] *= derivDet / absIdealMapDet;
447 for(
int d = 0; d < DIM; d++)
449 for (
int m = 0; m < DIM; ++m)
451 for (
int n = 0; n < DIM; ++n)
453 M2[d][m][n] = 0.5*(jacDerivPhi[m] * jacIdeal[d][n]
454 + jacIdeal[d][m] * jacDerivPhi[n]);
459 for (
int m = 0; m < DIM; ++m)
461 NekDouble frobProdA = FrobProd<DIM>(M2[m], Emat);
464 quadW[k] * absIdealMapDet *
465 (2.0 * mu * frobProdA +
466 K * lsigma * jacDetDeriv[m] /
467 (2.0 * sigma - jacDet));
471 for (
int m = 0; m < DIM; ++m)
473 for (
int l = m; l < DIM; ++l, ct++)
475 NekDouble frobProdBC = FrobProd<DIM>(M2[m], M2[l]);
482 for (
int p = 0;
p < DIM; ++
p)
484 for (
int q = 0; q < DIM; ++q)
486 M3[
p][q] = jacDerivPhi[
p] * jacDerivPhi[q];
489 frobProdBC += FrobProd<DIM>(M3,Emat);
493 quadW[k] * absIdealMapDet *
494 (2.0 * mu * frobProdBC +
495 jacDetDeriv[m] * jacDetDeriv[l] * K /
496 (2.0 * sigma - jacDet) /
497 (2.0 * sigma - jacDet) *
498 (1.0 - jacDet * lsigma /
499 (2.0 * sigma - jacDet)));
512 const NekDouble mu = 1.0 / 2.0 / (1.0 + nu);
513 const NekDouble K = 1.0 / 3.0 / (1.0 - 2.0 * nu);
515 for (
auto &typeIt : m_data)
517 const int nElmt = typeIt.second.size();
518 const int pts = m_derivUtils[typeIt.first]->pts;
521 m_derivUtils[typeIt.first]->quadW;
523 for (
int i = 0; i < nElmt; ++i)
525 for (
int k = 0; k < pts; ++k)
528 for (
int l = 0; l < DIM; ++l)
530 for (
int n = 0; n < DIM; ++n)
533 m_derivs[typeIt.first][l][i][n][k];
537 for (
int m = 0; m < DIM; ++m)
539 for (
int n = 0; n < DIM; ++n)
541 jacIdeal[n][m] = 0.0;
542 for (
int l = 0; l < DIM; ++l)
544 jacIdeal[n][m] += phiM[n][l] *
545 typeIt.second[i]->maps[k][m * 3 + l];
552 minJacNew = min(minJacNew, jacDet);
554 NekDouble absIdealMapDet = fabs(typeIt.second[i]->maps[k][9]);
560 (jacDet + sqrt(jacDet * jacDet + 4.0 * ep * ep));
562 if (sigma < numeric_limits<double>::min() && !gradient)
564 return numeric_limits<double>::max();
567 ASSERTL0(sigma > numeric_limits<double>::min(),
568 std::string(
"dividing by zero ") +
569 boost::lexical_cast<string>(sigma) +
" " +
570 boost::lexical_cast<string>(jacDet) +
" " +
571 boost::lexical_cast<string>(ep));
574 integral += quadW[k] * absIdealMapDet *
575 (0.5 * mu * (I1 - 3.0 - 2.0 * lsigma) +
576 0.5 * K * lsigma * lsigma);
584 NekDouble derivDet = Determinant<DIM>(phiM);
586 InvTrans<DIM>(phiM, jacInvTrans);
589 for (
int m = 0; m < DIM; ++m)
592 *(m_derivUtils[typeIt.first]->VdmD[m].GetRawPtr() +
593 typeIt.second[i]->NodeId(m_node->m_id) * pts + k);
601 for (
int l = 0; l < DIM; ++l)
603 jacDeriv[l] = basisDeriv[l];
608 for (
int n = 0; n < DIM; ++n)
610 jacDerivPhi[n] = 0.0;
611 for (
int l = 0; l < DIM; ++l)
613 jacDerivPhi[n] += jacDeriv[l] *
614 typeIt.second[i]->maps[k][l + 3 * n];
618 for (
int m = 0; m < DIM; ++m)
620 jacDetDeriv[m] = 0.0;
621 for (
int n = 0; n < DIM; ++n)
623 jacDetDeriv[m] += jacInvTrans[m][n] * basisDeriv[n];
625 jacDetDeriv[m] *= derivDet / absIdealMapDet;
629 for (
int m = 0; m < DIM; ++m)
634 ScalarProd<DIM>(jacIdeal[m],jacDerivPhi);
637 quadW[k] * absIdealMapDet *
639 (jacDetDeriv[m] / (2.0 * sigma - jacDet) *
644 for (
int m = 0; m < DIM; ++m)
646 for (
int l = m; l < DIM; ++l, ct++)
655 frobProdHes = ScalarProd<DIM>(jacDerivPhi,jacDerivPhi);
659 quadW[k] * absIdealMapDet *
661 jacDetDeriv[m] * jacDetDeriv[l] /
662 (2.0 * sigma - jacDet) /
663 (2.0 * sigma - jacDet) *
664 (K - jacDet * (K * lsigma - mu) /
665 (2.0 * sigma - jacDet)));
677 for (
auto &typeIt : m_data)
679 const int nElmt = typeIt.second.size();
680 const int pts = m_derivUtils[typeIt.first]->pts;
683 m_derivUtils[typeIt.first]->quadW;
685 for (
int i = 0; i < nElmt; ++i)
687 for (
int k = 0; k < pts; ++k)
690 for (
int l = 0; l < DIM; ++l)
692 for (
int n = 0; n < DIM; ++n)
695 m_derivs[typeIt.first][l][i][n][k];
699 for (
int m = 0; m < DIM; ++m)
701 for (
int n = 0; n < DIM; ++n)
703 jacIdeal[n][m] = 0.0;
704 for (
int l = 0; l < DIM; ++l)
706 jacIdeal[n][m] += phiM[n][l] *
707 typeIt.second[i]->maps[k][m * 3 + l];
714 NekDouble absIdealMapDet = fabs(typeIt.second[i]->maps[k][9]);
715 minJacNew = min(minJacNew, jacDet);
719 (jacDet + sqrt(jacDet * jacDet + 4.0 * ep * ep));
721 if (sigma < numeric_limits<double>::min() && !gradient)
723 return numeric_limits<double>::max();
726 ASSERTL0(sigma > numeric_limits<double>::min(),
727 std::string(
"dividing by zero ") +
728 boost::lexical_cast<string>(sigma) +
" " +
729 boost::lexical_cast<string>(jacDet) +
" " +
730 boost::lexical_cast<string>(ep));
732 NekDouble W = frob / DIM / pow(fabs(sigma), 2.0 / DIM);
734 quadW[k] * absIdealMapDet * W;
742 NekDouble derivDet = Determinant<DIM>(phiM);
744 InvTrans<DIM>(phiM, jacInvTrans);
747 for (
int m = 0; m < DIM; ++m)
750 m_derivUtils[typeIt.first]->VdmD[m])(
751 k, typeIt.second[i]->NodeId(m_node->m_id));
758 for (
int l = 0; l < DIM; ++l)
760 jacDeriv[l] = basisDeriv[l];
765 for (
int n = 0; n < DIM; ++n)
767 jacDerivPhi[n] = 0.0;
768 for (
int l = 0; l < DIM; ++l)
770 jacDerivPhi[n] += jacDeriv[l] *
771 typeIt.second[i]->maps[k][l + 3 * n];
775 for (
int m = 0; m < DIM; ++m)
777 jacDetDeriv[m] = 0.0;
778 for (
int n = 0; n < DIM; ++n)
780 jacDetDeriv[m] += jacInvTrans[m][n] * basisDeriv[n];
782 jacDetDeriv[m] *= derivDet / absIdealMapDet;
788 for (
int m = 0; m < DIM; ++m)
792 frobProd[m] = ScalarProd<DIM>(jacIdeal[m],jacDerivPhi);
795 quadW[k] * absIdealMapDet *
796 (2.0 * W * (frobProd[m] / frob -
797 jacDetDeriv[m] / DIM /
798 (2.0 * sigma - jacDet)));
805 for (
int m = 0; m < DIM; ++m)
807 for (
int l = m; l < DIM; ++l, ct++)
816 frobProdHes = ScalarProd<DIM>(jacDerivPhi,jacDerivPhi);
820 quadW[k] * absIdealMapDet *
821 (inc[m] * inc[l] / W +
823 (frobProdHes / frob -
824 2.0 * frobProd[m] * frobProd[l] /
826 jacDetDeriv[m] * jacDetDeriv[l] *
828 (2.0 * sigma - jacDet) /
829 (2.0 * sigma - jacDet) /
830 (2.0 * sigma - jacDet) /
843 for (
auto &typeIt : m_data)
845 const int nElmt = typeIt.second.size();
846 const int pts = m_derivUtils[typeIt.first]->pts;
849 m_derivUtils[typeIt.first]->quadW;
851 for (
int i = 0; i < nElmt; ++i)
853 for (
int k = 0; k < pts; ++k)
856 for (
int l = 0; l < DIM; ++l)
858 for (
int n = 0; n < DIM; ++n)
861 m_derivs[typeIt.first][l][i][n][k];
865 for (
int m = 0; m < DIM; ++m)
867 for (
int n = 0; n < DIM; ++n)
869 jacIdeal[n][m] = 0.0;
870 for (
int l = 0; l < DIM; ++l)
872 jacIdeal[n][m] += phiM[n][l] *
873 typeIt.second[i]->maps[k][m * 3 + l];
880 NekDouble absIdealMapDet = fabs(typeIt.second[i]->maps[k][9]);
881 minJacNew = min(minJacNew, jacDet);
885 (jacDet + sqrt(jacDet * jacDet + 4.0 * ep * ep));
887 if (sigma < numeric_limits<double>::min() && !gradient)
889 return numeric_limits<double>::max();
892 ASSERTL0(sigma > numeric_limits<double>::min(),
893 std::string(
"dividing by zero ") +
894 boost::lexical_cast<string>(sigma) +
" " +
895 boost::lexical_cast<string>(jacDet) +
" " +
896 boost::lexical_cast<string>(ep));
900 quadW[k] * absIdealMapDet * W;
908 NekDouble derivDet = Determinant<DIM>(phiM);
910 InvTrans<DIM>(phiM, jacInvTrans);
913 for (
int m = 0; m < DIM; ++m)
916 m_derivUtils[typeIt.first]->VdmD[m])(
917 k, typeIt.second[i]->NodeId(m_node->m_id));
924 for (
int l = 0; l < DIM; ++l)
926 jacDeriv[l] = basisDeriv[l];
931 for (
int n = 0; n < DIM; ++n)
933 jacDerivPhi[n] = 0.0;
934 for (
int l = 0; l < DIM; ++l)
936 jacDerivPhi[n] += jacDeriv[l] *
937 typeIt.second[i]->maps[k][l + 3 * n];
941 for (
int m = 0; m < DIM; ++m)
943 jacDetDeriv[m] = 0.0;
944 for (
int n = 0; n < DIM; ++n)
946 jacDetDeriv[m] += jacInvTrans[m][n] * basisDeriv[n];
948 jacDetDeriv[m] *= derivDet / absIdealMapDet;
954 for (
int m = 0; m < DIM; ++m)
958 frobProd[m] = ScalarProd<DIM>(jacIdeal[m],jacDerivPhi);
964 (2.0 * frobProd[m] / frob -
965 jacDetDeriv[m] / (2.0 * sigma - jacDet)));
970 for (
int m = 0; m < DIM; ++m)
972 for (
int l = m; l < DIM; ++l, ct++)
981 frobProdHes = ScalarProd<DIM>(jacDerivPhi,jacDerivPhi);
985 quadW[k] * absIdealMapDet *
986 (inc[m] * inc[l] / W +
988 (frobProdHes / frob -
989 2.0 * frobProd[m] * frobProd[l] /
991 0.5 * jacDetDeriv[m] *
992 jacDetDeriv[l] * jacDet /
993 (2.0 * sigma - jacDet) /
994 (2.0 * sigma - jacDet) /
995 (2.0 * sigma - jacDet)));
#define ASSERTL0(condition, msg)
void InvTrans< 3 >(NekDouble in[][3], NekDouble out[][3])
void InvTrans< 2 >(NekDouble in[][2], NekDouble out[][2])
NekDouble FrobeniusNorm< 3 >(NekDouble inarray[][3])
NekDouble ScalarProd< 3 >(NekDouble(&in1)[3], NekDouble(&in2)[3])
void EMatrix< 2 >(NekDouble in[][2], NekDouble out[][2])
NekDouble FrobProd< 3 >(NekDouble in1[][3], NekDouble in2[][3])
static void Dgemm(const char &transa, const char &transb, const int &m, const int &n, const int &k, const double &alpha, const double *a, const int &lda, const double *b, const int &ldb, const double &beta, double *c, const int &ldc)
BLAS level 3: Matrix-matrix multiply C = A x B where A[m x n], B[n x k], C[m x k].
NekDouble Determinant< 2 >(NekDouble jac[][2])
NekDouble Determinant(NekDouble jac[][DIM])
Calculate determinant of input matrix.
void InvTrans(NekDouble in[][DIM], NekDouble out[][DIM])
Calculate inverse transpose of input matrix.
NekDouble FrobProd(NekDouble in1[][DIM], NekDouble in2[][DIM])
Calculate Frobenius inner product of input matrices.
NekDouble FrobProd< 2 >(NekDouble in1[][2], NekDouble in2[][2])
NekDouble FrobeniusNorm< 2 >(NekDouble inarray[][2])
NekDouble GetFunctional(NekDouble &minJacNew, bool gradient=true)
Evaluate functional for elements connected to a node.
NekDouble ScalarProd(NekDouble(&in1)[DIM], NekDouble(&in2)[DIM])
Calculate Scalar product of input vectors.
NekDouble ScalarProd< 2 >(NekDouble(&in1)[2], NekDouble(&in2)[2])
void EMatrix(NekDouble in[][DIM], NekDouble out[][DIM])
Calculate tensor used in derivation of linear elasticity gradients.
NekDouble FrobeniusNorm(NekDouble inarray[][DIM])
Calculate Frobenius norm of a matrix .
NekDouble Determinant< 3 >(NekDouble jac[][3])
void EMatrix< 3 >(NekDouble in[][3], NekDouble out[][3])