Search in sources :

Example 1 with NumericalException

use of maspack.matrix.NumericalException in project artisynth_core by artisynth.

the class PolygonalMesh method computeVolumeIntegrals.

/**
 * Computes the volume integrals of this mesh, on the assumption that it is
 * manifold and closed. The code for this was taken from vclip, by Brian
 * Mirtich. See "Fast and Accurate Computation of Polyhedral Mass
 * Properties," Brian Mirtich, journal of graphics tools, volume 1, number 2,
 * 1996.
 *
 * @param mov1
 * if non-null, returns the first moment of volume
 * @param mov2
 * if non-null, returns the second moment of volume
 * @param pov
 * if non-null, returns the product of volume
 * @return closed volume of the mesh
 */
public double computeVolumeIntegrals(Vector3d mov1, Vector3d mov2, Vector3d pov) {
    int a, b, c;
    // Edge e;
    // Face f;
    double a0, a1, da;
    // al
    double b0, b1, db;
    double a0_2, a0_3, a0_4, b0_2, b0_3, b0_4;
    double a1_2, a1_3, b1_2, b1_3;
    double d, na, nb, nc, inv;
    double I, Ia, Ib, Iaa, Iab, Ibb, Iaaa, Iaab, Iabb, Ibbb;
    double Icc, Iccc, Ibbc, Icca;
    double C0, Ca, Caa, Caaa, Cb, Cbb, Cbbb;
    double Cab, Kab, Caab, Kaab, Cabb, Kabb;
    // h, w;
    Vector3d v;
    if (mov1 != null) {
        mov1.setZero();
    }
    if (mov2 != null) {
        mov2.setZero();
    }
    if (pov != null) {
        pov.setZero();
    }
    // double rad_ = 0;
    double vol_ = 0.0;
    for (int i = 0; i < myFaces.size(); i++) {
        Face f = myFaces.get(i);
        // compute projection direction
        Vector3d nrml = f.getNormal();
        if (nrml.containsNaN()) {
            // sanity check for badly formed meshes
            continue;
        }
        v = new Vector3d();
        v.set(Math.abs(nrml.x), Math.abs(nrml.y), Math.abs(nrml.z));
        c = (v.x >= v.y) ? ((v.x >= v.z) ? 0 : 2) : ((v.y >= v.z) ? 1 : 2);
        a = (c + 1) % 3;
        b = (c + 2) % 3;
        I = Ia = Ib = Iaa = Iab = Ibb = Iaaa = Iaab = Iabb = Ibbb = 0.0;
        // walk around face
        HalfEdge he0 = f.firstHalfEdge();
        HalfEdge he = he0;
        do {
            a0 = he.getTail().pnt.get(a);
            b0 = he.getTail().pnt.get(b);
            a1 = he.getHead().pnt.get(a);
            b1 = he.getHead().pnt.get(b);
            da = a1 - a0;
            db = b1 - b0;
            a0_2 = a0 * a0;
            a0_3 = a0_2 * a0;
            a0_4 = a0_3 * a0;
            b0_2 = b0 * b0;
            b0_3 = b0_2 * b0;
            b0_4 = b0_3 * b0;
            a1_2 = a1 * a1;
            a1_3 = a1_2 * a1;
            b1_2 = b1 * b1;
            b1_3 = b1_2 * b1;
            C0 = a1 + a0;
            Ca = a1 * C0 + a0_2;
            Caa = a1 * Ca + a0_3;
            Caaa = a1 * Caa + a0_4;
            Cb = b1 * (b1 + b0) + b0_2;
            Cbb = b1 * Cb + b0_3;
            Cbbb = b1 * Cbb + b0_4;
            Cab = 3 * a1_2 + 2 * a1 * a0 + a0_2;
            Kab = a1_2 + 2 * a1 * a0 + 3 * a0_2;
            Caab = a0 * Cab + 4 * a1_3;
            Kaab = a1 * Kab + 4 * a0_3;
            Cabb = 4 * b1_3 + 3 * b1_2 * b0 + 2 * b1 * b0_2 + b0_3;
            Kabb = b1_3 + 2 * b1_2 * b0 + 3 * b1 * b0_2 + 4 * b0_3;
            I += db * C0;
            Ia += db * Ca;
            Iaa += db * Caa;
            Iaaa += db * Caaa;
            Ib += da * Cb;
            Ibb += da * Cbb;
            Ibbb += da * Cbbb;
            Iab += db * (b1 * Cab + b0 * Kab);
            Iaab += db * (b1 * Caab + b0 * Kaab);
            Iabb += da * (a1 * Cabb + a0 * Kabb);
            he = he.getNext();
        } while (he != he0);
        I /= 2.0;
        Ia /= 6.0;
        Iaa /= 12.0;
        Iaaa /= 20.0;
        Ib /= -6.0;
        Ibb /= -12.0;
        Ibbb /= -20.0;
        Iab /= 24.0;
        Iaab /= 60.0;
        Iabb /= -60.0;
        d = -nrml.dot(f.firstHalfEdge().getHead().pnt);
        na = nrml.get(a);
        nb = nrml.get(b);
        nc = nrml.get(c);
        inv = 1.0 / nc;
        if (a == 0) {
            vol_ += inv * na * Ia;
        } else if (b == 0) {
            vol_ += inv * nb * Ib;
        } else {
            vol_ -= ((d * I + na * Ia + nb * Ib) / nc);
        }
        if (vol_ != vol_) {
            throw new NumericalException("nrml=" + nrml + ", face " + i);
        }
        Icc = (SQR(na) * Iaa + 2 * na * nb * Iab + SQR(nb) * Ibb + d * (2 * (na * Ia + nb * Ib) + d * I)) * SQR(inv);
        if (mov1 != null) {
            mov1.set(a, mov1.get(a) + inv * na * Iaa);
            mov1.set(b, mov1.get(b) + inv * nb * Ibb);
            mov1.set(c, mov1.get(c) + Icc);
        }
        Iccc = -(CUBE(na) * Iaaa + 3 * SQR(na) * nb * Iaab + 3 * na * SQR(nb) * Iabb + CUBE(nb) * Ibbb + 3 * (SQR(na) * Iaa + 2 * na * nb * Iab + SQR(nb) * Ibb) * d + d * d * (3 * (na * Ia + nb * Ib) + d * I)) * CUBE(inv);
        if (mov2 != null) {
            mov2.set(a, mov2.get(a) + inv * na * Iaaa);
            mov2.set(b, mov2.get(b) + inv * nb * Ibbb);
            mov2.set(c, mov2.get(c) + Iccc);
        }
        Ibbc = -(d * Ibb + na * Iabb + nb * Ibbb) * inv;
        Icca = (SQR(na) * Iaaa + 2 * na * nb * Iaab + SQR(nb) * Iabb + d * (2 * (na * Iaa + nb * Iab) + d * Ia)) * SQR(inv);
        if (pov != null) {
            pov.set(c, pov.get(c) + inv * na * Iaab);
            pov.set(a, pov.get(a) + inv * nb * Ibbc);
            pov.set(b, pov.get(b) + Icca);
        }
    }
    if (mov1 != null) {
        mov1.scale(0.5);
    }
    if (mov2 != null) {
        mov2.scale(1.0 / 3.0);
    }
    if (pov != null) {
        pov.scale(0.5);
    }
    return vol_;
}
Also used : Vector3d(maspack.matrix.Vector3d) NumericalException(maspack.matrix.NumericalException)

