297template <
short_t dim,
class T,
bool linear >
300 return this->_compute_TF(patch,u,z);
303template <
short_t dim,
class T,
bool linear >
310 for (
index_t k=0; k!=u.cols(); k++)
312 for(
index_t j=0; j < z.rows(); ++j )
314 colIdx = j*u.cols()+k;
315 if (TF(0,colIdx) == 1 || TF(0,colIdx) == -1)
317 result(0,colIdx) = NAN;
319 else if (TF(0,colIdx) == 0)
321 gsMatrix<T> C = m_materialMat->eval3D_matrix(patch,u.col(k),z(j,k),MaterialOutput::MatrixA);
322 gsMatrix<T> N = m_materialMat->eval3D_stress(patch,u.col(k),z(j,k),MaterialOutput::VectorN);;
323 gsMatrix<T> E = m_materialMat->eval3D_strain(patch,u.col(k),z(j,k));
326 result(0,colIdx) = thetas(0,0);
329 GISMO_ERROR(
"Tension field data not understood: "<<TF(0,colIdx));
335template <
short_t dim,
class T,
bool linear >
342 for (
index_t k=0; k!=u.cols(); k++)
344 for(
index_t j=0; j < z.rows(); ++j )
346 colIdx = j*u.cols()+k;
347 if (TF(0,colIdx) == 1 || TF(0,colIdx) == -1)
349 result(0,colIdx) = NAN;
351 else if (TF(0,colIdx) == 0)
353 gsMatrix<T> C = m_materialMat->eval3D_matrix(patch,u.col(k),z(j,k),MaterialOutput::MatrixA);
354 gsMatrix<T> N = m_materialMat->eval3D_stress(patch,u.col(k),z(j,k),MaterialOutput::VectorN);;
355 gsMatrix<T> E = m_materialMat->eval3D_strain(patch,u.col(k),z(j,k));
358 result(0,colIdx) = _compute_gamma(thetas(0,0),C.
reshape(3,3),N.reshape(3,1),E.reshape(3,1));
361 GISMO_ERROR(
"Tension field data not understood: "<<TF(0,colIdx));
368template <
short_t dim,
class T,
bool linear >
369template <
bool _linear>
370typename std::enable_if<_linear, gsMatrix<T> >::type
373 gsMatrix<T> result = m_materialMat->eval3D_matrix(patch,u,z,MaterialOutput::MatrixA);
378 for (
index_t k=0; k!=u.cols(); k++)
380 for(
index_t j=0; j < z.rows(); ++j )
382 colIdx = j*u.cols()+k;
383 if (TF(0,colIdx) == 1)
387 else if (TF(0,colIdx) == -1)
391 result.col(colIdx) *= m_options.getReal(
"SlackMultiplier");
393 else if (TF(0,colIdx) == 0)
396 gsMatrix<T> N = m_materialMat->eval3D_stress(patch,u.col(k),z(j,k),MaterialOutput::VectorN);
397 gsMatrix<T> E = m_materialMat->eval3D_strain(patch,u.col(k),z(j,k));
401 result.col(colIdx) = this->_compute_C(theta,C.
reshape(3,3),N.reshape(3,1)).
reshape(9,1);
404 GISMO_ERROR(
"Tension field data not understood: "<<TF(0,colIdx));
410template <
short_t dim,
class T,
bool linear >
411template <
bool _linear>
412typename std::enable_if<!_linear, gsMatrix<T> >::type
415 gsMatrix<T> result = m_materialMat->eval3D_matrix(patch,u,z,out);
420 for (index_t k=0; k!=u.cols(); k++)
422 for( index_t j=0; j < z.rows(); ++j )
424 colIdx = j*u.cols()+k;
425 if (TF(0,colIdx) == 1)
429 else if (TF(0,colIdx) == -1)
433 result.col(colIdx) *= m_options.getReal(
"SlackMultiplier");
435 else if (TF(0,colIdx) == 0)
438 gsMatrix<T> N = m_materialMat->eval3D_stress(patch,u.col(k),z(j,k),MaterialOutput::VectorN);
439 gsMatrix<T> E = m_materialMat->eval3D_strain(patch,u.col(k),z(j,k));
442 gsMatrix<T> dC = m_materialMat->eval3D_dmatrix(patch,u.col(k),z(j,k),MaterialOutput::MatrixA);
445 result.col(colIdx) = this->_compute_C(theta,C.
reshape(3,3),N.reshape(3,1),dC.
reshape(9,3)).
reshape(9,1);
448 GISMO_ERROR(
"Tension field data not understood: "<<TF(0,colIdx));
454template <
short_t dim,
class T,
bool linear >
457 GISMO_ASSERT(Cs.cols()==Ns.cols(),
"Number of C matrices and N vectors is different");
458 GISMO_ASSERT(Cs.cols()==Es.cols(),
"Number of C matrices and E vectors is different");
464 for (
index_t k = 0; k!=Cs.cols(); k++)
473 gsVector<T> theta_interval = _theta_interval(C, N, E);
474 objective<T> obj(C,N);
479 bool converged =
false;
480 if (theta_interval(0)!=0 && theta_interval(1)!=0)
482 arg<<theta_interval(0);
483 converged = obj.findRootBrent(f,theta_interval(0),theta_interval(1),theta,1e-18);
486 converged = obj.findRootBisection(f,theta_interval(0),theta_interval(1),theta,1e-6);
489 obj.newtonRaphson(zeros,arg,
false,1e-12,100,1);
496 if (!_check_theta_full(theta,C,N,E) || (theta_interval(0)==0 && theta_interval(1)==0))
503 for (
index_t i=0; i!=theta_vec.size(); i++)
506 f_vec(i) = obj.eval(t);
509 std::vector<std::pair<T,T>> intervals; intervals.reserve(theta_vec.size());
510 for (
index_t i=0; i!=f_vec.size()-1; i++)
511 if (f_vec(i)*f_vec(i+1) < 0)
512 intervals.push_back(std::make_pair(theta_vec(i),theta_vec(i+1)));
515 std::vector<T> thetas(intervals.size());
516 for (
size_t i = 0; i!=intervals.size(); i++)
518 arg<<intervals[i].first;
519 converged = obj.findRootBrent(f,intervals[i].first,intervals[i].second,theta,1e-18);
522 converged = obj.findRootBisection(f,intervals[i].first,intervals[i].second,theta,1e-6);
525 obj.newtonRaphson(zeros,arg,
false,1e-12,100,1);
533 if ((f_vec(0)*f_vec(f_vec.size()-1) <= 0))
534 thetas.push_back(0.0);
536 std::vector<bool> full_check(thetas.size());
537 for (
size_t i = 0; i!=thetas.size(); i++)
538 full_check[i] = _check_theta_full(thetas[i],C,N,E);
540 index_t full_check_sum = std::accumulate(full_check.begin(),full_check.end(),0);
541 if (full_check_sum!=0)
543 std::vector<bool>::iterator res = std::find_if(full_check.begin(), full_check.end(), [](
bool i) { return i;});
544 index_t i = std::distance(full_check.begin(),res);
549 gsWarn<<
"Everything failed??\n";
580template <
short_t dim,
class T,
bool linear >
583 T n1 = math::cos(theta);
584 T n2 = math::sin(theta);
585 T m1 = -math::sin(theta);
586 T m2 = math::cos(theta);
591 return - ( n1_vec.transpose() * N ).value() / ( n1_vec.transpose() * C * n1_vec ).value();
594template <
short_t dim,
class T,
bool linear >
597 T n1 = math::cos(theta);
598 T n2 = math::sin(theta);
599 T m1 = -math::sin(theta);
600 T m2 = math::cos(theta);
605 check &= ((n1_vec.transpose() * N).value() < 0);
606 check &= ((n4_vec.transpose() * E).value() > 0);
610template <
short_t dim,
class T,
bool linear >
613 T n1 = math::cos(theta);
614 T n2 = math::sin(theta);
616 return ((n1_vec.transpose() * N).value() < 0);
619template <
short_t dim,
class T,
bool linear >
622 GISMO_ASSERT(C.rows()==C.cols(),
"C must be a 3x3 square matrix");
623 GISMO_ASSERT(C.rows()==3,
"C must be a 3x3 square matrix");
628 objective<T> obj(C,N);
634 T R_E = math::sqrt( math::pow((E11-E22)/2.,2) + E12*E12 );
635 if (R_E==0) {R_E = 1; gsDebugVar(
"??");};
637 T cos_E0 = (E22-E11)/(2*R_E);
638 std::complex<T> sin_Esqrt = E12*E12-E11*E22;
639 std::complex<T> sin_E1_C = -math::sqrt(sin_Esqrt)/R_E;
640 T sin_E1 = sin_E1_C.real();
641 T cos_E1 = -(E11+E22)/(2*R_E);
642 std::complex<T> sin_E2_C = math::sqrt(sin_Esqrt)/R_E;
643 T sin_E2 = sin_E2_C.real();
644 T cos_E2 = -(E11+E22)/(2*R_E);
646 T theta_0E = math::atan2(sin_E0,cos_E0);
647 T theta_1E = math::atan2(sin_E1,cos_E1);
648 T theta_2E = math::atan2(sin_E2,cos_E2);
650 T pi = 4*math::atan(1);
654 T R_N = math::sqrt( math::pow((N11-N22)/2.,2) + N12*N12 );
657 T cos_N0 = (N11-N22)/(R_N);
658 std::complex<T> sin_Nsqrt = N12*N12-N11*N22;
660 std::complex<T> sin_N1_C = math::sqrt(sin_Nsqrt)/R_N;
661 T sin_N1 = sin_N1_C.real();
662 T cos_N1 = -(N11+N22)/(2*R_N);
663 std::complex<T> sin_N2_C = -math::sqrt(sin_Nsqrt)/R_N;
664 T sin_N2 = sin_N2_C.real();
665 T cos_N2 = -(N11+N22)/(2*R_N);
667 T theta_0N = math::atan2(sin_N0,cos_N0);
668 T theta_1N = math::atan2(sin_N1,cos_N1);
669 T theta_2N = math::atan2(sin_N2,cos_N2);
671 T theta_1 = mod((theta_1N - theta_0N + theta_0E + pi),(2*pi));
672 T theta_2 = mod((theta_2N - theta_0N + theta_0E + pi),(2*pi));
673 if (math::isnan(theta_1) || math::isnan(theta_2) || R_N==1 || R_E == 1)
682 gsDebugVar(sin_Esqrt);
694 gsDebugVar(sin_Nsqrt);
705 gsDebugVar(theta_1N);
706 gsDebugVar(theta_0N);
707 gsDebugVar(theta_0E);
710 T Q_E_min = theta_1E - theta_0E;
711 T Q_E_max = theta_2E - theta_0E;
715 if (theta_1 < theta_2)
717 Q_S_min = theta_1 - pi - theta_0E;
718 Q_S_max = theta_2 - pi - theta_0E;
721 min = math::max(Q_E_min,Q_S_min);
722 max = math::min(Q_E_max,Q_S_max);
727 else if (theta_1 > theta_2)
730 Q_S_min = theta_1 - pi - theta_0E;
731 Q_S_max = pi - theta_0E;
734 min = math::max(Q_E_min,Q_S_min);
735 max = math::min(Q_E_max,Q_S_max);
738 if (obj.eval(min)*obj.eval(max)>0)
741 Q_S_min = - pi - theta_0E;
742 Q_S_max = theta_2 - pi - theta_0E;
744 min = math::max(Q_E_min,Q_S_min);
745 max = math::min(Q_E_max,Q_S_max);
778template <
short_t dim,
class T,
bool linear >
781 if (m_options.getSwitch(
"Explicit"))
783 function_ptr tmp = m_materialMat->getDeformed();
784 m_materialMat->setDeformed(m_defpatches0);
785 gsMatrix<T> TF = m_materialMat->eval3D_tensionfield(patch,u,z,MaterialOutput::TensionField);
786 m_materialMat->setDeformed(tmp);
790 return m_materialMat->eval3D_tensionfield(patch,u,z,MaterialOutput::TensionField);
793template <
short_t dim,
class T,
bool linear >
798 return _compute_TF(patch,u,zmat);
802template <
short_t dim,
class T,
bool linear >
807 T n1 = math::cos(theta);
808 T n2 = math::sin(theta);
812 T gamma = - ( n1_vec.transpose() * S ).value() / ( n1_vec.transpose() * C * n1_vec ).value();
819template <
short_t dim,
class T,
bool linear >
824 T n1 = math::cos(theta);
825 T n2 = math::sin(theta);
829 T gamma = - ( n1_vec.transpose() * S ).value() / ( n1_vec.transpose() * C * n1_vec ).value();
836template <
short_t dim,
class T,
bool linear >
839 GISMO_ASSERT(C .rows()==3,
"Number of rows of C must be 3, but is "<<C.rows());
840 GISMO_ASSERT(C .cols()==3,
"Number of cols of C must be 3, but is "<<C.cols());
841 GISMO_ASSERT(S .rows()==3,
"Number of rows of S must be 3, but is "<<S.rows());
842 GISMO_ASSERT(S .cols()==1,
"Number of cols of S must be 1, but is "<<S.cols());
846 T n1 = math::cos(theta);
847 T n2 = math::sin(theta);
848 T m1 = -math::sin(theta);
849 T m2 = math::cos(theta);
855 T gamma = - ( n1_vec.transpose() * S ).value() / ( n1_vec.transpose() * C * n1_vec ).value();
859 gsMatrix<T> dgammadE = - ( n1_vec.transpose() * C) / ( n1_vec.transpose() * C * n1_vec ).value();
860 dgammadE.transposeInPlace();
863 T tmp = ( n2_vec.transpose() * C * n1_vec ).value() / ( n1_vec.transpose() * C * n1_vec ).value();
864 T dgammadT = - 2 * gamma * tmp;
868 gsMatrix<T> dfdE = n2_vec.transpose() * C - dgammadE.transpose() * (n2_vec.transpose() * C * n1_vec).value();
869 dfdE.transposeInPlace();
875 T dfdT = (n4_vec.transpose() * S).value() + dgammadT * (n2_vec.transpose() * C * n1_vec).value() +
876 gamma * ( (n4_vec.transpose() * C * n1_vec).value() + 2*(n2_vec.transpose() * C * n2_vec).value());
882 result += C * ( n1_vec * dgammadE.transpose() + dgammadT * n1_vec * dTdE.transpose() + 2*gamma * n2_vec * dTdE.transpose() );
886template <
short_t dim,
class T,
bool linear >
889 GISMO_ASSERT(C .rows()==3,
"Number of rows of C must be 3, but is "<<C.rows());
890 GISMO_ASSERT(C .cols()==3,
"Number of cols of C must be 3, but is "<<C.cols());
891 GISMO_ASSERT(S .rows()==3,
"Number of rows of S must be 3, but is "<<S.rows());
892 GISMO_ASSERT(S .cols()==1,
"Number of cols of S must be 1, but is "<<S.cols());
893 GISMO_ASSERT(dC.cols()==3,
"Number of cols of dC must be 3, but is "<<dC.cols());
894 GISMO_ASSERT(dC.rows()==9,
"Number of rows of dC must be 1, but is "<<dC.rows());
898 T n1 = math::cos(theta);
899 T n2 = math::sin(theta);
900 T m1 = -math::sin(theta);
901 T m2 = math::cos(theta);
908 for (index_t d = 0; d!=dC.cols(); d++)
914 T gamma = - ( n1_vec.transpose() * S ).value() / ( n1_vec.transpose() * C * n1_vec ).value();
918 gsMatrix<T> dgammadE = - ( n1_vec.transpose() * C + gamma * ( n1_vec.transpose() * dCN1) ) / ( n1_vec.transpose() * C * n1_vec ).value();
922 T tmp = ( n2_vec.transpose() * C * n1_vec ).value() / ( n1_vec.transpose() * C * n1_vec ).value();
923 T dgammadT = - 2 * gamma * tmp;
927 gsMatrix<T> dfdE = n2_vec.transpose() * C + dgammadE * (n2_vec.transpose() * C * n1_vec).value() + gamma * ( n2_vec.transpose() * dCN1);
934 T dfdT = (n4_vec.transpose() * S).value() + dgammadT * (n2_vec.transpose() * C * n1_vec).value() +
935 gamma * ( (n4_vec.transpose() * C * n1_vec).value() + 2*(n2_vec.transpose() * C * n2_vec).value());
941 gsMatrix<T> dgamman1dE = ( n1_vec * dgammadE + dgammadT * n1_vec * dTdE + 2*gamma * n2_vec * dTdE );
942 result += dgamman1dE.transpose() * C;
943 result += gamma * dCN1;
948using namespace gismo;
951T mod(
const T x,
const T y)
953 return x - math::floor(x/y)*y;
965 m_support.resize(1,2);
966 m_support<<0,2*3.1415926535;
971 result.resize(1,u.cols());
976 for (index_t k = 0; k!=u.cols(); k++)
979 n1 = math::cos(theta);
980 n2 = math::sin(theta);
981 m1 = -math::sin(theta);
982 m2 = math::cos(theta);
984 n1_vec<<n1*n1, n2*n2, 2*n1*n2;
985 n2_vec<<m1*n1, m2*n2, m1*n2+m2*n1;
987 gamma = - ( n1_vec.transpose() * m_S ).value() / ( n1_vec.transpose() * m_C * n1_vec ).value();
989 T res = (n2_vec.transpose() * m_S).value() + gamma * (n2_vec.transpose() * m_C * n1_vec).value();
995 T
eval(
const T & theta)
const
1021 result.resize(1,u.cols());
1023 T theta, gamma, dgammadT;
1026 for (index_t k = 0; k!=u.cols(); k++)
1029 n1 = math::cos(theta);
1030 n2 = math::sin(theta);
1031 m1 = -math::sin(theta);
1032 m2 = math::cos(theta);
1034 n1_vec<<n1*n1, n2*n2, 2*n1*n2;
1035 n2_vec<<m1*n1, m2*n2, m1*n2+m2*n1;
1036 n3_vec<<m1*m1-n1*n1, m2*m2-n2*n2, 2*(m1*m2-n1*n2);
1037 n4_vec<<m1*m1, m2*m2, 2*m1*m2;
1039 gamma = - ( n1_vec.transpose() * m_S ).value() / ( n1_vec.transpose() * m_C * n1_vec ).value();
1040 T tmp = ( n2_vec.transpose() * m_C * n1_vec ).value() / ( n1_vec.transpose() * m_C * n1_vec ).value();
1041 dgammadT = - 2 * gamma * tmp;
1044 T res = (n3_vec.transpose() * m_S).value() + dgammadT * (n2_vec.transpose() * m_C * n1_vec).value()
1045 + gamma * (n3_vec.transpose() * m_C * n1_vec).value() + 2*gamma * (n2_vec.transpose() * m_C * n2_vec).value();
1069 bool findRootBisection(T & ,
const T & A,
const T & B, T & x,
const T & t = 1e-12,
const index_t & itmax = 1000)
1075 while (math::abs(b-a) > t && it++ < itmax)
1077 if (this->
eval(c)==0.0)
1079 else if (this->
eval(c)*this->
eval(a) < 0)
1085 if (math::abs(b-a) < t)
1105 bool findRootBrent(T & f,
const T & a,
const T & b, T & x,
const T & t = 1e-12,
const index_t & itmax = 1000)
1134 fa = this->
eval( sa );
1135 fb = this->
eval( sb );
1147 macheps = std::numeric_limits<T>::epsilon();
1149 for ( index_t it = 0; it!=itmax; it++ )
1151 if ( std::fabs ( fc ) < std::fabs ( fb ) )
1161 tol = 2.0 * macheps * std::fabs ( sb ) + t;
1162 m = 0.5 * ( c - sb );
1164 if ( std::fabs ( m ) <= tol || fb == 0.0 )
1167 f = std::fabs ( m );
1172 if ( std::fabs ( e ) < tol || std::fabs ( fa ) <= std::fabs ( fb ) )
1190 p = s * ( 2.0 * m * q * ( q - r ) - ( sb - sa ) * ( r - 1.0 ) );
1191 q = ( q - 1.0 ) * ( r - 1.0 ) * ( s - 1.0 );
1206 if ( 2.0 * p < 3.0 * m * q - std::fabs ( tol * q ) &&
1207 p < std::fabs ( 0.5 * s * q ) )
1220 if ( tol < std::fabs ( d ) )
1233 fb = this->
eval( sb );
1235 if ( ( 0.0 < fb && 0.0 < fc ) || ( fb <= 0.0 && fc <= 0.0 ) )
1245 GISMO_ERROR(
"Brent's method did not find a root");