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); }
void ConsumingBorderCalculator::doCalc(CalcNode& cur_node, CalcNode& new_node, RheologyMatrixPtr matrix, vector<CalcNode>& previousNodes, bool inner[], float outer_normal[], float scale) { assert_eq(previousNodes.size(), 9); int outer_count = 3; // Tmp value for GSL solver int s; // Here we will store (omega = Matrix_OMEGA * u) float omega[9]; for(int i = 0; i < 9; i++) { // If omega is 'inner' one if(inner[i]) { // Calculate omega value omega[i] = 0; for(int j = 0; j < 9; j++) { omega[i] += matrix->getU(i,j) * previousNodes[i].values[j]; } // Load appropriate values into GSL containers gsl_vector_set(om_gsl, i, omega[i]); for(int j = 0; j < 9; j++) gsl_matrix_set(U_gsl, i, j, matrix->getU(i,j)); } // If omega is 'outer' one else { // Load appropriate values into GSL containers gsl_vector_set(om_gsl, i, 0); for(int j = 0; j < 9; j++) gsl_matrix_set(U_gsl, i, j, matrix->getU(i,j)); } } LOG_TRACE("F*****g FBC: outer_count = " << outer_count << "\nMatrix:\n"); for(int i = 0; i < 9; i++) { for(int j = 0; j < 9; j++) { LOG_TRACE(gsl_matrix_get(U_gsl, i, j) << "\t"); } LOG_TRACE("\n"); } // Solve linear equations using GSL tools gsl_linalg_LU_decomp (U_gsl, p_gsl, &s); gsl_linalg_LU_solve (U_gsl, p_gsl, om_gsl, x_gsl); for(int j = 0; j < 9; j++) new_node.values[j] = gsl_vector_get(x_gsl, j); };
void AdhesionContactCalculator::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); // 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++) { // If omega is 'inner' if(inner[i]) { // 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++) { // If omega is 'inner' if(virt_inner[i]) { // 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 ); } // Equality of velocities gsl_matrix_set( U_gsl, 12, 0, 1 ); gsl_matrix_set( U_gsl, 12, 9, -1 ); gsl_matrix_set( U_gsl, 13, 1, 1 ); gsl_matrix_set( U_gsl, 13, 10, -1 ); gsl_matrix_set( U_gsl, 14, 2, 1 ); gsl_matrix_set( U_gsl, 14, 11, -1 ); // Equality of normal and tangential stress // 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 gsl_matrix_set(U_gsl, 15, 3, outer_normal[0]); gsl_matrix_set(U_gsl, 15, 4, outer_normal[1]); gsl_matrix_set(U_gsl, 15, 5, outer_normal[2]); gsl_matrix_set(U_gsl, 15, 12, -outer_normal[0]); gsl_matrix_set(U_gsl, 15, 13, -outer_normal[1]); gsl_matrix_set(U_gsl, 15, 14, -outer_normal[2]); gsl_matrix_set(U_gsl, 16, 4, outer_normal[0]); gsl_matrix_set(U_gsl, 16, 6, outer_normal[1]); gsl_matrix_set(U_gsl, 16, 7, outer_normal[2]); gsl_matrix_set(U_gsl, 16, 13, -outer_normal[0]); gsl_matrix_set(U_gsl, 16, 15, -outer_normal[1]); gsl_matrix_set(U_gsl, 16, 16, -outer_normal[2]); gsl_matrix_set(U_gsl, 17, 5, outer_normal[0]); gsl_matrix_set(U_gsl, 17, 7, outer_normal[1]); gsl_matrix_set(U_gsl, 17, 8, outer_normal[2]); gsl_matrix_set(U_gsl, 17, 14, -outer_normal[0]); gsl_matrix_set(U_gsl, 17, 16, -outer_normal[1]); gsl_matrix_set(U_gsl, 17, 17, -outer_normal[2]); // Tmp value for GSL solver int s; gsl_linalg_LU_decomp (U_gsl, p_gsl, &s); gsl_linalg_LU_solve (U_gsl, p_gsl, om_gsl, x_gsl); // 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); };
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 FreeBorderCalculator::doCalc(CalcNode& cur_node, CalcNode& new_node, RheologyMatrixPtr matrix, vector<CalcNode>& previousNodes, bool inner[], float outer_normal[], float scale) { assert_eq(previousNodes.size(), 9); int outer_count = 3; // Tmp value for GSL solver int s; // Here we will store (omega = Matrix_OMEGA * u) float omega[9]; for(int i = 0; i < 9; i++) { // If omega is 'inner' one if(inner[i]) { // Calculate omega value omega[i] = 0; for(int j = 0; j < 9; j++) { omega[i] += matrix->getU(i,j) * previousNodes[i].values[j]; } // Load appropriate values into GSL containers gsl_vector_set(om_gsl, i, omega[i]); for(int j = 0; j < 9; j++) gsl_matrix_set(U_gsl, i, j, matrix->getU(i,j)); } // If omega is 'outer' one else { // omega (as right-hand part of OLE) is zero - it is free border, no external stress gsl_vector_set(om_gsl, i, 0); // corresponding string in matrix is zero ... for(int j = 0; j < 9; j++) gsl_matrix_set(U_gsl, i, j, 0); // ... except normal and tangential stress // We use outer normal to find total stress vector (sigma * n) - sum of normal and shear - and tell it is zero // TODO - never-ending questions - is everything ok with (x-y-z) and (ksi-eta-dzeta) basises? if ( outer_count == 3 ) { gsl_matrix_set(U_gsl, i, 3, outer_normal[0]); gsl_matrix_set(U_gsl, i, 4, outer_normal[1]); gsl_matrix_set(U_gsl, i, 5, outer_normal[2]); outer_count--; } else if ( outer_count == 2 ) { gsl_matrix_set(U_gsl, i, 4, outer_normal[0]); gsl_matrix_set(U_gsl, i, 6, outer_normal[1]); gsl_matrix_set(U_gsl, i, 7, outer_normal[2]); outer_count--; } else if ( outer_count == 1 ) { gsl_matrix_set(U_gsl, i, 5, outer_normal[0]); gsl_matrix_set(U_gsl, i, 7, outer_normal[1]); gsl_matrix_set(U_gsl, i, 8, outer_normal[2]); outer_count--; } } } // Solve linear equations using GSL tools gsl_linalg_LU_decomp (U_gsl, p_gsl, &s); gsl_linalg_LU_solve (U_gsl, p_gsl, om_gsl, x_gsl); for(int j = 0; j < 9; j++) new_node.values[j] = gsl_vector_get(x_gsl, j); };
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 CalcNode::setRheologyMatrix(RheologyMatrixPtr matrix) { assert_true(matrix.get()); rheologyMatrix = matrix; }