Example 2 with NumericalException

use of maspack.matrix.NumericalException in project artisynth_core by artisynth.

the class FemModel3d method updateStressAndStiffness.

// DIVBLK
public void updateStressAndStiffness() {
    // allocate or deallocate nodal incompressibility blocks
    setNodalIncompBlocksAllocated(getSoftIncompMethod() == IncompMethod.NODAL);
    // clear existing internal forces and maybe stiffnesses
    for (FemNode3d n : myNodes) {
        n.myInternalForce.setZero();
        if (!myStiffnessesValidP) {
            for (FemNodeNeighbor nbr : getNodeNeighbors(n)) {
                nbr.zeroStiffness();
            }
            // used for soft nodal-based incompressibilty:
            for (FemNodeNeighbor nbr : getIndirectNeighbors(n)) {
                nbr.zeroStiffness();
            }
        }
        if (myComputeNodalStress) {
            n.zeroStress();
        }
        if (myComputeNodalStrain) {
            n.zeroStrain();
        }
    }
    if (!myVolumeValid) {
        updateVolume();
    }
    IncompMethod softIncomp = getSoftIncompMethod();
    if (softIncomp == IncompMethod.NODAL) {
        if (!myNodalRestVolumesValidP) {
            updateNodalRestVolumes();
        }
        setNodalIncompConstraintsAllocated(true);
        updateNodalPressures((IncompressibleMaterial) myMaterial);
        for (FemNode3d n : myNodes) {
            for (FemNodeNeighbor nbr : getNodeNeighbors(n)) {
                nbr.myDivBlk.setZero();
            }
        }
    }
    Matrix6d D = new Matrix6d();
    // compute new forces as well as stiffness matrix if warping is enabled
    myMinDetJ = Double.MAX_VALUE;
    myMinDetJElement = null;
    myNumInverted = 0;
    double mins = Double.MAX_VALUE;
    FemElement3d minE = null;
    for (FemElement3d e : myElements) {
        FemMaterial mat = getElementMaterial(e);
        computeStressAndStiffness(e, mat, D, softIncomp);
        if (checkTangentStability) {
            double s = checkMatrixStability(D);
            if (s < mins) {
                mins = s;
                minE = e;
            }
        }
    }
    // incompressibility
    if ((softIncomp == IncompMethod.NODAL) && myMaterial != null && myMaterial.isIncompressible()) {
        computeNodalIncompressibility((IncompressibleMaterial) myMaterial, D);
    }
    if (checkTangentStability && minE != null) {
        System.out.println("min s=" + mins + ", element " + minE.getNumber());
    }
    if (myNumInverted > 0) {
        if (myWarnOnInvertedElems) {
            System.out.println("Warning: " + myNumInverted + " inverted elements; min detJ=" + myMinDetJ + ", element " + ComponentUtils.getPathName(myMinDetJElement));
        }
        if (myAbortOnInvertedElems) {
            throw new NumericalException("Inverted elements");
        }
    }
    if (!myStiffnessesValidP && mySolveMatrixSymmetricP) {
        for (FemNode3d n : myNodes) {
            int bi = n.getSolveIndex();
            if (bi != -1) {
                for (FemNodeNeighbor nbr : getNodeNeighbors(n)) {
                    int bj = nbr.myNode.getSolveIndex();
                    if (bj > bi) {
                        FemNodeNeighbor nbrT = nbr.myNode.getNodeNeighborBySolveIndex(bi);
                        nbrT.setTransposedStiffness(nbr);
                    }
                }
                // used for soft nodal-based incompressibilty:
                for (FemNodeNeighbor nbr : getIndirectNeighbors(n)) {
                    int bj = nbr.myNode.getSolveIndex();
                    if (bj > bi) {
                        FemNodeNeighbor nbrT = nbr.myNode.getIndirectNeighborBySolveIndex(bi);
                        nbrT.setTransposedStiffness(nbr);
                    }
                }
            }
        }
    }
    myStiffnessesValidP = true;
    myStressesValidP = true;
// timerStop("stressAndStiffness");
}
Also used : FemMaterial(artisynth.core.materials.FemMaterial) NumericalException(maspack.matrix.NumericalException) Matrix6d(maspack.matrix.Matrix6d) Point(artisynth.core.mechmodels.Point)

Aggregations

NumericalException (maspack.matrix.NumericalException)2 FemMaterial (artisynth.core.materials.FemMaterial)1 Point (artisynth.core.mechmodels.Point)1 Matrix6d (maspack.matrix.Matrix6d)1 Vector3d (maspack.matrix.Vector3d)1