void FE2FluidMaterial :: giveDeviatoricPressureStiffness(FloatArray &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep)
{
    FE2FluidMaterialStatus *ms = static_cast<FE2FluidMaterialStatus*> (this->giveStatus(gp));
    ms->computeTangents(tStep);
    if ( mode == TangentStiffness ) {
        answer = ms->giveDeviatoricPressureTangent();
#ifdef DEBUG_TANGENT
        // Numerical ATS for debugging
        FloatArray strain(3); strain.zero();
        FloatArray sig, sigh;
        double epspvol, pressure = 0.0;
        double h = 1.00; // Linear problem, size of this doesn't matter.
        computeDeviatoricStressVector (sig, epspvol, gp, strain, pressure, tStep);
        computeDeviatoricStressVector (sigh, epspvol, gp, strain, pressure+h, tStep);

        FloatArray dsigh; dsigh.beDifferenceOf(sigh,sig); dsigh.times(1/h);

        printf("Analytical deviatoric pressure tangent = "); answer.printYourself();
        printf("Numerical deviatoric pressure tangent = "); dsigh.printYourself();
        dsigh.subtract(answer);
        double norm = dsigh.computeNorm();
        if (norm > answer.computeNorm()*DEBUG_ERR && norm > 0.0) {
            OOFEM_ERROR("Error in deviatoric pressure tangent");
        }
#endif
    } else {
        OOFEM_ERROR("Mode not implemented");
    }
}
Example #2
0
void
NLStructuralElement :: computeDeformationGradientVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep)
{
    // Computes the deformation gradient in the Voigt format at the Gauss point gp of
    // the receiver at time step tStep.
    // Order of components: 11, 22, 33, 23, 13, 12, 32, 31, 21 in the 3D.

    // Obtain the current displacement vector of the element and subtract initial displacements (if present)
    FloatArray u;
    this->computeVectorOf({D_u, D_v, D_w}, VM_Total, tStep, u); // solution vector
    if ( initialDisplacements ) {
        u.subtract(* initialDisplacements);
    }

    // Displacement gradient H = du/dX
    FloatMatrix B;
    this->computeBHmatrixAt(gp, B);
    answer.beProductOf(B, u);

    // Deformation gradient F = H + I
    MaterialMode matMode = gp->giveMaterialMode();
    if ( matMode == _3dMat || matMode == _PlaneStrain ) {
        answer.at(1) += 1.0;
        answer.at(2) += 1.0;
        answer.at(3) += 1.0;
    } else if ( matMode == _PlaneStress ) {
        answer.at(1) += 1.0;
        answer.at(2) += 1.0;
    } else if ( matMode == _1dMat ) {
        answer.at(1) += 1.0;
    } else {
        OOFEM_ERROR("MaterialMode is not supported yet (%s)", __MaterialModeToString(matMode) );
    }
}
Example #3
0
void
B3SolidMaterial :: giveShrinkageStrainVector(FloatArray &answer,
                                             GaussPoint *gp,
                                             TimeStep *tStep,
                                             ValueModeType mode)
{
    FloatArray prevAnswer;

    if ( this->shMode == B3_NoShrinkage ) {
        answer.resize( StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) );
        answer.zero();
        return;
    }

    if ( ( mode != VM_Total ) && ( mode != VM_Incremental ) ) {
        OOFEM_ERROR("unsupported mode");
    }

    if ( this->shMode == B3_AverageShrinkage ) {
        this->computeTotalAverageShrinkageStrainVector(answer, gp, tStep);

        if ( ( mode == VM_Incremental ) && ( !tStep->isTheFirstStep() ) ) {
            this->computeTotalAverageShrinkageStrainVector( prevAnswer, gp, tStep->givePreviousStep() );
            answer.subtract(prevAnswer);
        }
    } else {
        this->computePointShrinkageStrainVector(answer, gp, tStep);
    }
}
double LineSurfaceTension :: SpatialLocalizerI_giveDistanceFromParametricCenter(const FloatArray &coords)
{
    FloatArray c;
    c = *this->giveNode(1)->giveCoordinates();
    c.add(*this->giveNode(2)->giveCoordinates());
    c.times(0.5);
    c.subtract(coords);
    return c.computeNorm();
}
Example #5
0
void
PrimaryField :: initialize(ValueModeType mode, TimeStep *tStep, FloatArray &answer, const UnknownNumberingScheme &s)
{
    if ( mode == VM_Total ) {
        answer = * ( this->giveSolutionVector(tStep) );
    } else if ( mode == VM_Incremental ) {
        int indxm1 = this->resolveIndx(tStep, -1);
        answer = * ( this->giveSolutionVector(tStep) );
        answer.subtract( * this->giveSolutionVector(indxm1) );
    } else {
        OOFEM_ERROR("unsupported mode %s", __ValueModeTypeToString(mode));
    }
}
Example #6
0
void
Beam3d :: giveEndForcesVector(FloatArray &answer, TimeStep *tStep)
{
    // computes exact global end-forces vector
    FloatArray loadEndForces;

    this->giveInternalForcesVector(answer, tStep);

    // add exact end forces due to nonnodal loading
    this->computeForceLoadVector(loadEndForces, tStep, VM_Total);
    if ( loadEndForces.giveSize() ) {
        answer.subtract(loadEndForces);
    }
}
Example #7
0
void
Beam2d :: giveEndForcesVector(FloatArray &answer, TimeStep *tStep)
{
    // stress equivalent vector in nodes (vector of internal forces)
    FloatArray load;

    this->giveInternalForcesVector(answer, tStep, false);

    // subtract exact end forces due to nonnodal loading
    this->computeLocalForceLoadVector(load, tStep, VM_Total);
    if ( load.isNotEmpty() ) {
        answer.subtract(load);
    }

}
Example #8
0
void
PrimaryField :: initialize(ValueModeType mode, TimeStep *atTime, FloatArray &answer)
{
    int neq =  emodel->giveNumberOfEquations(this->ut);
    answer.resize(neq);
    answer.zero();

    if ( mode == VM_Total ) {
        answer = * ( this->giveSolutionVector(atTime) );
    } else if ( mode == VM_Incremental ) {
        int indxm1 = this->resolveIndx(atTime, -1);
        answer = * ( this->giveSolutionVector(atTime) );
        answer.subtract( *this->giveSolutionVector(indxm1) );
    } else {
        _error2( "giveUnknownValue: unsupported mode %s", __ValueModeTypeToString(mode) );
    }
}
void TransportGradientPeriodic :: computeField(FloatArray &flux, TimeStep *tStep)
{
    DofIDEquationNumbering pnum(true, grad_ids);
    EngngModel *emodel = this->giveDomain()->giveEngngModel();
    FloatArray tmp;
    int npeq = grad_ids.giveSize();
    // sigma = residual (since we use the slave dofs) = f_ext - f_int
    flux.resize(npeq);
    flux.zero();
    emodel->assembleVector(flux, tStep, InternalForceAssembler(), VM_Total, pnum, this->domain);
    tmp.resize(npeq);
    tmp.zero();
    emodel->assembleVector(tmp, tStep, ExternalForceAssembler(), VM_Total, pnum, this->domain);
    flux.subtract(tmp);
    // Divide by the RVE-volume
    flux.times(1.0 / ( this->domainSize(this->giveDomain(), this->set) + this->domainSize(this->giveDomain(), this->masterSet) ));
}
Example #10
0
void
StructuralEngngModel :: computeReaction(FloatArray &answer, TimeStep *tStep, int di)
{
    FloatArray contribution;

    answer.resize( this->giveNumberOfDomainEquations( di, EModelDefaultPrescribedEquationNumbering() ) );
    answer.zero();

    // Add internal forces
    this->assembleVector( answer, tStep, LastEquilibratedInternalForcesVector, VM_Total,
                         EModelDefaultPrescribedEquationNumbering(), this->giveDomain(di) );
    // Subtract external loading
    ///@todo All engineering models should be using this (for consistency)
    //this->assembleVector( answer, tStep, ExternalForcesVector, VM_Total,
    //                    EModelDefaultPrescribedEquationNumbering(), this->giveDomain(di) );
    ///@todo This method is overloaded in some functions, it needs to be generalized.
    this->computeExternalLoadReactionContribution(contribution, tStep, di);
    answer.subtract(contribution);
    this->updateSharedDofManagers(answer, EModelDefaultPrescribedEquationNumbering(), ReactionExchangeTag);
}
Example #11
0
void
CCTPlate3d :: giveLocalCoordinates(FloatArray &answer, FloatArray &global)
// Returns global coordinates given in global vector
// transformed into local coordinate system of the
// receiver
{
    FloatArray offset;
    // test the parametr
    if ( global.giveSize() != 3 ) {
        _error("giveLocalCoordinate : cannot transform coordinates - size mismatch");
        exit(1);
    }

    // first ensure that receiver's GtoLRotationMatrix[3,3] is defined
    if ( GtoLRotationMatrix == NULL ) {
        this->computeGtoLRotationMatrix();
    }

    offset = global;
    offset.subtract(*this->giveNode(1)->giveCoordinates());
    answer.beProductOf(* GtoLRotationMatrix, offset);
}
Example #12
0
void
StructuralEngngModel :: computeReaction(FloatArray &answer, TimeStep *tStep, int di)
{
    int numRestrDofs = 0;
    FloatArray contribution;
    FloatArray EquivForces;

    numRestrDofs = this->giveNumberOfPrescribedDomainEquations(di, EID_MomentumBalance);
    answer.resize(numRestrDofs);
    answer.zero();

    // Internal forces contribution
    this->computeInternalForceReactionContribution(contribution, tStep, di);
    answer.add(contribution);
    // External loading contribution
    this->computeExternalLoadReactionContribution(contribution, tStep, di);
    answer.subtract(contribution);

#ifdef __PARALLEL_MODE
    this->updateSharedPrescribedDofManagers( answer, ReactionExchangeTag  );
#endif
}
void
StructuralInterfaceElement :: computeSpatialJump(FloatArray &answer, IntegrationPoint *ip, TimeStep *tStep)
{
    // Computes the spatial jump vector at the Gauss point (ip) of
    // the receiver, at time step (tStep). jump = N*u
    FloatMatrix N;
    FloatArray u;

    if ( !this->isActivated(tStep) ) {
        answer.resize(3);
        answer.zero();
        return;
    }

    this->computeNmatrixAt(ip, N);
    this->computeVectorOf(VM_Total, tStep, u);

    // subtract initial displacements, if defined
    if ( initialDisplacements ) {
        u.subtract(* initialDisplacements);
    }

    answer.beProductOf(N, u);
}
Example #14
0
void
RCM2Material ::  giveRealPrincipalStressVector3d(FloatArray &answer, GaussPoint *gp,
                                                 FloatArray &principalStrain,
                                                 FloatMatrix &tempCrackDirs,
                                                 TimeStep *atTime)
