void testDecomposition(MaterialGenerator generator) { for (int count = 0; count < ITERATIONS; count++) { CalcNode anisotropicNode; AnisotropicMatrixImplementation matrix; string testMaterialName = "AnisotropicMatrix3D_FuzzyMultiplication_" + to_string(count); NumericalAnisotropicElasticMaterial mat = generator(testMaterialName); anisotropicNode.setMaterialId(Engine::getInstance().addMaterial(&mat)); for (int i = 0; i < 3; i++) { switch (i) { case 0: matrix.createAx(anisotropicNode); break; case 1: matrix.createAy(anisotropicNode); break; case 2: matrix.createAz(anisotropicNode); break; } // Test decomposition ASSERT_TRUE( matrix.getU1() * matrix.getL() * matrix.getU() |= matrix.getA() ); // Test eigenvalues and eigenvectors ASSERT_TRUE( matrix.getU1() * matrix.getL() |= matrix.getA() * matrix.getU1() ); } Engine::getInstance().clear(); } };
/** * Launch this dialog in order to edit the format of the specified database. * * @param subject The database whose format is to be edited */ int DBEditor::edit(Database *subject) { db = subject; columnEditor = new ColumnEditor(db, this); originalCols = db->listColumns(); renamedCols = db->listColumns(); int count = originalCols.count(); for (int i = 0; i < count; i++) { QString name = originalCols[i]; int type = db->getType(name); QString defaultVal = db->getDefault(name); if (type == CALC) { int decimals = 2; CalcNode *root = db->loadCalc(name, &decimals); calcMap.insert(name, root); decimalsMap.insert(name, decimals); if (root != 0) { defaultVal = root->equation(db); } } info.Add(ceName [name.toUtf8()] + ceType [type] + ceDefault [defaultVal.toUtf8()] + ceOldIndex [i] + ceNewIndex [i]); } updateTable(); return exec(); }
void RectangularCutCubicMeshGenerator::loadMesh(RectangularCutCubicMesh* mesh, GCMDispatcher* dispatcher, float h, int numX, int numY, int numZ, int minX, int minY, int minZ, int maxX, int maxY, int maxZ) { mesh->setNumX(numX); mesh->setNumY(numY); mesh->setNumZ(numZ); static int startNumber = 0; for( int k = 0; k <= numZ; k++ ) for( int j = 0; j <= numY; j++ ) for( int i = 0; i <= numX; i++ ) { int n = i*(numY+1)*(numZ+1) + j*(numZ+1) + k + startNumber; float x = i*h; float y = j*h; float z = k*h; CalcNode* node = new CalcNode();//(n, x, y, z); node->number = n; node->coords[0] = x; node->coords[1] = y; node->coords[2] = z; node->setPlacement(true); mesh->addNode( *node ); } mesh->setCutArea( AABB(minX*h, maxX*h, minY*h, maxY*h, minZ*h, maxZ*h) ); mesh->preProcess(); startNumber += 100000000; }
void MshTetrFileReader::readFile(string file, TetrMeshFirstOrder* mesh, GCMDispatcher* dispatcher, int rank, bool ignoreDispatcher) { assert_true(mesh); assert_true(dispatcher); int tetrsCount = 0; int fileVer; string str; int tmp_int; float tmp_float; int number_of_nodes; int number_of_elements; ifstream infile; infile.open(file.c_str(), ifstream::in); if(!infile.is_open()) THROW_INVALID_INPUT( "Can not open msh file" ); LOG_DEBUG("Reading msh file..."); infile >> str; if(strcmp(str.c_str(),"$MeshFormat") != 0) THROW_INVALID_INPUT("Wrong file format"); infile >> tmp_float >> tmp_int >> tmp_int; fileVer = (int)(tmp_float*10); infile >> str; if(strcmp(str.c_str(),"$EndMeshFormat") != 0) THROW_INVALID_INPUT("Wrong file format"); LOG_DEBUG("Header Ok"); infile >> str; if(strcmp(str.c_str(),"$Nodes") != 0) THROW_INVALID_INPUT("Wrong file format"); infile >> number_of_nodes; LOG_DEBUG("File contains " << number_of_nodes << " nodes"); vector<CalcNode*>* nodes = new vector<CalcNode*>; for(int i = 0; i < number_of_nodes; i++) { infile >> tmp_int; if( tmp_int > 0 ) { float coords[3]; infile >> coords[0] >> coords[1] >> coords[2]; if( ignoreDispatcher || dispatcher->isMine( coords, mesh->getBody()->getId() ) ) { CalcNode* node = new CalcNode(); node->number = tmp_int - 1; node->coords[0] = coords[0]; node->coords[1] = coords[1]; node->coords[2] = coords[2]; node->setPlacement(true); nodes->push_back( node ); } } else {
TEST(AnisotropicMatrix3D, AnalyticalEqNumerical) { srand(time(NULL)); for (int count = 0; count < ITERATIONS; count++) { AnisotropicMatrix3DAnalytical analyticalMatrix; AnisotropicMatrix3D numericalMatrix; CalcNode anisotropicNode; string testMaterialName = "AnisotropicMatrix3D_AnalyticalEqNumerical"; auto mat = generateRandomMaterial(testMaterialName); anisotropicNode.setMaterialId(Engine::getInstance().addMaterial(&mat)); analyticalMatrix.createAx(anisotropicNode); numericalMatrix.createAx(anisotropicNode); ASSERT_TRUE( analyticalMatrix.getA() |= numericalMatrix.getA() ); analyticalMatrix.createAy(anisotropicNode); numericalMatrix.createAy(anisotropicNode); ASSERT_TRUE( analyticalMatrix.getA() |= numericalMatrix.getA() ); analyticalMatrix.createAz(anisotropicNode); numericalMatrix.createAz(anisotropicNode); ASSERT_TRUE( analyticalMatrix.getA() |= numericalMatrix.getA() ); Engine::getInstance().clear(); } };
/** * Update any defined calculations to reflect the deletion of a column. * * @param name The name of the column that was deleted */ void DBEditor::deleteColumnRefs(const QString &name) { NameCalcMap::Iterator iter; QStringList deletions; for (iter = calcMap.begin(); iter != calcMap.end(); ++iter) { QString calcName = iter.key(); CalcNode *calcRoot = iter.value(); if (calcRoot != 0) { int index = info.Find(ceName [calcName.toUtf8()]); if (calcRoot->deleteColumn(name)) { delete calcRoot; deletions.append(calcName); ceDefault (info[index]) = ""; } else { ceDefault (info[index]) = calcRoot->equation().toUtf8(); } } } int count = deletions.count(); for (int i = 0; i < count; i++) { calcMap.remove(deletions[i]); calcMap.insert(deletions[i], 0); } }
void compareDecomposition(MaterialGenerator generator) { for (int count = 0; count < ITERATIONS; count++) { CalcNode anisotropicNode; AnisotropicMatrixImplementation1 matrix1; AnisotropicMatrixImplementation2 matrix2; string testMaterialName = "AnisotropicMatrix3D_Comparing_" + to_string(count); NumericalAnisotropicElasticMaterial mat = generator(testMaterialName); anisotropicNode.setMaterialId(Engine::getInstance().addMaterial(&mat)); for (int i = 0; i < 3; i++) { switch (i) { case 0: matrix1.createAx(anisotropicNode); matrix2.createAx(anisotropicNode); break; case 1: matrix1.createAy(anisotropicNode); matrix2.createAy(anisotropicNode); break; case 2: matrix1.createAz(anisotropicNode); matrix2.createAz(anisotropicNode); break; } int j_an, j_num, k; float eigenvA, ratio; // Through all eigenvalues for(j_an = 0; j_an < 6; j_an++) { eigenvA = matrix1.getL().get(j_an, j_an); // Finding the same eigenvalue in numericalMatrix j_num = 0; while(fabs(eigenvA - matrix2.getL().get(j_num, j_num)) > fmax(fabs(eigenvA), fabs(matrix2.getL().get(j_num, j_num)))*10.0*EQUALITY_TOLERANCE) { j_num++; //if(j_num > 5) THROW_INVALID_ARG("Remaining quality is inaccessible!"); } // Finding the first exapmle ratio of components k = -1; do { k++; ratio = matrix1.getU1().get(k, j_an)/matrix2.getU1().get(k, j_num); } while(fabs(matrix2.getU1().get(k, j_num)) < 1.0e-8); // Comparing this ratio with another ratios for(k = 0; k < 9; k++) { if(fabs(matrix1.getU1().get(k, j_an)) < 1.0e-8) ASSERT_NEAR(matrix2.getU1().get(k, j_num), 0.0, 1.0e-8); else ASSERT_NEAR(ratio, matrix1.getU1().get(k, j_an)/matrix2.getU1().get(k, j_num), fmax(fabs(ratio), fabs(matrix1.getU1().get(k, j_an)/matrix2.getU1().get(k, j_num)))*100.0*EQUALITY_TOLERANCE); } } } Engine::getInstance().clear(); } };
/** * Update any defined calculations to reflect a column renaming. * * @param oldName The old column name * @param newName The new column name */ void DBEditor::renameColumnRefs(const QString &oldName, const QString &newName) { NameCalcMap::Iterator iter; for (iter = calcMap.begin(); iter != calcMap.end(); ++iter) { QString calcName = iter.key(); CalcNode *calcRoot = iter.value(); if (calcRoot != 0) { int index = info.Find(ceName [calcName.toUtf8()]); calcRoot->renameColumn(oldName, newName); ceDefault (info[index]) = calcRoot->equation().toUtf8(); } } }
void RectangularCutCubicMesh::findBorderNodeNormal(const CalcNode& node, float* x, float* y, float* z, bool debug) { //CalcNode& node = getNode( border_node_index ); assert_true(node.isBorder() ); float normal[3]; normal[0] = normal[1] = normal[2] = 0.0; uint i = node.contactDirection; for( int cntr = 0; cntr < 3; cntr++) { if( fabs(node.coords[i] - outline.min_coords[i]) < EQUALITY_TOLERANCE ) { normal[i] = -1; break; } if( fabs(node.coords[i] - outline.max_coords[i]) < EQUALITY_TOLERANCE ) { normal[i] = 1; break; } if(cutArea.isInAABB(node)) { if( fabs(node.coords[i] - cutArea.min_coords[i]) < EQUALITY_TOLERANCE ) { normal[i] = 1; break; } if( fabs(node.coords[i] - cutArea.max_coords[i]) < EQUALITY_TOLERANCE ) { normal[i] = -1; break; } } i = (i + 1) % 3; } *x = normal[0]; *y = normal[1]; *z = normal[2]; };
int InterpolationFixedAxis::prepare_node(CalcNode& cur_node, RheologyMatrixPtr rheologyMatrix, float time_step, int stage, Mesh* mesh, float* dksi, bool* inner, vector<CalcNode>& previous_nodes, float* outer_normal, bool debug) { assert_ge(stage, 0); assert_le(stage, 2); if (cur_node.isBorder()) mesh->findBorderNodeNormal(cur_node, &outer_normal[0], &outer_normal[1], &outer_normal[2], false); LOG_TRACE("Preparing elastic matrix"); // Prepare matrixes A, Lambda, Omega, Omega^(-1) switch (stage) { case 0: rheologyMatrix->decomposeX(cur_node); break; case 1: rheologyMatrix->decomposeY(cur_node); break; case 2: rheologyMatrix->decomposeZ(cur_node); break; } LOG_TRACE("Preparing elastic matrix done"); LOG_TRACE("Elastic matrix eigen values:\n" << rheologyMatrix->getL()); for (int i = 0; i < 9; i++) dksi[i] = -rheologyMatrix->getL(i, i) * time_step; return find_nodes_on_previous_time_layer(cur_node, stage, mesh, dksi, inner, previous_nodes, outer_normal, debug); }
bool BasicCubicMesh::interpolateBorderNode_old(real x, real y, real z, real dx, real dy, real dz, CalcNode& node) { //int meshSizeX = 1 + (outline.maxX - outline.minX + meshH * 0.1) / meshH; float coords[3]; float tx = coords[0] = x + dx; float ty = coords[1] = y + dy; float tz = coords[2] = z + dz; if( outline.isInAABB(tx, ty, tz) != outline.isInAABB(x, y, z) ) { // FIXME_ASAP float minH = std::numeric_limits<float>::infinity(); int num = -1; for(int i = 1; i < getNodesNumber(); i++) { CalcNode& node = getNodeByLocalIndex(i); if(node.isBorder()) { float h = distance(coords, node.coords); if( h < minH ) { minH = h; num = i; } } } node = getNodeByLocalIndex(num); return true; } return false; };
void TetrMeshSecondOrder::fillSecondOrderNode(CalcNode& newNode, int nodeIdx1, int nodeIdx2) { CalcNode& node1 = getNode(nodeIdx1); CalcNode& node2 = getNode(nodeIdx2); for (int i = 0; i < 3; i++) newNode.coords[i] = (node1.coords[i] + node2.coords[i]) * 0.5; for (int i = 0; i < 9; i++) newNode.values[i] = (node1.values[i] + node2.values[i]) * 0.5; newNode.setRho((node1.getRho() + node2.getRho()) * 0.5); newNode.setMaterialId(node1.getMaterialId()); newNode.setPlacement(true); newNode.setOrder(2); }
void launcher::setIsotropicElasticPWave(CalcNode& node, const Vector3& direction, real amplitudeScale, bool compression) { assert_gt(amplitudeScale, 0.0); const MaterialPtr& mat = node.getMaterial(); auto la = mat->getLa(); auto mu = mat->getMu(); auto rho = mat->getRho(); auto pWaveVelocity = sqrt(la + 2 * mu / rho); auto dir = vectorNormalize(direction); auto sxx = la*amplitudeScale; auto szz = sxx; auto syy = (la + 2*mu)*amplitudeScale; if (!compression) { sxx = -sxx; syy = -syy; szz = -szz; } StressTensor tensor({ sxx, 0.0, 0.0, syy, 0.0, szz }); auto alpha = atan2(dir.y, dir.x) - M_PI/2; auto _dir = getZRotationMatrix(alpha)*dir; auto beta = atan2(_dir.z, _dir.y); auto s = getZRotationMatrix(-alpha) *getXRotationMatrix(-beta); tensor.transform(s); node.sxx = tensor.xx; node.sxy = tensor.xy; node.sxz = tensor.xz; node.syy = tensor.yy; node.syz = tensor.yz; node.szz = tensor.zz; auto velocity = (compression ? -1 : 1) * vectorNormalize(dir)*pWaveVelocity*amplitudeScale; node.vx = velocity.x; node.vy = velocity.y; node.vz = velocity.z; }
void gcm::LineFirstOrderInterpolator::interpolate(CalcNode& node, CalcNode& node0, CalcNode& node1) { LOG_TRACE("Start interpolation"); float lenTotal = distance(node0.coords, node1.coords); float factor0 = distance(node.coords, node1.coords) / lenTotal; float factor1 = distance(node.coords, node0.coords) / lenTotal; // If we see potential instability if (factor0 + factor1 > 1.0) { // If it is small - treat instability as minor and just 'smooth' it if (factor0 + factor1 < 1 + EQUALITY_TOLERANCE) // FIXME@avasyukov { float sum = factor0 + factor1; factor0 = factor0 / sum; factor1 = factor1 / sum; } // Throw exception else { LOG_ERROR("Requested node: " << node); LOG_ERROR("Node #1: " << node0); LOG_ERROR("Node #2: " << node1); LOG_ERROR("Factor: " << factor0 + factor1); THROW_BAD_MESH("Sum of factors is greater than 1.0"); } } for (int i = 0; i < 9; i++) { node.values[i] = (node0.values[i] * factor0 + node1.values[i] * factor1); } node.setRho(node0.getRho() * factor0 + node1.getRho() * factor1); node.setMaterialId(node0.getMaterialId()); LOG_TRACE("Interpolation done"); }
void testIsotropicTransition() { for (int count = 0; count < ITERATIONS; count++) { gcm_real la = ISOTROPIC_LAMBDA_LIMIT * (double) rand() / RAND_MAX; gcm_real mu = ISOTROPIC_MU_LIMIT * (double) rand() / RAND_MAX; gcm_real rho = ISOTROPIC_RHO_LIMIT * (double) rand() / RAND_MAX; gcm_real crackThreshold = numeric_limits<gcm_real>::infinity(); CalcNode isotropicNode; CalcNode anisotropicNode; IAnisotropicElasticMaterial::RheologyParameters params; params.c11 = params.c22 = params.c33 = la + 2 * mu; params.c44 = params.c55 = params.c66 = mu; params.c12 = params.c13 = params.c23 = la; params.c14 = params.c15 = params.c16 = 0.0; params.c24 = params.c25 = params.c26 = 0.0; params.c34 = params.c35 = params.c36 = 0.0; params.c45 = params.c46 = params.c56 = 0.0; IsotropicElasticMaterial m1("AnisotropicMatrix3D_IsotropicTransition_IEM", rho, crackThreshold, la, mu); MaterialImplementation m2("AnisotropicMatrix3D_IsotropicTransition_AEM", rho, crackThreshold, params); isotropicNode.setMaterialId(Engine::getInstance().addMaterial(&m1)); anisotropicNode.setMaterialId(Engine::getInstance().addMaterial(&m2)); RheologyMatrix3D& isotropicMatrix = isotropicNode.getRheologyMatrix(); RheologyMatrix3D& anisotropicMatrix = anisotropicNode.getRheologyMatrix(); for (int i = 0; i < 3; i++) { switch (i) { case 0: isotropicMatrix.createAx(isotropicNode); anisotropicMatrix.createAx(anisotropicNode); break; case 1: isotropicMatrix.createAy(isotropicNode); anisotropicMatrix.createAy(anisotropicNode); break; case 2: isotropicMatrix.createAz(isotropicNode); anisotropicMatrix.createAz(anisotropicNode); break; } for (int j = 0; j < 9; j++) for (int k = 0; k < 9; k++) ASSERT_NEAR(anisotropicMatrix.getA(j, k), isotropicMatrix.getA(j, k), EQUALITY_TOLERANCE); } Engine::getInstance().clear(); } };
void BasicCubicMesh::findBorderNodeNormal(const CalcNode& node, float* x, float* y, float* z, bool debug) { assert_true(node.isBorder() ); float normal[3]; normal[0] = normal[1] = normal[2] = 0.0; uint i = node.contactDirection; for( int cntr = 0; cntr < 3; cntr ++) { if( fabs(node.coords[i] - outline.min_coords[i]) < EQUALITY_TOLERANCE ) { normal[i] = -1; break; } if( fabs(node.coords[i] - outline.max_coords[i]) < EQUALITY_TOLERANCE ) { normal[i] = 1; break; } i = (i + 1) % 3; } *x = normal[0]; *y = normal[1]; *z = normal[2]; };
uchar RheologyModel::getSizeOfValuesInODE() const { CalcNode tmpNode = newNode(nodeType); return tmpNode.getSizeOfValuesInODE(); }
void SlidingContactCalculator::doCalc(CalcNode& cur_node, CalcNode& new_node, CalcNode& virt_node, RheologyMatrixPtr matrix, vector<CalcNode>& previousNodes, bool inner[], RheologyMatrixPtr virt_matrix, vector<CalcNode>& virtPreviousNodes, bool virt_inner[], float outer_normal[], float scale) { assert_eq(previousNodes.size(), 9); assert_eq(virtPreviousNodes.size(), 9); if (isFreeBorder(cur_node, virt_node, outer_normal)) { fbc->doCalc(cur_node, new_node, matrix, previousNodes, inner, outer_normal, scale); return; } // Here we will store (omega = Matrix_OMEGA * u) float omega[9]; float virt_omega[9]; int posInEq18 = 0; int curNN = 0; // For all omegas of real node for(int i = 0; i < 9; i++) { LOG_TRACE("PrNode: " << previousNodes[i]); // If omega is 'inner' if(inner[i]) { LOG_TRACE("INNER"); // omega on new time layer is equal to omega on previous time layer along characteristic omega[i] = 0; for( int j = 0; j < 9; j++ ) { omega[i] += matrix->getU(i,j) * previousNodes[i].values[j]; } // then we must set the corresponding values of the 18x18 matrix gsl_vector_set( om_gsl, 6 * curNN + posInEq18, omega[i] ); for( int j = 0; j < 9; j++ ) { gsl_matrix_set( U_gsl, 6 * curNN + posInEq18, j, matrix->getU( i, j ) ); } for( int j = 9; j < 18; j++ ) { gsl_matrix_set( U_gsl, 6 * curNN + posInEq18, j, 0 ); } posInEq18++; } } posInEq18 = 0; curNN = 1; // For all omegas of virtual node for(int i = 0; i < 9; i++) { LOG_TRACE("VirtPrNode: " << virtPreviousNodes[i]); // If omega is 'inner' if(virt_inner[i]) { LOG_TRACE("INNER"); // omega on new time layer is equal to omega on previous time layer along characteristic virt_omega[i] = 0; for( int j = 0; j < 9; j++ ) { virt_omega[i] += virt_matrix->getU(i,j) * virtPreviousNodes[i].values[j]; } // then we must set the corresponding values of the 18x18 matrix gsl_vector_set( om_gsl, 6 * curNN + posInEq18, virt_omega[i] ); for( int j = 0; j < 9; j++ ) { gsl_matrix_set( U_gsl, 6 * curNN + posInEq18, j, 0 ); } for( int j = 9; j < 18; j++ ) { gsl_matrix_set( U_gsl, 6 * curNN + posInEq18, j, virt_matrix->getU( i, j - 9 ) ); } posInEq18++; } } // Clear the rest 6 rows of the matrix for( int strN = 12; strN < 18; strN++ ) { for( int colN = 0; colN < 18; colN++ ) { gsl_matrix_set( U_gsl, strN, colN, 0 ); } } for( int strN = 12; strN < 18; strN++ ) { gsl_vector_set( om_gsl, strN, 0 ); } float local_n[3][3]; local_n[0][0] = outer_normal[0]; local_n[0][1] = outer_normal[1]; local_n[0][2] = outer_normal[2]; createLocalBasis(local_n[0], local_n[1], local_n[2]); // Normal velocities are equal gsl_matrix_set( U_gsl, 12, 0, local_n[0][0]); gsl_matrix_set( U_gsl, 12, 1, local_n[0][1]); gsl_matrix_set( U_gsl, 12, 2, local_n[0][2]); gsl_matrix_set( U_gsl, 12, 9, - local_n[0][0]); gsl_matrix_set( U_gsl, 12, 10, - local_n[0][1]); gsl_matrix_set( U_gsl, 12, 11, - local_n[0][2]); // We use outer normal to find total stress vector (sigma * n) - sum of normal and shear - and tell it is equal // TODO - is it ok? // TODO - never-ending questions - is everything ok with (x-y-z) and (ksi-eta-dzeta) basises? // TODO FIXME - it works now because exactly the first axis is the only one where contact is possible // and it coincides with outer normal // Normal stresses are equal gsl_matrix_set(U_gsl, 13, 3, local_n[0][0] * local_n[0][0]); gsl_matrix_set(U_gsl, 13, 4, 2 * local_n[0][1] * local_n[0][0]); gsl_matrix_set(U_gsl, 13, 5, 2 * local_n[0][2] * local_n[0][0]); gsl_matrix_set(U_gsl, 13, 6, local_n[0][1] * local_n[0][1]); gsl_matrix_set(U_gsl, 13, 7, 2 * local_n[0][2] * local_n[0][1]); gsl_matrix_set(U_gsl, 13, 8, local_n[0][2] * local_n[0][2]); gsl_matrix_set(U_gsl, 13, 12, - local_n[0][0] * local_n[0][0]); gsl_matrix_set(U_gsl, 13, 13, - 2 * local_n[0][1] * local_n[0][0]); gsl_matrix_set(U_gsl, 13, 14, - 2 * local_n[0][2] * local_n[0][0]); gsl_matrix_set(U_gsl, 13, 15, - local_n[0][1] * local_n[0][1]); gsl_matrix_set(U_gsl, 13, 16, - 2 * local_n[0][2] * local_n[0][1]); gsl_matrix_set(U_gsl, 13, 17, - local_n[0][2] * local_n[0][2]); // Tangential stresses are zero gsl_matrix_set(U_gsl, 14, 3, - (local_n[0][0] * local_n[1][0]) ); gsl_matrix_set(U_gsl, 14, 4, - (local_n[0][1] * local_n[1][0] + local_n[0][0] * local_n[1][1]) ); gsl_matrix_set(U_gsl, 14, 5, - (local_n[0][2] * local_n[1][0] + local_n[0][0] * local_n[1][2]) ); gsl_matrix_set(U_gsl, 14, 6, - (local_n[0][1] * local_n[1][1]) ); gsl_matrix_set(U_gsl, 14, 7, - (local_n[0][2] * local_n[1][1] + local_n[0][1] * local_n[1][2]) ); gsl_matrix_set(U_gsl, 14, 8, - (local_n[0][2] * local_n[1][2]) ); gsl_matrix_set(U_gsl, 15, 3, - (local_n[0][0] * local_n[2][0]) ); gsl_matrix_set(U_gsl, 15, 4, - (local_n[0][1] * local_n[2][0] + local_n[0][0] * local_n[2][1]) ); gsl_matrix_set(U_gsl, 15, 5, - (local_n[0][2] * local_n[2][0] + local_n[0][0] * local_n[2][2]) ); gsl_matrix_set(U_gsl, 15, 6, - (local_n[0][1] * local_n[2][1]) ); gsl_matrix_set(U_gsl, 15, 7, - (local_n[0][2] * local_n[2][1] + local_n[0][1] * local_n[2][2]) ); gsl_matrix_set(U_gsl, 15, 8, - (local_n[0][2] * local_n[2][2]) ); gsl_matrix_set(U_gsl, 16, 12, - (local_n[0][0] * local_n[1][0]) ); gsl_matrix_set(U_gsl, 16, 13, - (local_n[0][1] * local_n[1][0] + local_n[0][0] * local_n[1][1]) ); gsl_matrix_set(U_gsl, 16, 14, - (local_n[0][2] * local_n[1][0] + local_n[0][0] * local_n[1][2]) ); gsl_matrix_set(U_gsl, 16, 15, - (local_n[0][1] * local_n[1][1]) ); gsl_matrix_set(U_gsl, 16, 16, - (local_n[0][2] * local_n[1][1] + local_n[0][1] * local_n[1][2]) ); gsl_matrix_set(U_gsl, 16, 17, - (local_n[0][2] * local_n[1][2]) ); gsl_matrix_set(U_gsl, 17, 12, - (local_n[0][0] * local_n[2][0]) ); gsl_matrix_set(U_gsl, 17, 13, - (local_n[0][1] * local_n[2][0] + local_n[0][0] * local_n[2][1]) ); gsl_matrix_set(U_gsl, 17, 14, - (local_n[0][2] * local_n[2][0] + local_n[0][0] * local_n[2][2]) ); gsl_matrix_set(U_gsl, 17, 15, - (local_n[0][1] * local_n[2][1]) ); gsl_matrix_set(U_gsl, 17, 16, - (local_n[0][2] * local_n[2][1] + local_n[0][1] * local_n[2][2]) ); gsl_matrix_set(U_gsl, 17, 17, - (local_n[0][2] * local_n[2][2]) ); // Tmp value for GSL solver int s; gsl_linalg_LU_decomp (U_gsl, p_gsl, &s); try { gsl_linalg_LU_solve (U_gsl, p_gsl, om_gsl, x_gsl); } catch (Exception& e) { cur_node.setContactCalculationError(); for(int i = 0; i < 18; i++) { std::stringstream matStr; for(int j = 0; j < 18; j++) matStr << gsl_matrix_get(U_gsl, i, j) << " "; LOG_TRACE(matStr.str()); } LOG_ERROR("Bad node: " << cur_node); LOG_ERROR("Normal: " << outer_normal[0] << " " << outer_normal[1] << " " << outer_normal[2]); LOG_ERROR("Delta: " << virt_node.coords[0] - cur_node.coords[0] << " " << virt_node.coords[1] - cur_node.coords[1] << " " << virt_node.coords[2] - cur_node.coords[2]); throw; } // Just get first 9 values (real node) and dump the rest 9 (virt node) for(int j = 0; j < 9; j++) new_node.values[j] = gsl_vector_get(x_gsl, j); CalcNode new_virt_node; for(int j = 0; j < 9; j++) new_virt_node.values[j] = gsl_vector_get(x_gsl, j + 9); if (isFreeBorder(new_node, new_virt_node, outer_normal)) { fbc->doCalc(cur_node, new_node, matrix, previousNodes, inner, outer_normal, scale); return; } };
void Vtu2TetrFileReader::readFile(string file, TetrMeshSecondOrder* mesh, GCMDispatcher* dispatcher, int rank, bool ignoreDispatcher) { vtkXMLUnstructuredGridReader *xgr = vtkXMLUnstructuredGridReader::New(); vtkUnstructuredGrid *g = vtkUnstructuredGrid::New(); xgr->SetFileName(const_cast<char*>(file.c_str())); xgr->Update(); g = xgr->GetOutput(); if( ignoreDispatcher ) { LOG_DEBUG("Reading file ignoring dispatcher"); } else { LOG_DEBUG("Dispatcher zones:"); dispatcher->printZones(); } LOG_DEBUG("Number of points: " << g->GetNumberOfPoints()); LOG_DEBUG("Number of cells: " << g->GetNumberOfCells()); double v[3]; vtkDoubleArray *vel = (vtkDoubleArray*) g->GetPointData()->GetArray("velocity"); vel->SetNumberOfComponents(3); vtkDoubleArray *sxx = (vtkDoubleArray*) g->GetPointData()->GetArray("sxx"); vtkDoubleArray *sxy = (vtkDoubleArray*) g->GetPointData()->GetArray("sxy"); vtkDoubleArray *sxz = (vtkDoubleArray*) g->GetPointData()->GetArray("sxz"); vtkDoubleArray *syy = (vtkDoubleArray*) g->GetPointData()->GetArray("syy"); vtkDoubleArray *syz = (vtkDoubleArray*) g->GetPointData()->GetArray("syz"); vtkDoubleArray *szz = (vtkDoubleArray*) g->GetPointData()->GetArray("szz"); vtkIntArray *matId = (vtkIntArray*) g->GetPointData()->GetArray("materialID"); vtkDoubleArray *rho = (vtkDoubleArray*) g->GetPointData()->GetArray("rho"); vtkIntArray *nodeNumber = (vtkIntArray*) g->GetPointData ()->GetArray("nodeNumber"); vtkIntArray *publicFlags = (vtkIntArray*) g->GetPointData ()->GetArray("publicFlags"); vtkIntArray *privateFlags = (vtkIntArray*) g->GetPointData ()->GetArray("privateFlags"); vtkIntArray *nodeBorderConditionId = (vtkIntArray*) g->GetPointData ()->GetArray("borderConditionId"); vector<CalcNode*>* nodes = new vector<CalcNode*>; for( int i = 0; i < g->GetNumberOfPoints(); i++ ) { double* dp = g->GetPoint(i); if( ignoreDispatcher || dispatcher->isMine( dp, mesh->getBody()->getId() ) ) { CalcNode* node = new CalcNode(); node->number = nodeNumber->GetValue(i); node->coords[0] = dp[0]; node->coords[1] = dp[1]; node->coords[2] = dp[2]; vel->GetTupleValue(i, v); node->vx = v[0]; node->vy = v[1]; node->vz = v[2]; node->sxx = sxx->GetValue(i); node->sxy = sxy->GetValue(i); node->sxz = sxz->GetValue(i); node->syy = syy->GetValue(i); node->syz = syz->GetValue(i); node->szz = szz->GetValue(i); node->setMaterialId( matId->GetValue(i) ); node->setRho( rho->GetValue(i) ); node->setPublicFlags( publicFlags->GetValue(i) ); node->setPrivateFlags( privateFlags->GetValue(i) ); node->setBorderConditionId( nodeBorderConditionId->GetValue(i) ); if( !ignoreDispatcher ) node->setPlacement(true); nodes->push_back( node ); } } LOG_DEBUG("Finished reading nodes"); LOG_DEBUG("There are " << nodes->size() << " local nodes"); mesh->createNodes( nodes->size() ); for(unsigned int i = 0; i < nodes->size(); i++) { mesh->addNode( *nodes->at(i) ); } for(unsigned int i = 0; i < nodes->size(); i++) { delete( nodes->at(i)); } nodes->clear(); delete nodes; vtkIntArray* tetr2ndOrderNodes = (vtkIntArray*) g->GetCellData ()->GetArray ("tetr2ndOrderNodes"); assert_eq(tetr2ndOrderNodes->GetNumberOfComponents (), 6); vtkIntArray* tetr1stOrderNodes = (vtkIntArray*) g->GetCellData ()->GetArray ("tetr1stOrderNodes"); vtkIntArray* tetrNumber = (vtkIntArray*) g->GetCellData ()->GetArray ("tetrNumber"); assert_eq(tetr1stOrderNodes->GetNumberOfComponents (), 4); vector<TetrSecondOrder*>* tetrs = new vector<TetrSecondOrder*>; TetrSecondOrder new_tetr; for( int i = 0; i < g->GetNumberOfCells(); i++ ) { new_tetr.number = tetrNumber->GetValue(i); tetr1stOrderNodes->GetTupleValue (i, new_tetr.verts); tetr2ndOrderNodes->GetTupleValue (i, new_tetr.addVerts); /*vtkTetra *vt = (vtkTetra*) g->GetCell(i); int vert[4]; vert[0] = vt->GetPointId(0); vert[1] = vt->GetPointId(1); vert[2] = vt->GetPointId(2); vert[3] = vt->GetPointId(3);*/ if( mesh->hasNode(new_tetr.verts[0]) || mesh->hasNode(new_tetr.verts[1]) || mesh->hasNode(new_tetr.verts[2]) || mesh->hasNode(new_tetr.verts[3]) ) tetrs->push_back( new TetrSecondOrder( new_tetr.number, new_tetr.verts, new_tetr.addVerts ) ); } LOG_DEBUG("File contains " << g->GetNumberOfCells() << " tetrs"); LOG_DEBUG("There are " << tetrs->size() << " local tetrs"); map<int,int> remoteNodes; mesh->createTetrs( tetrs->size() ); for(unsigned int i = 0; i < tetrs->size(); i++) { TetrSecondOrder* tetr = tetrs->at(i); mesh->addTetr2( *tetr ); for(int j = 0; j < 4; j++) if( ! mesh->hasNode( tetr->verts[j] ) ) remoteNodes[tetr->verts[j]] = i; for(int j = 0; j < 6; j++) if( ! mesh->hasNode( tetr->addVerts[j] ) ) remoteNodes[tetr->addVerts[j]] = i; } for(unsigned int i = 0; i < tetrs->size(); i++) { delete( tetrs->at(i) ); } tetrs->clear(); delete tetrs; LOG_DEBUG("Finished reading elements"); LOG_DEBUG("Reading required remote nodes"); LOG_DEBUG("We expect " << remoteNodes.size() << " nodes" ); int remoteNodesCount = 0; CalcNode tmpNode; for( int i = 0; i < g->GetNumberOfPoints(); i++ ) { if( remoteNodes.find( nodeNumber->GetValue(i) ) != remoteNodes.end() ) { double* dp = g->GetPoint(i); tmpNode.number = nodeNumber->GetValue(i); tmpNode.coords[0] = dp[0]; tmpNode.coords[1] = dp[1]; tmpNode.coords[2] = dp[2]; vel->GetTupleValue(i, v); tmpNode.vx = v[0]; tmpNode.vy = v[1]; tmpNode.vz = v[2]; tmpNode.sxx = sxx->GetValue(i); tmpNode.sxy = sxy->GetValue(i); tmpNode.sxz = sxz->GetValue(i); tmpNode.syy = syy->GetValue(i); tmpNode.syz = syz->GetValue(i); tmpNode.szz = szz->GetValue(i); tmpNode.setMaterialId( matId->GetValue(i) ); tmpNode.setRho( rho->GetValue(i) ); tmpNode.setPublicFlags( publicFlags->GetValue(i) ); tmpNode.setPrivateFlags( privateFlags->GetValue(i) ); tmpNode.setBorderConditionId( nodeBorderConditionId->GetValue(i) ); tmpNode.setPlacement(false); mesh->addNode(tmpNode); remoteNodesCount++; } } LOG_DEBUG("Read " << remoteNodesCount << " remote nodes"); LOG_DEBUG("Finished reading nodes"); LOG_DEBUG("File successfylly read."); LOG_DEBUG("There are " << mesh->getNodesNumber() << " nodes is the mesh"); LOG_DEBUG("Checking tetrs and nodes"); for( int i = 0; i < mesh->getTetrsNumber(); i++ ) { TetrSecondOrder& tetr = mesh->getTetr2ByLocalIndex(i); for (int j = 0; j < 4; j++) if ( ! mesh->hasNode(tetr.verts[j]) ) { LOG_ERROR("Can not find node " << tetr.verts[j] << " required by local tetr " << i); THROW_BAD_MESH("Missed node"); } for (int j = 0; j < 6; j++) if ( ! mesh->hasNode(tetr.addVerts[j]) ) { LOG_ERROR("Can not find node " << tetr.addVerts[j] << " required by local tetr " << i); THROW_BAD_MESH("Missed node"); } } //xgr->Delete(); //g->Delete(); }
int InterpolationFixedAxis::find_nodes_on_previous_time_layer(CalcNode& cur_node, int stage, Mesh* mesh, float dksi[], bool inner[], vector<CalcNode>& previous_nodes, float outer_normal[], bool debug) { LOG_TRACE("Start looking for nodes on previous time layer"); // For all omegas for (int i = 0; i < 9; i++) { LOG_TRACE("Looking for characteristic " << i); // Check prevoius omegas ... bool already_found = false; for (int j = 0; j < i; j++) { // ... And try to find if we have already worked with the required point // on previous time layer (or at least with the point that is close enough) if (fabs(dksi[i] - dksi[j]) <= EQUALITY_TOLERANCE * 0.5 * fabs(dksi[i] + dksi[j])) { LOG_TRACE("Found old value " << dksi[i] << " - done"); // If we have already worked with this point - just remember the number already_found = true; previous_nodes[i] = previous_nodes[j]; inner[i] = inner[j]; } } // If we do not have necessary point in place - ... if (!already_found) { LOG_TRACE("New value " << dksi[i] << " - preparing vectors"); // ... Put new number ... previous_nodes[i] = cur_node; // ... Find vectors ... float dx[3]; dx[0] = dx[1] = dx[2] = 0.0; dx[stage] += dksi[i]; // For dksi = 0 we can skip check and just copy everything if (dksi[i] == 0) { // no interpolation required - everything is already in place inner[i] = true; LOG_TRACE("dksi is zero - done"); } else if (cur_node.isInner()) { LOG_TRACE("Checking inner node"); // ... Find owner tetrahedron ... bool isInnerPoint; mesh->interpolateNode(cur_node, dx[0], dx[1], dx[2], debug, previous_nodes[i], isInnerPoint); if (!isInnerPoint) { LOG_TRACE("Inner node: we need new method here!"); LOG_TRACE("Node:\n" << cur_node); LOG_TRACE("Move: " << dx[0] << " " << dx[1] << " " << dx[2]); // TODO: return it back later // Re-run search with debug on //mesh->interpolateNode(origin, dx[0], dx[1], dx[2], true, // previous_nodes[i], isInnerPoint); } inner[i] = true; LOG_TRACE("Checking inner node done"); } else if (cur_node.isBorder()) { LOG_TRACE("Checking border node"); // ... Find owner tetrahedron ... bool isInnerPoint; bool interpolated = mesh->interpolateNode(cur_node, dx[0], dx[1], dx[2], debug, previous_nodes[i], isInnerPoint); // If we found inner point, it means // this direction is inner and everything works as for usual inner point if (isInnerPoint) { inner[i] = true; // If we did not find inner point - two cases are possible } else { inner[i] = false; // We found border cross somehow // It can happen if we work with really thin structures and big time step // We can work as usual in this case if (interpolated) { LOG_TRACE("Border node: we need new method here!"); inner[i] = true; // Or we did not find any point at all - it means this characteristic is outer } else { inner[i] = false; } } LOG_TRACE("Checking border node done"); } else { THROW_BAD_MESH("Unsupported case for characteristic location"); } } LOG_TRACE("Looking for characteristic " << i << " done"); } int outer_count = 0; for (int i = 0; i < 9; i++) if (!inner[i]) outer_count++; // assert_true(outer_count == 0 || outer_count == 3); LOG_TRACE("Looking for nodes on previous time layer done. Outer count = " << outer_count); return outer_count; }
void InterpolationFixedAxis::__doNextPartStep(CalcNode& cur_node, CalcNode& new_node, float time_step, int stage, Mesh* mesh) { assert_ge(stage, 0); assert_le(stage, 2); auto& engine = Engine::getInstance(); LOG_TRACE("Start node prepare for node " << cur_node.number); LOG_TRACE("Node: " << cur_node); // Variables used in calculations internally // Delta x on previous time layer for all the omegas // omega_new_time_layer(ksi) = omega_old_time_layer(ksi+dksi) float dksi[9]; // If the corresponding point on previous time layer is inner or not bool inner[9]; // We will store interpolated nodes on previous time layer here // We know that we need five nodes for each direction (corresponding to Lambdas -C1, -C2, 0, C2, C1) // TODO - We can deal with (lambda == 0) separately vector<CalcNode> previous_nodes; previous_nodes.resize(9); // Outer normal at current point float outer_normal[3]; // Number of outer characteristics int outer_count = prepare_node(cur_node, cur_node.getRheologyMatrix(), time_step, stage, mesh, dksi, inner, previous_nodes, outer_normal); LOG_TRACE("Done node prepare"); // If all the omegas are 'inner' // omega = Matrix_OMEGA * u // new_u = Matrix_OMEGA^(-1) * omega // TODO - to think - if all omegas are 'inner' can we skip matrix calculations and just use new_u = interpolated_u ? if (cur_node.isInner()) { LOG_TRACE("Start inner node calc"); if (outer_count == 0) // FIXME - hardcoded name engine.getVolumeCalculator("SimpleVolumeCalculator")->doCalc( new_node, cur_node.getRheologyMatrix(), previous_nodes); else THROW_BAD_MESH("Outer characteristic for internal node detected"); LOG_TRACE("Done inner node calc"); } if (cur_node.isBorder()) { LOG_TRACE("Start border node calc"); // FIXME_ASAP - do smth with this! // It is not stable now. See ugly hack below. // Think about: (a) cube, (b) rotated cube, (c) sphere. float val = (outer_normal[stage] >= 0 ? 1.0 : -1.0); outer_normal[0] = outer_normal[1] = outer_normal[2] = 0; outer_normal[stage] = val; // If there is no 'outer' omega - it is ok, border node can be inner for some directions if (outer_count == 0) { // FIXME - hardcoded name engine.getVolumeCalculator("SimpleVolumeCalculator")->doCalc( new_node, cur_node.getRheologyMatrix(), previous_nodes); } // If there are 3 'outer' omegas - we should use border or contact algorithm else if (outer_count == 3) { // Border if (!cur_node.isInContact() || cur_node.contactDirection != stage) { // FIXME int borderCondId = cur_node.getBorderConditionId(); LOG_TRACE("Using calculator: " << engine.getBorderCondition(borderCondId)->calc->getType()); engine.getBorderCondition(borderCondId)->doCalc(Engine::getInstance().getCurrentTime(), cur_node, new_node, cur_node.getRheologyMatrix(), previous_nodes, inner, outer_normal); } // Contact else { CalcNode& virt_node = engine.getVirtNode(cur_node.contactNodeNum); // FIXME - WA Mesh* virtMesh = (Mesh*) engine.getBody(virt_node.contactNodeNum)->getMeshes(); LOG_TRACE("We are going to calc contact. Target virt node: " << cur_node.contactNodeNum << " Target mesh: " << virt_node.contactNodeNum); LOG_TRACE("Mesh: " << mesh->getId() << " Virt mesh: " << virtMesh->getId() << "\nReal node: " << cur_node << "\nVirt node: " << virt_node); // Mark virt node as having contact state // TODO FIXME - most probably CollisionDetector should do it // But we should check it anycase virt_node.setInContact(true); //virt_node.contactNodeNum = cur_node.contactNodeNum; // Variables used in calculations internally // Delta x on previous time layer for all the omegas // omega_new_time_layer(ksi) = omega_old_time_layer(ksi+dksi) float virt_dksi[9]; // If the corresponding point on previous time layer is inner or not bool virt_inner[9]; // We will store interpolated nodes on previous time layer here // We know that we need five nodes for each direction (corresponding to Lambdas -C1, -C2, 0, C2, C1) // TODO - We can deal with (lambda == 0) separately vector<CalcNode> virt_previous_nodes; virt_previous_nodes.resize(9); // Outer normal at current point float virt_outer_normal[3]; // Number of outer characteristics int virt_outer_count = prepare_node(virt_node, virt_node.getRheologyMatrix(), time_step, stage, virtMesh, virt_dksi, virt_inner, virt_previous_nodes, virt_outer_normal); // FIXME_ASAP: WA switch (stage) { case 0: virt_node.getRheologyMatrix()->decomposeX(virt_node); break; case 1: virt_node.getRheologyMatrix()->decomposeY(virt_node); break; case 2: virt_node.getRheologyMatrix()->decomposeZ(virt_node); break; } // WA for sharp edges if(virt_outer_count == 0) { RheologyMatrixPtr curM = cur_node.getRheologyMatrix(); RheologyMatrixPtr virtM = virt_node.getRheologyMatrix(); int sign = 0; for(int i = 0; i < 9; i++) { if(!inner[i]) sign = (curM->getL(i,i) > 0 ? 1 : -1); } for(int i = 0; i < 9; i++) { if( virtM->getL(i,i) * sign < 0 ) virt_inner[i] = false; } virt_outer_count = 3; } // TODO - merge this condition with the next ones if (virt_outer_count != 3) { LOG_DEBUG("EXTENDED DEBUG INFO BEGINS"); prepare_node(virt_node, virt_node.getRheologyMatrix(), time_step, stage, virtMesh, virt_dksi, virt_inner, virt_previous_nodes, virt_outer_normal, true); LOG_DEBUG("EXTENDED DEBUG INFO ENDS"); LOG_DEBUG("Calc contact failed. Mesh: " << mesh->getId() << " Virt mesh: " << virtMesh->getId() << "\nReal node: " << cur_node << "\nVirt node: " << virt_node); LOG_DEBUG("There are " << virt_outer_count << " 'outer' characteristics for virt node."); for (int z = 0; z < 9; z++) { LOG_DEBUG("Dksi[" << z << "]: " << virt_dksi[z]); LOG_DEBUG("Inner[" << z << "]: " << virt_inner[z]); LOG_DEBUG("PrNodes[" << z << "]: " << virt_previous_nodes[z]); } THROW_BAD_METHOD("Illegal number of outer characteristics"); } // // Check that 'paired node' is in the direction of 'outer' characteristics // // If it is not the case - we have strange situation when // // we replace 'outer' points data with data of 'paired node' from different axis direction. // // // For all characteristics of real node and virt node // /*for(int i = 0; i < 9; i++) // { // float v_x_outer[3]; // float v_x_virt[3]; // // Real node - if characteristic is 'outer'*/ // /* if(!inner[i]) // { // // Find directions to corresponding 'outer' point and to virt 'paired node' // for(int j = 0; j < 3; j++) { // v_x_outer[j] = previous_nodes[ppoint_num[i]].coords[j] - cur_node.coords[j]; // v_x_virt[j] = virt_node.coords[j] - cur_node.coords[j]; // } // // If directions are different - smth bad happens // if( (v_x_outer[0] * v_x_virt[0] // + v_x_outer[1] * v_x_virt[1] + v_x_outer[2] * v_x_virt[2]) < 0 ) // { // *logger << "MESH " << mesh->zone_num << "REAL NODE " << cur_node.local_num << ": " // << "x: " << cur_node.coords[0] // << " y: " << cur_node.coords[1] // << " z: " < cur_node.coords[2]; // log_node_diagnostics(cur_node, stage, outer_normal, mesh, basis_num, rheologyMatrix, time_step, previous_nodes, ppoint_num, inner, dksi); // *logger << "'Outer' direction: " << v_x_outer[0] << " " // << v_x_outer[1] << " " < v_x_outer[2]; // *logger << "'Virt' direction: " << v_x_virt[0] << " " // << v_x_virt[1] << " " < v_x_virt[2]; // throw GCMException( GCMException::METHOD_EXCEPTION, "Bad contact from real node point of view: 'outer' and 'virt' directions are different"); // } // }*/ // // We switch it off because it conflicts sometimes with 'safe_direction' // /* // Virt node - if characteristic is 'outer' // if(!virt_inner[i]) // { // // Find directions to corresponding 'outer' point and to real 'paired node' // for(int j = 0; j < 3; j++) { // v_x_outer[j] = virt_previous_nodes[virt_ppoint_num[i]].coords[j] - virt_node.coords[j]; // v_x_virt[j] = cur_node.coords[j] - virt_node.coords[j]; // } // // If directions are different - smth bad happens // if( (v_x_outer[0] * v_x_virt[0] // + v_x_outer[1] * v_x_virt[1] + v_x_outer[2] * v_x_virt[2]) < 0 ) // { // *logger << "MESH " << mesh->zone_num << "REAL NODE " << cur_node.local_num << ": " // << "x: " << cur_node.coords[0] // << " y: " << cur_node.coords[1] // << " z: " < cur_node.coords[2]; // log_node_diagnostics(virt_node, stage, virt_outer_normal, virt_node.mesh, basis_num, virt_rheologyMatrix, time_step, virt_previous_nodes, virt_ppoint_num, virt_inner, virt_dksi); // *logger << "'Outer' direction: " << v_x_outer[0] << " " // << v_x_outer[1] << " "< v_x_outer[2]; // *logger << "'Virt' direction: " << v_x_virt[0] << " " // << v_x_virt[1] << " " < v_x_virt[2]; // throw GCMException( GCMException::METHOD_EXCEPTION, "Bad contact from virt node point of view: 'outer' and 'virt' directions are different"); // } // }*/ //// } // LOG_TRACE("Using calculator: " << engine.getContactCondition(cur_node.getContactConditionId())->calc->getType()); LOG_TRACE("Outer normal: " << outer_normal[0] << " " << outer_normal[1] << " " << outer_normal[2]); engine.getContactCondition(cur_node.getContactConditionId())->doCalc(Engine::getInstance().getCurrentTime(), cur_node, new_node, virt_node, cur_node.getRheologyMatrix(), previous_nodes, inner, virt_node.getRheologyMatrix(), virt_previous_nodes, virt_inner, outer_normal); } // It means smth went wrong. Just interpolate the values and report bad node. } else { //LOG_WARN("Outer count: " << outer_count); //LOG_WARN("Node: " << cur_node); //for (int z = 0; z < 9; z++) { // LOG_WARN("Dksi[" << z << "]: " << dksi[z]); // LOG_WARN("Inner[" << z << "]: " << inner[z]); // LOG_WARN("PrNodes[" << z << "]: " << previous_nodes[z]); //} //THROW_BAD_METHOD("Illegal number of outer characteristics"); // FIXME - implement border and contact completely LOG_TRACE("Using calculator: " << engine.getBorderCondition(0)->calc->getType()); engine.getBorderCondition(0)->doCalc(Engine::getInstance().getCurrentTime(), cur_node, new_node, cur_node.getRheologyMatrix(), previous_nodes, inner, outer_normal); cur_node.setNeighError(stage); } LOG_TRACE("Done border node calc"); } }
void TetrFirstOrderInterpolator::interpolate(CalcNode& node, CalcNode& node0, CalcNode& node1, CalcNode& node2, CalcNode& node3) { LOG_TRACE("Start interpolation"); float Vol = tetrVolume( (node1.coords[0])-(node0.coords[0]), (node1.coords[1])-(node0.coords[1]), (node1.coords[2])-(node0.coords[2]), (node2.coords[0])-(node0.coords[0]), (node2.coords[1])-(node0.coords[1]), (node2.coords[2])-(node0.coords[2]), (node3.coords[0])-(node0.coords[0]), (node3.coords[1])-(node0.coords[1]), (node3.coords[2])-(node0.coords[2]) ); float factor[4]; factor[0] = fabs(tetrVolume( (node1.coords[0])-(node.coords[0]), (node1.coords[1])-(node.coords[1]), (node1.coords[2])-(node.coords[2]), (node2.coords[0])-(node.coords[0]), (node2.coords[1])-(node.coords[1]), (node2.coords[2])-(node.coords[2]), (node3.coords[0])-(node.coords[0]), (node3.coords[1])-(node.coords[1]), (node3.coords[2])-(node.coords[2]) ) / Vol); factor[1] = fabs(tetrVolume( (node0.coords[0])-(node.coords[0]), (node0.coords[1])-(node.coords[1]), (node0.coords[2])-(node.coords[2]), (node2.coords[0])-(node.coords[0]), (node2.coords[1])-(node.coords[1]), (node2.coords[2])-(node.coords[2]), (node3.coords[0])-(node.coords[0]), (node3.coords[1])-(node.coords[1]), (node3.coords[2])-(node.coords[2]) ) / Vol); factor[2] = fabs(tetrVolume( (node1.coords[0])-(node.coords[0]), (node1.coords[1])-(node.coords[1]), (node1.coords[2])-(node.coords[2]), (node0.coords[0])-(node.coords[0]), (node0.coords[1])-(node.coords[1]), (node0.coords[2])-(node.coords[2]), (node3.coords[0])-(node.coords[0]), (node3.coords[1])-(node.coords[1]), (node3.coords[2])-(node.coords[2]) ) / Vol); factor[3] = fabs(tetrVolume( (node1.coords[0])-(node.coords[0]), (node1.coords[1])-(node.coords[1]), (node1.coords[2])-(node.coords[2]), (node2.coords[0])-(node.coords[0]), (node2.coords[1])-(node.coords[1]), (node2.coords[2])-(node.coords[2]), (node0.coords[0])-(node.coords[0]), (node0.coords[1])-(node.coords[1]), (node0.coords[2])-(node.coords[2]) ) / Vol); // If we see potential instability if (factor[0] + factor[1] + factor[2] + factor[3] > 1.0) { // If it is small - treat instability as minor and just 'smooth' it // TODO - think about it more carefully //if( point_in_tetr(node.local_num, node.coords[0], node.coords[1], node.coords[2], tetr) ) if (factor[0] + factor[1] + factor[2] + factor[3] < 1.05) // FIXME@avasyukov { //if (factor[0] + factor[1] + factor[2] + factor[3] > 5.0) // LOG_ERROR("Factor: " << factor[0] + factor[1] + factor[2] + factor[3]); float sum = factor[0] + factor[1] + factor[2] + factor[3]; for (int i = 0; i < 4; i++) factor[i] = factor[i] / sum; } // If point is not in tetr - throw exception else { /* *logger << "\tTetrVol = " < Vol; *logger << "\tfactor[0]=" << factor[0] << " factor[1]=" << factor[1] << " factor[2]=" << factor[2] << " factor[3]=" << factor[3] << " Sum: " < factor[0] + factor[1] + factor[2] + factor[3]; *logger << "\tnode.coords.x[0]=" << node.coords[0] << " node.coords.x[1]=" << node.coords[1] << " node.coords.x[2]=" < node.coords[2]; if( node.isFirstOrder() ) *logger < "First order node"; else if( node.isSecondOrder() ) *logger < "Second order node"; *logger << "\tv0.x[0]=" << nodes[tetr.vert[0]].coords[0] << " v0.x[1]=" << nodes[tetr.vert[0]].coords[1] << " v0.x[2]=" < nodes[tetr.vert[0]].coords[2]; *logger << "\tv1.x[0]=" << nodes[tetr.vert[1]].coords[0] << " v1.x[1]=" << nodes[tetr.vert[1]].coords[1] << " v1.x[2]=" < nodes[tetr.vert[1]].coords[2]; *logger << "\tv2.x[0]=" << nodes[tetr.vert[2]].coords[0] << " v2.x[1]=" << nodes[tetr.vert[2]].coords[1] << " v2.x[2]=" < nodes[tetr.vert[2]].coords[2]; *logger << "\tv3.x[0]=" << nodes[tetr.vert[3]].coords[0] << " v3.x[1]=" << nodes[tetr.vert[3]].coords[1] << " v3.x[2]=" < nodes[tetr.vert[3]].coords[2];*/ LOG_ERROR("Requested node: " << node); LOG_ERROR("Node #1: " << node0); LOG_ERROR("Node #2: " << node1); LOG_ERROR("Node #3: " << node2); LOG_ERROR("Node #4: " << node3); LOG_ERROR("Factor: " << factor[0] + factor[1] + factor[2] + factor[3]); THROW_BAD_MESH("Sum of factors is greater than 1.0"); } } for (int i = 0; i < 9; i++) { node.values[i] = (node0.values[i] * factor[0] + node1.values[i] * factor[1] + node2.values[i] * factor[2] + node3.values[i] * factor[3]); } node.setRho(node0.getRho() * factor[0] + node1.getRho() * factor[1] + node2.getRho() * factor[2] + node3.getRho() * factor[3]); node.setMaterialId(node0.getMaterialId()); LOG_TRACE("Interpolation done"); }
/** * Use the ColumnEditor dialog to edit the currently selected column * definition. Called when the "Edit" button is pressed. */ void DBEditor::editColumn() { QTreeWidgetItem *item = table->currentItem(); if (!item) { return; } QString name = item->text(0); QString oldName = name; int index = info.Find(ceName [name.toUtf8()]); int type = ceType (info[index]); QString defaultVal = QString::fromUtf8(ceDefault (info[index])); columnEditor->setName(name); columnEditor->setType(type); columnEditor->setTypeEditable(false); columnEditor->setDefaultValue(defaultVal); CalcNode *calcRoot = 0; int decimals = 2; if (type == CALC) { calcRoot = calcMap[name]; decimals = decimalsMap[name]; // use a copy in case the edit is cancelled if (calcRoot != 0) { calcRoot = calcRoot->clone(); } columnEditor->setCalculation(calcRoot, decimals); } bool finished = false; bool aborted = false; while (!finished) { if (!columnEditor->exec()) { finished = true; aborted = true; } else { name = columnEditor->name(); type = columnEditor->type(); defaultVal = columnEditor->defaultValue(); if (name != oldName) { finished = (isValidName(name) && isValidDefault(type, defaultVal)); if (finished) { int oldIndex = ceOldIndex (info[index]); if (oldIndex != -1) { renamedCols[oldIndex] = name; } renameColumnRefs(oldName, name); } } else { finished = isValidDefault(type, defaultVal); } } } calcRoot = columnEditor->calculation(&decimals); if (!aborted) { ceName (info[index]) = name.toUtf8(); ceDefault (info[index]) = defaultVal.toUtf8(); if (type == CALC) { CalcNode *oldRoot = calcMap[oldName]; if (oldRoot != 0) { delete oldRoot; } calcMap.remove(oldName); decimalsMap.remove(oldName); calcMap.insert(name, calcRoot); decimalsMap.insert(name, decimals); columnEditor->setCalculation(0, 2); calcRoot = 0; } updateTable(); } if (calcRoot != 0) { delete calcRoot; columnEditor->setCalculation(0, 2); } }
void TetrSecondOrderMinMaxInterpolator::interpolate(CalcNode& node, CalcNode& node0, CalcNode& node1, CalcNode& node2, CalcNode& node3, CalcNode& addNode0, CalcNode& addNode1, CalcNode& addNode2, CalcNode& addNode3, CalcNode& addNode4, CalcNode& addNode5) { LOG_TRACE("Start interpolation"); float factor[4]; float Vol = tetrVolume( (node1.coords[0])-(node0.coords[0]), (node1.coords[1])-(node0.coords[1]), (node1.coords[2])-(node0.coords[2]), (node2.coords[0])-(node0.coords[0]), (node2.coords[1])-(node0.coords[1]), (node2.coords[2])-(node0.coords[2]), (node3.coords[0])-(node0.coords[0]), (node3.coords[1])-(node0.coords[1]), (node3.coords[2])-(node0.coords[2]) ); factor[0] = fabs(tetrVolume( (node1.coords[0])-(node.coords[0]), (node1.coords[1])-(node.coords[1]), (node1.coords[2])-(node.coords[2]), (node2.coords[0])-(node.coords[0]), (node2.coords[1])-(node.coords[1]), (node2.coords[2])-(node.coords[2]), (node3.coords[0])-(node.coords[0]), (node3.coords[1])-(node.coords[1]), (node3.coords[2])-(node.coords[2]) ) / Vol); factor[1] = fabs(tetrVolume( (node0.coords[0])-(node.coords[0]), (node0.coords[1])-(node.coords[1]), (node0.coords[2])-(node.coords[2]), (node2.coords[0])-(node.coords[0]), (node2.coords[1])-(node.coords[1]), (node2.coords[2])-(node.coords[2]), (node3.coords[0])-(node.coords[0]), (node3.coords[1])-(node.coords[1]), (node3.coords[2])-(node.coords[2]) ) / Vol); factor[2] = fabs(tetrVolume( (node1.coords[0])-(node.coords[0]), (node1.coords[1])-(node.coords[1]), (node1.coords[2])-(node.coords[2]), (node0.coords[0])-(node.coords[0]), (node0.coords[1])-(node.coords[1]), (node0.coords[2])-(node.coords[2]), (node3.coords[0])-(node.coords[0]), (node3.coords[1])-(node.coords[1]), (node3.coords[2])-(node.coords[2]) ) / Vol); factor[3] = fabs(tetrVolume( (node1.coords[0])-(node.coords[0]), (node1.coords[1])-(node.coords[1]), (node1.coords[2])-(node.coords[2]), (node2.coords[0])-(node.coords[0]), (node2.coords[1])-(node.coords[1]), (node2.coords[2])-(node.coords[2]), (node0.coords[0])-(node.coords[0]), (node0.coords[1])-(node.coords[1]), (node0.coords[2])-(node.coords[2]) ) / Vol); // If we see potential instability if (factor[0] + factor[1] + factor[2] + factor[3] > 1.0) { // If it is small - treat instability as minor and just 'smooth' it // TODO - think about it more carefully //if( point_in_tetr(node.local_num, node.coords[0], node.coords[1], node.coords[2], tetr) ) if (factor[0] + factor[1] + factor[2] + factor[3] < 1.1) { float sum = factor[0] + factor[1] + factor[2] + factor[3]; for (int i = 0; i < 4; i++) factor[i] = factor[i] / sum; } // If point is not in tetr - throw exception else { /* *logger << "\tTetrVol = " < Vol; *logger << "\tfactor[0]=" << factor[0] << " factor[1]=" << factor[1] << " factor[2]=" << factor[2] << " factor[3]=" << factor[3] << " Sum: " < factor[0] + factor[1] + factor[2] + factor[3]; *logger << "\tnode.coords.x[0]=" << node.coords[0] << " node.coords.x[1]=" << node.coords[1] << " node.coords.x[2]=" < node.coords[2]; if( node.isFirstOrder() ) *logger < "First order node"; else if( node.isSecondOrder() ) *logger < "Second order node"; *logger << "\tv0.x[0]=" << nodes[tetr.vert[0]].coords[0] << " v0.x[1]=" << nodes[tetr.vert[0]].coords[1] << " v0.x[2]=" < nodes[tetr.vert[0]].coords[2]; *logger << "\tv1.x[0]=" << nodes[tetr.vert[1]].coords[0] << " v1.x[1]=" << nodes[tetr.vert[1]].coords[1] << " v1.x[2]=" < nodes[tetr.vert[1]].coords[2]; *logger << "\tv2.x[0]=" << nodes[tetr.vert[2]].coords[0] << " v2.x[1]=" << nodes[tetr.vert[2]].coords[1] << " v2.x[2]=" < nodes[tetr.vert[2]].coords[2]; *logger << "\tv3.x[0]=" << nodes[tetr.vert[3]].coords[0] << " v3.x[1]=" << nodes[tetr.vert[3]].coords[1] << " v3.x[2]=" < nodes[tetr.vert[3]].coords[2];*/ THROW_BAD_MESH("Sum of factors is greater than 1.0"); } } baseNodes[0] = &node0; baseNodes[1] = &node1; baseNodes[2] = &node2; baseNodes[3] = &node3; addNodes[0] = &addNode0; addNodes[1] = &addNode1; addNodes[2] = &addNode2; addNodes[3] = &addNode3; addNodes[4] = &addNode4; addNodes[5] = &addNode5; for (int i = 0; i < 9; i++) { float min = baseNodes[0]->values[i]; float max = baseNodes[0]->values[i]; for (int z = 1; z < 4; z++) { if (baseNodes[z]->values[i] < min) min = baseNodes[z]->values[i]; if (baseNodes[z]->values[i] > max) max = baseNodes[z]->values[i]; } for (int z = 0; z < 6; z++) { if (addNodes[z]->values[i] < min) min = addNodes[z]->values[i]; if (addNodes[z]->values[i] > max) max = addNodes[z]->values[i]; } node.values[i] = (baseNodes[0]->values[i] * factor[0] * (2 * factor[0] - 1) + baseNodes[1]->values[i] * factor[1] * (2 * factor[1] - 1) + baseNodes[2]->values[i] * factor[2] * (2 * factor[2] - 1) + baseNodes[3]->values[i] * factor[3] * (2 * factor[3] - 1) + addNodes[0]->values[i] * 4 * factor[0] * factor[1] + addNodes[1]->values[i] * 4 * factor[0] * factor[2] + addNodes[2]->values[i] * 4 * factor[0] * factor[3] + addNodes[3]->values[i] * 4 * factor[1] * factor[2] + addNodes[4]->values[i] * 4 * factor[1] * factor[3] + addNodes[5]->values[i] * 4 * factor[2] * factor[3] ); if (node.values[i] < min) node.values[i] = min; if (node.values[i] > max) node.values[i] = max; } { float min = baseNodes[0]->getRho(); float max = baseNodes[0]->getRho(); for (int z = 1; z < 4; z++) { if (baseNodes[z]->getRho() < min) min = baseNodes[z]->getRho(); if (baseNodes[z]->getRho() > max) max = baseNodes[z]->getRho(); } for (int z = 0; z < 6; z++) { if (addNodes[z]->getRho() < min) min = addNodes[z]->getRho(); if (addNodes[z]->getRho() > max) max = addNodes[z]->getRho(); } float rho = (baseNodes[0]->getRho() * factor[0] * (2 * factor[0] - 1) + baseNodes[1]->getRho() * factor[1] * (2 * factor[1] - 1) + baseNodes[2]->getRho() * factor[2] * (2 * factor[2] - 1) + baseNodes[3]->getRho() * factor[3] * (2 * factor[3] - 1) + addNodes[0]->getRho() * 4 * factor[0] * factor[1] + addNodes[1]->getRho() * 4 * factor[0] * factor[2] + addNodes[2]->getRho() * 4 * factor[0] * factor[3] + addNodes[3]->getRho() * 4 * factor[1] * factor[2] + addNodes[4]->getRho() * 4 * factor[1] * factor[3] + addNodes[5]->getRho() * 4 * factor[2] * factor[3] ); if (rho < min) rho = min; if (rho > max) rho = max; node.setRho(rho); } node.setMaterialId(baseNodes[0]->getMaterialId()); LOG_TRACE("Interpolation done"); }
void VtuTetrFileReader::readFile(string file, TetrMeshFirstOrder* mesh, GCMDispatcher* dispatcher, int rank) { vtkXMLUnstructuredGridReader *xgr = vtkXMLUnstructuredGridReader::New(); vtkUnstructuredGrid *g = vtkUnstructuredGrid::New(); xgr->SetFileName(const_cast<char*>(file.c_str())); xgr->Update(); g = xgr->GetOutput(); LOG_DEBUG("Number of points: " << g->GetNumberOfPoints()); LOG_DEBUG("Number of cells: " << g->GetNumberOfCells()); double v[3]; vtkDoubleArray *vel = (vtkDoubleArray*) g->GetPointData()->GetArray("velocity"); vel->SetNumberOfComponents(3); vtkDoubleArray *sxx = (vtkDoubleArray*) g->GetPointData()->GetArray("sxx"); vtkDoubleArray *sxy = (vtkDoubleArray*) g->GetPointData()->GetArray("sxy"); vtkDoubleArray *sxz = (vtkDoubleArray*) g->GetPointData()->GetArray("sxz"); vtkDoubleArray *syy = (vtkDoubleArray*) g->GetPointData()->GetArray("syy"); vtkDoubleArray *syz = (vtkDoubleArray*) g->GetPointData()->GetArray("syz"); vtkDoubleArray *szz = (vtkDoubleArray*) g->GetPointData()->GetArray("szz"); vtkIntArray *matId = (vtkIntArray*) g->GetPointData()->GetArray("materialID"); vtkDoubleArray *rho = (vtkDoubleArray*) g->GetPointData()->GetArray("rho"); vtkIntArray *publicFlags = (vtkIntArray*) g->GetPointData ()->GetArray("publicFlags"); vtkIntArray *privateFlags = (vtkIntArray*) g->GetPointData ()->GetArray("privateFlags"); vector<CalcNode*>* nodes = new vector<CalcNode*>; for( int i = 0; i < g->GetNumberOfPoints(); i++ ) { double* dp = g->GetPoint(i); if( dispatcher->isMine( dp, mesh->getBody()->getId() ) ) { CalcNode* node = new CalcNode(); node->number = i; node->coords[0] = dp[0]; node->coords[1] = dp[1]; node->coords[2] = dp[2]; vel->GetTupleValue(i, v); node->vx = v[0]; node->vy = v[1]; node->vz = v[2]; node->sxx = sxx->GetValue(i); node->sxy = sxy->GetValue(i); node->sxz = sxz->GetValue(i); node->syy = syy->GetValue(i); node->syz = syz->GetValue(i); node->szz = szz->GetValue(i); node->setMaterialId( matId->GetValue(i) ); node->setRho( rho->GetValue(i) ); node->setPublicFlags( publicFlags->GetValue(i) ); node->setPrivateFlags( privateFlags->GetValue(i) ); node->setPlacement(true); nodes->push_back( node ); } } LOG_DEBUG("Finished reading nodes"); LOG_DEBUG("There are " << nodes->size() << " local nodes"); mesh->createNodes( nodes->size() ); for(unsigned int i = 0; i < nodes->size(); i++) { mesh->addNode( *nodes->at(i) ); } nodes->clear(); delete nodes; vector<TetrFirstOrder*>* tetrs = new vector<TetrFirstOrder*>; for( int i = 0; i < g->GetNumberOfCells(); i++ ) { int number = tetrs->size(); vtkTetra *vt = (vtkTetra*) g->GetCell(i); int vert[4]; vert[0] = vt->GetPointId(0); vert[1] = vt->GetPointId(1); vert[2] = vt->GetPointId(2); vert[3] = vt->GetPointId(3); if( mesh->hasNode(vert[0]) || mesh->hasNode(vert[1]) || mesh->hasNode(vert[2]) || mesh->hasNode(vert[3]) ) tetrs->push_back( new TetrFirstOrder( number, vert ) ); } LOG_DEBUG("File contains " << g->GetNumberOfCells() << " tetrs"); LOG_DEBUG("There are " << tetrs->size() << " local tetrs"); map<int,int> remoteNodes; mesh->createTetrs( tetrs->size() ); for(unsigned int i = 0; i < tetrs->size(); i++) { TetrFirstOrder* tetr = tetrs->at(i); mesh->addTetr( *tetr ); for(int j = 0; j < 4; j++) if( ! mesh->hasNode( tetr->verts[j] ) ) remoteNodes[tetr->verts[j]] = i; } tetrs->clear(); delete tetrs; LOG_DEBUG("Finished reading elements"); LOG_DEBUG("Reading required remote nodes"); LOG_DEBUG("We expect " << remoteNodes.size() << " nodes" ); int remoteNodesCount = 0; CalcNode tmpNode; for( int i = 0; i < g->GetNumberOfPoints(); i++ ) { if( remoteNodes.find( i ) != remoteNodes.end() ) { double* dp = g->GetPoint(i); tmpNode.number = i; tmpNode.coords[0] = dp[0]; tmpNode.coords[1] = dp[1]; tmpNode.coords[2] = dp[2]; vel->GetTupleValue(i, v); tmpNode.vx = v[0]; tmpNode.vy = v[1]; tmpNode.vz = v[2]; tmpNode.sxx = sxx->GetValue(i); tmpNode.sxy = sxy->GetValue(i); tmpNode.sxz = sxz->GetValue(i); tmpNode.syy = syy->GetValue(i); tmpNode.syz = syz->GetValue(i); tmpNode.szz = szz->GetValue(i); tmpNode.setMaterialId( matId->GetValue(i) ); tmpNode.setRho( rho->GetValue(i) ); tmpNode.setPublicFlags( publicFlags->GetValue(i) ); tmpNode.setPrivateFlags( privateFlags->GetValue(i) ); tmpNode.setPlacement(false); mesh->addNode(tmpNode); remoteNodesCount++; } } LOG_DEBUG("Read " << remoteNodesCount << " remote nodes"); LOG_DEBUG("Finished reading nodes"); LOG_DEBUG("File successfylly read."); LOG_DEBUG("There are " << mesh->getNodesNumber() << " nodes is the mesh"); }