void Line2SurfaceTension :: computeLoadVector(FloatArray &answer, ValueModeType mode, TimeStep *tStep)
{
    ///@todo Support axisymm.
    //domainType dt = this->giveDomain()->giveDomainType();
    IntegrationRule *iRule = this->integrationRulesArray [ 0 ];
    double t = 1, gamma_s;
    ///@todo Should i use this? Not used in FM module (but perhaps it should?) / Mikael.
    //t = this->giveDomain()->giveCrossSection(1)->give(CS_Thickness);
    gamma_s = this->giveMaterial()->give('g', NULL);

    FloatMatrix xy(2, 3);
    Node *node;
    for ( int i = 1; i <= 3; i++ ) {
        node = giveNode(i);
        xy.at(1, i) = node->giveCoordinate(1);
        xy.at(2, i) = node->giveCoordinate(2);
    }

    FloatArray A;
    FloatArray dNdxi(3);
    FloatArray es(2); // tangent vector to curve
    FloatMatrix BJ(2, 6);
    BJ.zero();

    answer.resize(6);
    answer.zero();

    for ( int k = 0; k < iRule->getNumberOfIntegrationPoints(); k++ ) {
        GaussPoint *gp = iRule->getIntegrationPoint(k);
        //interpolation.evaldNdx(dN, domain, dofManArray, * gp->giveCoordinates(), 0.0);
        double xi = gp->giveCoordinate(1);

        // Some simplifications can be performed, since the mapping J is a scalar.
        dNdxi.at(1) = -0.5 + xi;
        dNdxi.at(2) =  0.5 + xi;
        dNdxi.at(3) = -2.0 * xi;

        es.beProductOf(xy, dNdxi);
        double J = es.computeNorm();
        es.times(1 / J); //es.normalize();

        // dNds = dNdxi/J
        // B.at(1,1) = dNds.at(1); and so on.

        BJ.at(1, 1) = BJ.at(2, 2) = dNdxi.at(1);
        BJ.at(1, 3) = BJ.at(2, 4) = dNdxi.at(2);
        BJ.at(1, 5) = BJ.at(2, 6) = dNdxi.at(3);

        A.beTProductOf(BJ, es);
        answer.add( - gamma_s * t * gp->giveWeight(), A); // Note! Negative sign!
    }
}
Esempio n. 2
0
double
FEI3dTetQuad :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo)
{
    IntArray snodes(3);
    FloatArray a,b;
    this->computeLocalSurfaceMapping(snodes, isurf);

    double l1, l2, l3;
    l1 = lcoords.at(1);
    l2 = lcoords.at(2);
    l3 = 1.0 - l1 - l2;

    FloatArray dNdxi(6), dNdeta(6);

    dNdxi(0) = 4.0 * l1 - 1.0;
    dNdxi(1) = 0.0;
    dNdxi(2) = -1.0 * ( 4.0 * l3 - 1.0 );
    dNdxi(3) = 4.0 * l2;
    dNdxi(4) = -4.0 * l2;
    dNdxi(5) = 4.0 * l3 - 4.0 * l1;

    dNdeta(0) = 0.0;
    dNdeta(1) = 4.0 * l2 - 1.0;
    dNdeta(2) = -1.0 * ( 4.0 * l3 - 1.0 );
    dNdeta(3) = 4.0 * l1;
    dNdeta(4) = 4.0 * l3 - 4.0 * l2;
    dNdeta(5) = -4.0 * l1;

    for (int i = 0; i < 6; ++i) {
        a.add(dNdxi(i),  *cellgeo.giveVertexCoordinates(snodes(i)));
        b.add(dNdeta(i), *cellgeo.giveVertexCoordinates(snodes(i)));
    }
    answer.beVectorProductOf(a, b);
    double J = answer.computeNorm();
    answer.times(1/J);
    return J;
}
Esempio n. 3
0
void
FEI2dTrQuad :: edgeEvaldNds(FloatArray &answer, int iedge,
                            const FloatArray &lcoords, const FEICellGeometry &cellgeo)
{
    // I think it at least should return both dNds and J. Both are almost always needed.
    // In fact, dxdxi is also needed sometimes (surface tension)
#if 0
    IntArray edgeNodes;
    FloatArray dNdxi(3);
    FloatArray dxdxi(2);
    double xi = lcoords.at(1);
    this->computeLocalEdgeMapping(edgeNodes, iedge);
    dNdxi.at(1) = xi - 0.5;
    dNdxi.at(2) = xi + 0.5;
    dNdxi.at(3) = -2 * xi;

    dxdxi.at(1) = dNdxi.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(xind) +
    dNdxi.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(xind) +
    dNdxi.at(3) * cellgeo.giveVertexCoordinates( edgeNodes.at(3) )->at(xind);
    dxdxi.at(2) = dNdxi.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(yind) +
    dNdxi.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(yind) +
    dNdxi.at(3) * cellgeo.giveVertexCoordinates( edgeNodes.at(3) )->at(yind);

    double J = dxdxi.computeNorm();
    answer = dNdxi;
    answer.times(1 / J);
    return J;

#endif
    double xi = lcoords.at(1);
    double J = edgeGiveTransformationJacobian(iedge, lcoords, cellgeo);
    answer = {
        ( xi - 0.5 ) / J,
        ( xi + 0.5 ) / J,
        -2 * xi / J
    };
}
void Line2SurfaceTension :: computeTangent(FloatMatrix &answer, TimeStep *tStep)
{
#if 1
    answer.resize(6, 6);
    answer.zero();
#else
    ///@todo Support axisymm.
    domainType dt = this->giveDomain()->giveDomainType();
    if (dt == _3dAxisymmMode) {
        OOFEM_ERROR("Line2SurfaceTension :: computeTangent - Axisymm not implemented");
    }
    IntegrationRule *iRule = this->integrationRulesArray [ 0 ];
    double t = 1, gamma_s;
    ///@todo Should i use this? Not that meaningful for flow problems.
    //t = this->giveDomain()->giveCrossSection(1)->give(CS_Thickness);
    gamma_s = this->giveMaterial()->give('g', NULL);

    FloatMatrix xy(2,3);
    Node *node;
    for (int i = 1; i <= 3; i++) {
        node = giveNode(i);
        xy.at(1,i) = node->giveCoordinate(1);
        xy.at(2,i) = node->giveCoordinate(2);
    }

    FloatArray A;
    FloatArray dNdxi(3);
    FloatArray es(2); // tangent vector to curve
    FloatMatrix BJ(2,6);
    BJ.zero();
    FloatMatrix temp1,temp2;

    answer.resize(6,6);
    answer.zero();
    for (int k = 0; k < iRule->getNumberOfIntegrationPoints(); k++ ) {
        GaussPoint *gp = iRule->getIntegrationPoint(k);

        double xi = gp->giveCoordinate(1);

        dNdxi.at(1) = -0.5+xi;
        dNdxi.at(2) =  0.5+xi;
        dNdxi.at(3) = -2.0*xi;

        es.beProductOf(xy,dNdxi);
        double J = es.computeNorm();
        es.times(1/J); //es.normalize();

        BJ.at(1,1) = BJ.at(2,2) = dNdxi.at(1);
        BJ.at(1,3) = BJ.at(2,4) = dNdxi.at(2);
        BJ.at(1,5) = BJ.at(2,6) = dNdxi.at(3);

        A.beTProductOf(BJ,es);

        temp1.beTProductOf(BJ,BJ);
        temp2.beDyadicProductOf(A,A);
        temp1.subtract(temp2);
        temp1.times(t*gp->giveWeight()/J*(tStep->giveTimeIncrement()));
        answer.add(temp1);
    }
    answer.times(gamma_s);
#endif
}