//
// returns real principal stress vector in 3d stress space of receiver according to
// previous level of stress and current
// strain increment, the only way, how to correctly update gp records
// updates principal strain and stress of the receiver's status.
//
{
    int i, iter, ind;
    double maxErr;
    FloatArray crackStrainVector, reducedTotalStrainVector;
    FloatArray strainIncrement, crackStrainIterativeIncrement;
    FloatArray prevPrincipalStrain;
    FloatArray dSigma;
    FloatArray elastStrain, sigmaEl, sigmaCr(3);
    FloatArray fullDSigma;
    IntArray activatedCracks, crackMapping;
    FloatMatrix dcr, de, decr, fullDecr, crackDirs;
    RCM2MaterialStatus *status = ( RCM2MaterialStatus * ) this->giveStatus(gp);

    /*
     * if (status -> giveStressVector() == NULL) status->letStressVectorBe(new FloatArray(this->giveSizeOfReducedStressStrainVector(gp->giveMaterialMode())));
     * if (status -> giveStrainVector() == NULL) status->letStrainVectorBe(new FloatArray(this->giveSizeOfReducedStressStrainVector(gp->giveMaterialMode())));
     * // if (status -> givePlasticStrainVector() == NULL) status->letPlasticStrainVectorBe(new FloatArray(6));
     * if (status -> giveStressIncrementVector() == NULL) status->letStressIncrementVectorBe(new FloatArray(this->giveSizeOfReducedStressStrainVector(gp->giveMaterialMode())));
     * if (status -> giveStrainIncrementVector() == NULL) status->letStrainIncrementVectorBe(new FloatArray(this->giveSizeOfReducedStressStrainVector(gp->giveMaterialMode())));
     * // if (status -> givePlasticStrainIncrementVector() == NULL) status->letPlasticStrainIncrementVectorBe(new FloatArray(6));
     */

    /*
     * // totalStressVector = gp -> giveStressVector()->GiveCopy();
     * reducedTotalStrainVector = status -> giveStrainVector();
     * reducedTotalStrainVector.add(fullStrainIncrement);
     * crossSection->giveFullCharacteristicVector(totalStrainVector, gp, reducedTotalStrainVector);
     * //delete reducedTotalStrainVector;
     * // plasticStrainVector = status -> givePlasticStrainVector()->GiveCopy();
     *
     *
     * // already cracked - next directions are determined
     * // according to principal strain directions
     * status->giveTempCrackDirs(tempCrackDirs);
     * this->computePrincipalValDir (principalStrain, tempCrackDirs,
     *              totalStrainVector,
     *              principal_strain);
     * status->letTempCrackDirsBe (tempCrackDirs);
     */
    status->giveCrackStrainVector(crackStrainVector); // local one
    status->giveCrackDirs(crackDirs);
    if ( principalStrain.containsOnlyZeroes() ) {
        // keep old principal values
        status->letTempCrackDirsBe(crackDirs);
    } else {
        this->sortPrincDirAndValCloseTo(& principalStrain,
                                        & tempCrackDirs, & crackDirs);
        status->letTempCrackDirsBe(tempCrackDirs);
    }

    // compute de in local system
    // for iso materials no transformation if stiffness required
    //
    // local strain increment
    status->givePrevPrincStrainVector(prevPrincipalStrain);
    strainIncrement.beDifferenceOf(principalStrain, prevPrincipalStrain);
    status->letPrincipalStrainVectorBe(principalStrain);

    this->giveNormalElasticStiffnessMatrix(de, FullForm, TangentStiffness,
                                           gp, atTime, tempCrackDirs);
    //
    // construct mapping matrix of active cracks
    // this mapping will dynamically change as
    // some crack can unlo or reload
    //
    this->updateActiveCrackMap(gp);
    status->giveCrackMap(crackMapping);
    // start iteration until stress computed from elastic increment
    // is equal to stress computed from cracking strain increment
    // we do this computation in reduced stress strain space
    dSigma.resize(0);
    for ( iter = 1; iter <= 20; iter++ ) {
        //
        // first check if already cracked
        //
        if ( status->giveNumberOfTempActiveCracks() ) {
            // active crack exist
            this->giveCrackedStiffnessMatrix(dcr, TangentStiffness, gp, atTime);
            fullDecr = de;
            fullDecr.add(dcr);
            decr.beSubMatrixOf(fullDecr, crackMapping);

            if ( dSigma.giveSize() == 0 ) {
                fullDSigma.beProductOf(de, strainIncrement);
                dSigma.beSubArrayOf(fullDSigma, crackMapping);
            }

            decr.solveForRhs(dSigma, crackStrainIterativeIncrement);
            for ( i = 1; i <= 3; i++ ) {
                if ( ( ind = crackMapping.at(i) ) ) {
                    crackStrainVector.at(i) += crackStrainIterativeIncrement.at(ind);
                }
            }

            // check for crack closing, updates also cracking map
            this->checkIfClosedCracks(gp, crackStrainVector, crackMapping);

            // elastic strain component
            elastStrain.beDifferenceOf(principalStrain, crackStrainVector);
            sigmaEl.beProductOf(de, elastStrain);

            // Stress in cracks
            for ( i = 1; i <= 3; i++ ) {
                if ( crackMapping.at(i) ) {
                    sigmaCr.at(i) = giveNormalCrackingStress(gp, crackStrainVector.at(i), i);
                }
            }

            // update status
            status->letCrackStrainVectorBe(crackStrainVector);
        } else {
            //
            // no active crack exist - elastic behaviour
            //
            elastStrain.beDifferenceOf(principalStrain, crackStrainVector);
            sigmaEl.beProductOf(de, elastStrain);
            sigmaCr.zero();
        }

        // check for new cracks
        // and update crack map if necessary
        // when we update map, we need to add new crack at end
        // because sigmaCr is build
        this->checkForNewActiveCracks(activatedCracks, gp, crackStrainVector,
                                      sigmaEl, sigmaCr, principalStrain);
        if ( activatedCracks.giveSize() ) {
            // update crack map also
            this->updateActiveCrackMap(gp, & activatedCracks);
            status->giveCrackMap(crackMapping); // update crackMap
        }

        //

        // compute unbalanced stress
        // dSigma = sigmaEl - sigmaCr for active cracks
        fullDSigma = sigmaEl;
        fullDSigma.subtract(sigmaCr);
        dSigma.beSubArrayOf(fullDSigma, crackMapping);
        // find max error in dSigma
        // if max err < allovedErr -> stop iteration
        // allowed Err is computed relative to Ft;

        // check only for active cracks
        maxErr = 0.;
        for ( i = 1; i <= dSigma.giveSize(); i++ ) {
            if ( fabs( dSigma.at(i) ) > maxErr ) {
                maxErr = fabs( dSigma.at(i) );
            }
        }

        if ( maxErr < rcm_STRESSRELERROR * this->give(pscm_Ft, gp) ) {
            status->letPrincipalStressVectorBe(sigmaEl);
            answer = sigmaEl;
            return;
        }
    } // loop

    // convergence not reached
    _error("GiveRealStressVector3d - convergence not reached");
}
void
SimpleInterfaceMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp,
                                                //const FloatArray &totalStrain,// @todo temporary -should not be here /JB
                                                const FloatArray &strainVector,
                                                TimeStep *tStep)
