Matrix GeneratePhiDemagTensor( int dim_x, int dim_y, int dim_z, double delta_x, double delta_y, double delta_z, bool periodic_x, bool periodic_y, bool periodic_z, int periodic_repeat, int padding, const char *cache_dir) { int exp_x = round_tensor_dimension(dim_x, periodic_x, padding); int exp_y = round_tensor_dimension(dim_y, periodic_y, padding); int exp_z = round_tensor_dimension(dim_z, periodic_z, padding); // also pad if exp_i = 1 if (exp_x == 1) exp_x = 2; if (exp_y == 1) exp_y = 2; if (exp_z == 1) exp_z = 2; LOG_INFO << "Preparing scalar potential tensor."; LOG_DEBUG << " Magn. size: " << dim_x << "x" << dim_y << "x" << dim_z; LOG_DEBUG << " Zeropadded: " << exp_x << "x" << exp_y << "x" << exp_z; LOG_DEBUG << "Periodic boundary conditions:"; LOG_DEBUG << " Dimensions : " << (periodic_x ? "x" : "") << (periodic_y ? "y" : "") << (periodic_z ? "z" : ""); LOG_DEBUG << " Repetitions: " << periodic_repeat; if (periodic_x || periodic_y || periodic_z) { throw std::runtime_error("Demag potential tensor field calculation for periodic boundary conditions not yet supported"); } Matrix S(Shape(3, exp_x, exp_y, exp_z)); S.clear(); if (std::getenv("MAGNUM_DEMAG_GARBAGE")) { LOG_INFO << "Skipping phi tensor generation ('MAGNUM_GARBAGE' environment variable is set!)"; return S; } LOG_DEBUG<< "Generating..."; Matrix::wo_accessor S_acc(S); int cnt = 0, percent = 0; for (int z=0; z<exp_z; ++z) for (int y=0; y<exp_y; ++y) { for (int x=0; x<exp_x; ++x) { // position delta (in number of cells) const int dx = x - dim_x + 1; const int dy = y - dim_y + 1; const int dz = z - dim_z + 1; /*if (dx >= dim_x+1) continue; if (dy >= dim_y+1) continue; if (dz >= dim_z+1) continue;*/ // position delta (in nanometer) const double diff_x = dx * delta_x - 0.5*delta_x; const double diff_y = dy * delta_y - 0.5*delta_y; const double diff_z = dz * delta_z - 0.5*delta_z; // store Nij at modulo position const int X = (dx + 2*exp_x) % exp_x; const int Y = (dy + 2*exp_y) % exp_y; const int Z = (dz + 2*exp_z) % exp_z; // insert components (all real) Vector3d S_i( - demag_phi_coeff::getS<long double>(0, diff_x, diff_y, diff_z, delta_x, delta_y, delta_z), - demag_phi_coeff::getS<long double>(1, diff_x, diff_y, diff_z, delta_x, delta_y, delta_z), - demag_phi_coeff::getS<long double>(2, diff_x, diff_y, diff_z, delta_x, delta_y, delta_z) ); S_acc.at(0, X, Y, Z) = S_i.x; S_acc.at(1, X, Y, Z) = S_i.y; S_acc.at(2, X, Y, Z) = S_i.z; } cnt += 1; if (100 * cnt / (exp_y*exp_z) > percent) { LOG_DEBUG << " * " << percent << "%"; percent += 10; } } LOG_INFO << "Done."; return S; }
//------------------------------------------------------------------------------ void ADRmohrCoulombFracture::evaluateStepTwo(const pair<int, int> &id_col) { // First calculating the total stress on an material point. The stress is averaged // all its bonds, and the stress state on a bond is the mean of the // stress at each material point. const int id_i = id_col.first; const int col_i = id_col.second; if((*m_data)(col_i, m_indexUnbreakable) >= 1) return; vector<pair<int, vector<double>>> & PDconnections = m_particles->pdConnections(id_i); /* if(m_dim == 2) { arma::mat S_i(2, 2); arma::mat S(2, 2); S_i(0, 0) = (*m_data)(col_i, m_indexStress[0]); S_i(1, 1) = (*m_data)(col_i, m_indexStress[1]); S_i(0, 1) = (*m_data)(col_i, m_indexStress[3]); S_i(1, 0) = S_i(0, 1); arma::vec eigval; for(auto &con:PDconnections) { const int id_j = con.first; const int j = (*m_pIds)[id_j]; if((*m_data)(j, m_indexUnbreakable) >= 1) continue; if(con.second[m_indexConnected] <= 0.5) continue; S(0, 0) = 0.5*(S_i(0, 0) + (*m_data)(j, m_indexStress[0])); S(1, 1) = 0.5*(S_i(1, 1) + (*m_data)(j, m_indexStress[1])); S(0, 1) = 0.5*(S_i(0, 1) + (*m_data)(j, m_indexStress[3])); // S(0, 0) = max(S_i(0, 0), (*m_data)(j, m_indexStress[0])); // S(1, 1) = max(S_i(1, 1), (*m_data)(j, m_indexStress[1])); // S(0, 1) = max(S_i(0, 1), (*m_data)(j, m_indexStress[3])); S(1, 0) = S(0, 1); const double first = 0.5*(S(0, 0) + S(1, 1)); const double second = sqrt(0.25*(S(0, 0) - S(1, 1))*(S(0, 0) - S(1, 1)) + S(0, 1)*S(0, 1)); const double s1 = first + second; const double s2 = first - second; const double p_1 = max(s1, s2); const double p_2 = min(s1, s2); // arma::eig_sym(eigval, S); // const double p_1 = eigval(1); // const double p_2 = eigval(0); // if(m_d*p_1 - p_2 - m_C > 0) // { // con.second[m_indexConnected] = 0; // m_maxPId = pair<int, pair<int, vector<double>> *>(id_i, &con); // } // else if(p_1 > m_T) if(p_1 > m_T) { // con.second[m_indexConnected] = 0; if(p_1 > m_maxStress) { m_maxPId = pair<int, pair<int, vector<double>> *>(id_i, &con); m_maxStress = p_1; } } } } */ arma::vec eigval(m_dim); arma::mat S_i(m_dim, m_dim); arma::mat S(m_dim, m_dim); if(m_dim == 2) { S_i(0, 0) = (*m_data)(col_i, m_indexStress[0]); S_i(1, 1) = (*m_data)(col_i, m_indexStress[1]); S_i(0, 1) = (*m_data)(col_i, m_indexStress[3]); S_i(1, 0) = S_i(0, 1); for(auto &con:PDconnections) { const int id_j = con.first; const int j = (*m_pIds)[id_j]; if((*m_data)(j, m_indexUnbreakable) >= 1) continue; if(con.second[m_indexConnected] <= 0.5) continue; S(0, 0) = 0.5*(S_i(0, 0) + (*m_data)(j, m_indexStress[0])); S(1, 1) = 0.5*(S_i(1, 1) + (*m_data)(j, m_indexStress[1])); S(0, 1) = 0.5*(S_i(0, 1) + (*m_data)(j, m_indexStress[3])); S(1, 0) = S(0, 1); #if 0 arma::eig_sym(eigval, S); const double p_1 = eigval(1); const double p_2 = eigval(0); #else const double first = 0.5*(S(0, 0) + S(1, 1)); const double second = sqrt(0.25*(S(0, 0) - S(1, 1))*(S(0, 0) - S(1, 1)) + S(0, 1)*S(0, 1)); const double s1 = first + second; const double s2 = first - second; const double p_1 = max(s1, s2); const double p_2 = min(s1, s2); #endif if(m_d*p_1 - p_2 - m_C > 0) { con.second[m_indexConnected] = 0; m_maxPId = pair<int, pair<int, vector<double>> *>(id_i, &con); } else if(p_1 > m_T) { con.second[m_indexConnected] = 0; m_maxPId = pair<int, pair<int, vector<double>> *>(id_i, &con); } } } else if(m_dim == 3) { S_i(0, 0) = (*m_data)(col_i, m_indexStress[0]); S_i(1, 1) = (*m_data)(col_i, m_indexStress[1]); S_i(2, 2) = (*m_data)(col_i, m_indexStress[2]); S_i(0, 1) = (*m_data)(col_i, m_indexStress[3]); S_i(1, 0) = S_i(0, 1); S_i(0, 2) = (*m_data)(col_i, m_indexStress[4]); S_i(2, 0) = S_i(0, 2); S_i(1, 2) = (*m_data)(col_i, m_indexStress[5]); S_i(2, 1) = S_i(1, 2); for(auto &con:PDconnections) { const int id_j = con.first; const int col_j = (*m_pIds)[id_j]; if((*m_data)(col_j, m_indexUnbreakable) >= 1) continue; if(con.second[m_indexConnected] <= 0.5) continue; S(0, 0) = 0.5*(S_i(0, 0) + (*m_data)(col_j, m_indexStress[0])); S(1, 1) = 0.5*(S_i(1, 1) + (*m_data)(col_j, m_indexStress[1])); S(2, 2) = 0.5*(S_i(2, 2) + (*m_data)(col_j, m_indexStress[2])); S(0, 1) = 0.5*(S_i(0, 1) + (*m_data)(col_j, m_indexStress[3])); S(1, 0) = S(0, 1); S(0, 2) = 0.5*(S_i(0, 2) + (*m_data)(col_j, m_indexStress[4])); S(2, 0) = S(0, 2); S(1, 2) = 0.5*(S_i(1, 2) + (*m_data)(col_j, m_indexStress[5])); S(2, 1) = S(1, 2); #if 0 arma::eig_sym(eigval, S); const double p_1 = eigval(2); const double p_2 = eigval(0); #else const double I1 = S(0, 0) + S(1, 1) + S(2, 2); const double I2 = S(0, 0)*S(1, 1) + S(1, 1)*S(2, 2) + S(3, 3)*S(0, 0) - pow(S(0, 1), 2) - pow(S(1, 2), 2) - pow(S(0, 2), 2); const double I3 = S(0, 0)*S(1, 1)*S(2, 2) - S(0, 0)*pow(S(1, 2), 2) - S(1, 1)*pow(S(0, 2), 2) - S(2, 2)*pow(S(0, 1), 2) + 2*S(0, 1)*S(1, 2)*S(0, 2); const double phi = 1./3.*acos(0.5*(2*pow(I1, 3) -9*I1*I2 + 27*I3)/pow(pow(I1, 2) - 3*I2, 1.5)); const double core = 2./3.*(sqrt(I1*I1 - 3*I2)); const double s1 = I1/3. + core*cos(phi); const double s2 = I1/3. + core*cos(phi + 2.*M_PI/3.); const double s3 = I1/3. + core*cos(phi + 4.*M_PI/3.); double p_1 = s1; double p_2 = s2; if(s2>p_1) { p_1 = s2; p_2 = s1; } if(s3>p_1) { p_1 = s3; } else if(p_2 < s3) { p_2 = s3; } #endif if(m_d*p_1 - p_2 - m_C > 0) { con.second[m_indexConnected] = 0; m_maxPId = pair<int, pair<int, vector<double>> *>(id_i, &con); } else if(p_1 > m_T) { con.second[m_indexConnected] = 0; m_maxPId = pair<int, pair<int, vector<double>> *>(id_i, &con); } } } //-------------------------------------------------------------------------- }