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;
    }

};
示例#5
0
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");
    }
}
示例#7
0
void CalcNode::setRheologyMatrix(RheologyMatrixPtr matrix)
{
    assert_true(matrix.get());
    rheologyMatrix = matrix;
}