//
// returns real stress vector in 3d stress space of receiver according to
// previous level of stress and current
// strain increment, the only way, how to correctly update gp records
//
{
    SimpleInterfaceMaterialStatus *status = static_cast< SimpleInterfaceMaterialStatus * >( this->giveStatus(gp) );
    //this->initGpForNewStep(gp);
    this->initTempStatus(gp);
    FloatArray shearStrain(2), shearStress; //, strainVector;
    StructuralElement *el = static_cast< StructuralElement * >( gp->giveElement() );
    //el->computeStrainVector(strainVector, gp, tStep);

    FloatArray tempShearStressShift = status->giveTempShearStressShift();
    const double normalStrain = strainVector.at(1);
    double normalStress, maxShearStress, dp;
    double shift = -this->kn * this->stiffCoeff * normalClearance;

    MaterialMode mMode = el->giveMaterialMode();
    //answer.resize(giveSizeOfReducedStressStrainVector(mMode));
    answer.zero();
    if ( normalStrain + normalClearance <= 0. ) {
        normalStress = this->kn * ( normalStrain + normalClearance ) + shift; //in compression and after the clearance gap closed
        maxShearStress = fabs(normalStress) * this->frictCoeff;
    } else {
        normalStress = this->kn * this->stiffCoeff * ( normalStrain + normalClearance ) + shift;
        maxShearStress = 0.;
    }

    switch ( mMode ) {
    case _1dInterface:
        answer.resize(1);
        break;
    case _2dInterface:
        answer.resize(2);
        shearStrain.at(1) = strainVector.at(2);
        shearStress.beScaled(this->kn, shearStrain);
        shearStress.subtract(tempShearStressShift);
        dp = shearStress.dotProduct(shearStress, 1);
        if ( dp > maxShearStress * maxShearStress ) {
            shearStress.times( maxShearStress / sqrt(dp) );
        }

        tempShearStressShift.beScaled(this->kn, shearStrain);
        tempShearStressShift.subtract(shearStress);
        answer.at(2) = shearStress.at(1);
        break;
    case _3dInterface:
    case _3dMat: //JB
        answer.resize(3);
        shearStrain.at(1) = strainVector.at(2);
        shearStrain.at(2) = strainVector.at(3);
        shearStress.beScaled(this->kn, shearStrain);
        shearStress.subtract(tempShearStressShift);
        dp = shearStress.dotProduct(shearStress, 2);
        if ( dp > maxShearStress * maxShearStress ) {
            shearStress.times( maxShearStress / sqrt(dp) );
        }

        tempShearStressShift.beScaled(this->kn, shearStrain);
        tempShearStressShift.subtract(shearStress);
        answer.at(2) = shearStress.at(1);
        answer.at(3) = shearStress.at(2);
        break;
    default:
        OOFEM_ERROR("Unsupported interface mode");
    }

    double lim = 1.e+50;
    answer.at(1) = min(normalStress, lim);  //threshold on maximum
    answer.at(1) = max(answer.at(1), -lim);  //threshold on minimum
    //answer.at(1) = normalStress > lim ? lim : normalStress < -lim ? -lim : normalStress;
    // update gp
    status->setTempShearStressShift(tempShearStressShift);
    status->letTempStrainVectorBe(strainVector);
    status->letTempStressVectorBe(answer);
}
Example #16
0
int
FEI3dHexaLin :: global2local(FloatArray &answer, const FloatArray &coords, const FEICellGeometry &cellgeo)
{
    double x1, x2, x3, x4, x5, x6, x7, x8, a1, a2, a3, a4, a5, a6, a7, a8;
    double y1, y2, y3, y4, y5, y6, y7, y8, b1, b2, b3, b4, b5, b6, b7, b8;
    double z1, z2, z3, z4, z5, z6, z7, z8, c1, c2, c3, c4, c5, c6, c7, c8;
    double xp, yp, zp, u, v, w;
    FloatMatrix p(3, 3);
    FloatArray r(3), delta;
    int nite = 0;

    x1 = cellgeo.giveVertexCoordinates(1)->at(1);
    x2 = cellgeo.giveVertexCoordinates(2)->at(1);
    x3 = cellgeo.giveVertexCoordinates(3)->at(1);
    x4 = cellgeo.giveVertexCoordinates(4)->at(1);
    x5 = cellgeo.giveVertexCoordinates(5)->at(1);
    x6 = cellgeo.giveVertexCoordinates(6)->at(1);
    x7 = cellgeo.giveVertexCoordinates(7)->at(1);
    x8 = cellgeo.giveVertexCoordinates(8)->at(1);

    y1 = cellgeo.giveVertexCoordinates(1)->at(2);
    y2 = cellgeo.giveVertexCoordinates(2)->at(2);
    y3 = cellgeo.giveVertexCoordinates(3)->at(2);
    y4 = cellgeo.giveVertexCoordinates(4)->at(2);
    y5 = cellgeo.giveVertexCoordinates(5)->at(2);
    y6 = cellgeo.giveVertexCoordinates(6)->at(2);
    y7 = cellgeo.giveVertexCoordinates(7)->at(2);
    y8 = cellgeo.giveVertexCoordinates(8)->at(2);

    z1 = cellgeo.giveVertexCoordinates(1)->at(3);
    z2 = cellgeo.giveVertexCoordinates(2)->at(3);
    z3 = cellgeo.giveVertexCoordinates(3)->at(3);
    z4 = cellgeo.giveVertexCoordinates(4)->at(3);
    z5 = cellgeo.giveVertexCoordinates(5)->at(3);
    z6 = cellgeo.giveVertexCoordinates(6)->at(3);
    z7 = cellgeo.giveVertexCoordinates(7)->at(3);
    z8 = cellgeo.giveVertexCoordinates(8)->at(3);

    xp = coords.at(1);
    yp = coords.at(2);
    zp = coords.at(3);

    a1 =  x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8;
    a2 = -x1 - x2 + x3 + x4 - x5 - x6 + x7 + x8;
    a3 = -x1 + x2 + x3 - x4 - x5 + x6 + x7 - x8;
    a4 =  x1 + x2 + x3 + x4 - x5 - x6 - x7 - x8;
    a5 =  x1 - x2 + x3 - x4 + x5 - x6 + x7 - x8;
    a6 = -x1 - x2 + x3 + x4 + x5 + x6 - x7 - x8;
    a7 = -x1 + x2 + x3 - x4 + x5 - x6 - x7 + x8;
    a8 =  x1 - x2 + x3 - x4 - x5 + x6 - x7 + x8;

    b1 =  y1 + y2 + y3 + y4 + y5 + y6 + y7 + y8;
    b2 = -y1 - y2 + y3 + y4 - y5 - y6 + y7 + y8;
    b3 = -y1 + y2 + y3 - y4 - y5 + y6 + y7 - y8;
    b4 =  y1 + y2 + y3 + y4 - y5 - y6 - y7 - y8;
    b5 =  y1 - y2 + y3 - y4 + y5 - y6 + y7 - y8;
    b6 = -y1 - y2 + y3 + y4 + y5 + y6 - y7 - y8;
    b7 = -y1 + y2 + y3 - y4 + y5 - y6 - y7 + y8;
    b8 =  y1 - y2 + y3 - y4 - y5 + y6 - y7 + y8;

    c1 =  z1 + z2 + z3 + z4 + z5 + z6 + z7 + z8;
    c2 = -z1 - z2 + z3 + z4 - z5 - z6 + z7 + z8;
    c3 = -z1 + z2 + z3 - z4 - z5 + z6 + z7 - z8;
    c4 =  z1 + z2 + z3 + z4 - z5 - z6 - z7 - z8;
    c5 =  z1 - z2 + z3 - z4 + z5 - z6 + z7 - z8;
    c6 = -z1 - z2 + z3 + z4 + z5 + z6 - z7 - z8;
    c7 = -z1 + z2 + z3 - z4 + z5 - z6 - z7 + z8;
    c8 =  z1 - z2 + z3 - z4 - z5 + z6 - z7 + z8;

    // setup initial guess
    answer.resize(3);
    answer.zero();

    // apply Newton-Raphson to solve the problem
    do {
        if ( ( ++nite ) > 10 ) {
            // fprintf(stderr, "FEI3dHexaLin :: global2local: no convergence after 10 iterations");
            answer.zero();
            return false;
        }

        u = answer.at(1);
        v = answer.at(2);
        w = answer.at(3);

        // compute the residual
        r.at(1) = a1 + u * a2 + v * a3 + w * a4 + u * v * a5 + u * w * a6 + v * w * a7 + u * v * w * a8 - 8.0 * xp;
        r.at(2) = b1 + u * b2 + v * b3 + w * b4 + u * v * b5 + u * w * b6 + v * w * b7 + u * v * w * b8 - 8.0 * yp;
        r.at(3) = c1 + u * c2 + v * c3 + w * c4 + u * v * c5 + u * w * c6 + v * w * c7 + u * v * w * c8 - 8.0 * zp;

        // check for convergence
        if ( r.computeSquaredNorm() < 1.e-20 ) {
            break;                                  // sqrt(1.e-20) = 1.e-10
        }

        p.at(1, 1) = a2 + v * a5 + w * a6 + v * w * a8;
        p.at(1, 2) = a3 + u * a5 + w * a7 + u * w * a8;
        p.at(1, 3) = a4 + u * a6 + v * a7 + u * v * a8;

        p.at(2, 1) = b2 + v * b5 + w * b6 + v * w * b8;
        p.at(2, 2) = b3 + u * b5 + w * b7 + u * w * b8;
        p.at(2, 3) = b4 + u * b6 + v * b7 + u * v * b8;

        p.at(3, 1) = c2 + v * c5 + w * c6 + v * w * c8;
        p.at(3, 2) = c3 + u * c5 + w * c7 + u * w * c8;
        p.at(3, 3) = c4 + u * c6 + v * c7 + u * v * c8;

        // solve for corrections
        p.solveForRhs(r, delta);

        // update guess
        answer.subtract(delta);
    } while ( 1 );

    // test if inside
    bool inside = true;
    for ( int i = 1; i <= 3; i++ ) {
        if ( answer.at(i) < ( -1. - POINT_TOL ) ) {
            answer.at(i) = -1.;
            inside = false;
        } else if ( answer.at(i) > ( 1. + POINT_TOL ) ) {
            answer.at(i) = 1.;
            inside = false;
        }
    }

    return inside;
}
Example #17
0
void FE2FluidMaterial :: giveStiffnessMatrices(FloatMatrix &dsdd, FloatArray &dsdp, FloatArray &dedd, double &dedp,
                                               MatResponseMode mode, GaussPoint *gp, TimeStep *tStep)
{
    FE2FluidMaterialStatus *ms = static_cast< FE2FluidMaterialStatus * >( this->giveStatus(gp) );
    ms->computeTangents(tStep);
    if ( mode == TangentStiffness ) {
        dsdd = ms->giveDeviatoricTangent();
        dsdp = ms->giveDeviatoricPressureTangent();
        dedd = ms->giveVolumetricDeviatoricTangent();
        dedp = ms->giveVolumetricPressureTangent();
#if 0
        // Numerical ATS for debugging
        FloatMatrix numericalATS(6, 6);
        FloatArray dsig;
        FloatArray tempStrain(6);

        tempStrain.zero();
        FloatArray sig, strain, sigPert;
        double epspvol;
        computeDeviatoricStressVector(sig, epspvol, gp, tempStrain, 0., tStep);
        double h = 0.001; // Linear problem, size of this doesn't matter.
        for ( int k = 1; k <= 6; ++k ) {
            strain = tempStrain;
            strain.at(k) += h;
            double tmp = strain.at(1) + strain.at(2) + strain.at(3);
            strain.at(1) -= tmp/3.0;
            strain.at(2) -= tmp/3.0;
            strain.at(3) -= tmp/3.0;
            strain.printYourself();
            computeDeviatoricStressVector(sigPert, epspvol, gp, strain, 0., tStep);
            sigPert.printYourself();
            dsig.beDifferenceOf(sigPert, sig);
            numericalATS.setColumn(dsig, k);
        }
        numericalATS.times(1. / h);

        printf("Analytical deviatoric tangent = ");
        dsdd.printYourself();
        printf("Numerical deviatoric tangent = ");
        numericalATS.printYourself();
        numericalATS.subtract(dsdd);
        double norm = numericalATS.computeFrobeniusNorm();
        if ( norm > dsdd.computeFrobeniusNorm() * DEBUG_ERR && norm > 0.0 ) {
            OOFEM_ERROR("Error in deviatoric tangent");
        }
#endif
#if 0
        // Numerical ATS for debugging
        FloatArray strain(3);
        strain.zero();
        FloatArray sig, sigh;
        double epspvol, pressure = 0.0;
        double h = 1.00; // Linear problem, size of this doesn't matter.
        computeDeviatoricStressVector(sig, epspvol, gp, strain, pressure, tStep);
        computeDeviatoricStressVector(sigh, epspvol, gp, strain, pressure + h, tStep);

        FloatArray dsigh;
        dsigh.beDifferenceOf(sigh, sig);
        dsigh.times(1 / h);

        printf("Analytical deviatoric pressure tangent = ");
        dsdp.printYourself();
        printf("Numerical deviatoric pressure tangent = ");
        dsigh.printYourself();
        dsigh.subtract(dsdp);
        double norm = dsigh.computeNorm();
        if ( norm > dsdp.computeNorm() * DEBUG_ERR && norm > 0.0 ) {
            OOFEM_ERROR("Error in deviatoric pressure tangent");
        }
#endif
#if 0
        // Numerical ATS for debugging
        FloatArray tempStrain(3);
        tempStrain.zero();
        FloatArray sig, strain;
        double epspvol, epspvol11, epspvol22, epspvol12, pressure = 0.0;
        double h = 1.0; // Linear problem, size of this doesn't matter.

        computeDeviatoricStressVector(sig, epspvol, gp, tempStrain, pressure, tStep);
        strain = tempStrain;
        strain.at(1) += h;
        computeDeviatoricStressVector(sig, epspvol11, gp, strain, pressure, tStep);
        strain = tempStrain;
        strain.at(2) += h;
        computeDeviatoricStressVector(sig, epspvol22, gp, strain, pressure, tStep);
        strain = tempStrain;
        strain.at(3) += h;
        computeDeviatoricStressVector(sig, epspvol12, gp, strain, pressure, tStep);

        FloatArray dvol(3);
        dvol.at(1) = ( epspvol11 - epspvol ) / h;
        dvol.at(2) = ( epspvol22 - epspvol ) / h;
        dvol.at(3) = ( epspvol12 - epspvol ) / h;
        dvol.at(1) += 1.0;
        dvol.at(2) += 1.0;

        printf("Analytical volumetric deviatoric tangent = ");
        dedd.printYourself();
        printf("Numerical volumetric deviatoric tangent = ");
        dvol.printYourself();
        dvol.subtract(dedd);
        double norm = dvol.computeNorm();
        if ( norm > dedd.computeNorm() * DEBUG_ERR && norm > 0.0 ) {
            OOFEM_ERROR("Error in volumetric deviatoric tangent");
        }
#endif
#if 0
        // Numerical ATS for debugging
        FloatArray strain(3);
        strain.zero();
        FloatArray sig;
        double epspvol, epspvolh, pressure = 0.0;
        double h = 1.0; // Linear problem, size of this doesn't matter.

        computeDeviatoricStressVector(sig, epspvol, gp, strain, pressure, tStep);
        computeDeviatoricStressVector(sig, epspvolh, gp, strain, pressure + h, tStep);

        double dvol = -( epspvolh - epspvol ) / h;

        printf("Analytical volumetric pressure tangent = %e\n", dedp);
        printf("Numerical volumetric pressure tangent = %e\n", dvol);

        double norm = fabs(dvol - dedp);
        if ( norm > fabs(dedp) * DEBUG_ERR && norm > 0.0 ) {
            OOFEM_ERROR("Error in volumetric pressure tangent");
        }
#endif
    } else {
        OOFEM_ERROR("Mode not implemented");
    }
}
Example #18
0
void AbaqusUserMaterial :: giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp,
                                                   const FloatArray &reducedStrain, TimeStep *tStep)
{
    AbaqusUserMaterialStatus *ms = static_cast< AbaqusUserMaterialStatus * >( this->giveStatus(gp) );
    /* User-defined material name, left justified. Some internal material models are given names starting with
     * the “ABQ_” character string. To avoid conflict, you should not use “ABQ_” as the leading string for
     * CMNAME. */
    //char cmname[80];

    // Sizes of the tensors.
    int ndi = 3;
    int nshr = 3;

    int ntens = ndi + nshr;
    FloatArray strain = ms->giveStrainVector();
    FloatArray stress = ms->giveStressVector();
    // adding the initial stress
    stress.add(initialStress);
    FloatArray strainIncrement;
    strainIncrement.beDifferenceOf(reducedStrain, strain);
    FloatArray state = ms->giveStateVector();
    FloatMatrix jacobian(ntens, ntens);
    int numProperties = this->properties.giveSize();

    // Temperature and increment
    double temp = 0.0, dtemp = 0.0;

    // Times and increment
    double dtime = tStep->giveTimeIncrement();
    ///@todo Check this. I'm just guessing. Maybe intrinsic time instead?
    double time [ 2 ] = {
        tStep->giveTargetTime() - dtime, tStep->giveTargetTime()
    };
    double pnewdt = 1.0; ///@todo Right default value? umat routines may change this (although we ignore it)

    /* Specific elastic strain energy, plastic dissipation, and “creep” dissipation, respectively. These are passed
     * in as the values at the start of the increment and should be updated to the corresponding specific energy
     * values at the end of the increment. They have no effect on the solution, except that they are used for
     * energy output. */
    double sse, spd, scd;

    // Outputs only in a fully coupled thermal-stress analysis:
    double rpl = 0.0; // Volumetric heat generation per unit time at the end of the increment caused by mechanical working of the material.
    FloatArray ddsddt(ntens); // Variation of the stress increments with respect to the temperature.
    FloatArray drplde(ntens); // Variation of RPL with respect to the strain increments.
    double drpldt = 0.0; // Variation of RPL with respect to the temperature.

    /* An array containing the coordinates of this point. These are the current coordinates if geometric
     * nonlinearity is accounted for during the step (see “Procedures: overview,” Section 6.1.1); otherwise,
     * the array contains the original coordinates of the point */
    FloatArray coords;
    gp->giveElement()->computeGlobalCoordinates( coords, gp->giveNaturalCoordinates() );

    /* Rotation increment matrix. This matrix represents the increment of rigid body rotation of the basis
     * system in which the components of stress (STRESS) and strain (STRAN) are stored. It is provided so
     * that vector- or tensor-valued state variables can be rotated appropriately in this subroutine: stress and
     * strain components are already rotated by this amount before UMAT is called. This matrix is passed in
     * as a unit matrix for small-displacement analysis and for large-displacement analysis if the basis system
     * for the material point rotates with the material (as in a shell element or when a local orientation is used).*/
    FloatMatrix drot(3, 3);
    drot.beUnitMatrix();

    /* Characteristic element length, which is a typical length of a line across an element for a first-order
     * element; it is half of the same typical length for a second-order element. For beams and trusses it is a
     * characteristic length along the element axis. For membranes and shells it is a characteristic length in
     * the reference surface. For axisymmetric elements it is a characteristic length in the
     * plane only.
     * For cohesive elements it is equal to the constitutive thickness.*/
    double celent = 0.0; /// @todo Include the characteristic element length

    /* Array containing the deformation gradient at the beginning of the increment. See the discussion
     * regarding the availability of the deformation gradient for various element types. */
    FloatMatrix dfgrd0(3, 3);
    dfgrd0.beUnitMatrix();
    /* Array containing the deformation gradient at the end of the increment. The components of this array
     * are set to zero if nonlinear geometric effects are not included in the step definition associated with
     * this increment. See the discussion regarding the availability of the deformation gradient for various
     * element types. */
    FloatMatrix dfgrd1(3, 3);
    dfgrd1.beUnitMatrix();

    int noel = gp->giveElement()->giveNumber(); // Element number.
    int npt = 0; // Integration point number.

    int layer = 0; // Layer number (for composite shells and layered solids)..
    int kspt = 0; // Section point number within the current layer.
    int kstep = 0; // Step number.
    int kinc = 0; // Increment number.

    ///@todo No idea about these parameters
    double predef;
    double dpred;

    // Change to Abaqus's component order
    stress.changeComponentOrder();
    strain.changeComponentOrder();
    strainIncrement.changeComponentOrder();

    //    printf("stress oofem: "); stress.printYourself();

    OOFEM_LOG_DEBUG("AbaqusUserMaterial :: giveRealStressVector_3d - Calling subroutine");
    this->umat(stress.givePointer(), // STRESS
               state.givePointer(), // STATEV
               jacobian.givePointer(), // DDSDDE
               & sse, // SSE
               & spd, // SPD
               & scd, // SCD
               & rpl, // RPL
               ddsddt.givePointer(), // DDSDDT
               drplde.givePointer(), // DRPLDE
               & drpldt, // DRPLDT
               strain.givePointer(), // STRAN
               strainIncrement.givePointer(), // DSTRAN
               time, // TIME
               & dtime, // DTIME
               & temp, // TEMP
               & dtemp, // DTEMP
               & predef, // PREDEF
               & dpred, // DPRED
               this->cmname, // CMNAME
               & ndi, // NDI
               & nshr, // NSHR
               & ntens, // NTENS
               & numState, // NSTATV
               properties.givePointer(), // PROPS
               & numProperties, // NPROPS
               coords.givePointer(), // COORDS
               drot.givePointer(), // DROT
               & pnewdt, // PNEWDT
               & celent, // CELENT
               dfgrd0.givePointer(), // DFGRD0
               dfgrd1.givePointer(), // DFGRD1
               & noel, // NOEL
               & npt, // NPT
               & layer, // LAYER
               & kspt, // KSPT
               & kstep, // KSTEP
               & kinc); // KINC

    // Change to OOFEM's component order
    stress.changeComponentOrder();
    // subtracking the initial stress
    stress.subtract(initialStress);
    strain.changeComponentOrder();
    strainIncrement.changeComponentOrder();
    jacobian.changeComponentOrder();

    ms->letTempStrainVectorBe(reducedStrain);
    ms->letTempStressVectorBe(stress);
    ms->letTempStateVectorBe(state);
    ms->letTempTangentBe(jacobian);
    answer = stress;

    OOFEM_LOG_DEBUG("AbaqusUserMaterial :: giveRealStressVector - Calling subroutine was successful");
}
Example #19
0
void
MisesMat :: performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrain)
{
    MisesMatStatus *status = static_cast< MisesMatStatus * >( this->giveStatus(gp) );
    double kappa;
    FloatArray plStrain;
    FloatArray fullStress;
    // get the initial plastic strain and initial kappa from the status
    plStrain = status->givePlasticStrain();
    kappa = status->giveCumulativePlasticStrain();

    // === radial return algorithm ===
    if ( totalStrain.giveSize() == 1 ) {
        LinearElasticMaterial *lmat = this->giveLinearElasticMaterial();
        double E = lmat->give('E', gp);
        /*trial stress*/
        fullStress.resize(6);
        fullStress.at(1) = E * ( totalStrain.at(1) - plStrain.at(1) );
        double trialS = fabs(fullStress.at(1));
        /*yield function*/
        double yieldValue = trialS - (sig0 + H * kappa);
        // === radial return algorithm ===
        if ( yieldValue > 0 ) {
            double dKappa = yieldValue / ( H + E );
            kappa += dKappa;
            plStrain.at(1) += dKappa * signum( fullStress.at(1) );
            plStrain.at(2) -= 0.5 * dKappa * signum( fullStress.at(1) );
            plStrain.at(3) -= 0.5 * dKappa * signum( fullStress.at(1) );
            fullStress.at(1) -= dKappa * E * signum( fullStress.at(1) );
        }
    } else {
        // elastic predictor
        FloatArray elStrain = totalStrain;
        elStrain.subtract(plStrain);
        FloatArray elStrainDev;
        double elStrainVol;
        elStrainVol = computeDeviatoricVolumetricSplit(elStrainDev, elStrain);
        FloatArray trialStressDev;
        applyDeviatoricElasticStiffness(trialStressDev, elStrainDev, G);
        /**************************************************************/
        double trialStressVol = 3 * K * elStrainVol;
        /**************************************************************/

        // store the deviatoric and trial stress (reused by algorithmic stiffness)
        status->letTrialStressDevBe(trialStressDev);
        status->setTrialStressVol(trialStressVol);
        // check the yield condition at the trial state
        double trialS = computeStressNorm(trialStressDev);
        double yieldValue = sqrt(3./2.) * trialS - (sig0 + H * kappa);
        if ( yieldValue > 0. ) {
            // increment of cumulative plastic strain
            double dKappa = yieldValue / ( H + 3. * G );
            kappa += dKappa;
            FloatArray dPlStrain;
            // the following line is equivalent to multiplication by scaling matrix P
            applyDeviatoricElasticCompliance(dPlStrain, trialStressDev, 0.5);
            // increment of plastic strain
            plStrain.add(sqrt(3. / 2.) * dKappa / trialS, dPlStrain);
            // scaling of deviatoric trial stress
            trialStressDev.times(1. - sqrt(6.) * G * dKappa / trialS);
        }

        // assemble the stress from the elastically computed volumetric part
        // and scaled deviatoric part

        computeDeviatoricVolumetricSum(fullStress, trialStressDev, trialStressVol);
    }

    // store the effective stress in status
    status->letTempEffectiveStressBe(fullStress);
    // store the plastic strain and cumulative plastic strain
    status->letTempPlasticStrainBe(plStrain);
    status->setTempCumulativePlasticStrain(kappa);
}