void
LIBeam2dNL :: computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep)
{
    double dV;
    GaussPoint *gp;
    IntegrationRule *iRule;
    FloatArray stress;
    FloatMatrix A;
    Material *mat = this->giveMaterial();

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

    iRule = integrationRulesArray [ giveDefaultIntegrationRule() ];
    // assemble initial stress matrix
    for ( int i = 0; i < iRule->giveNumberOfIntegrationPoints(); i++ ) {
        gp = iRule->getIntegrationPoint(i);
        dV = this->computeVolumeAround(gp);
        stress = static_cast< StructuralMaterialStatus * >( mat->giveStatus(gp) )->giveStressVector();
        if ( stress.giveSize() ) {
            for ( int j = 1; j <= stress.giveSize(); j++ ) {
                // loop over each component of strain vector
                this->computeNLBMatrixAt(A, gp, j);
                if ( A.isNotEmpty() ) {
                    A.times(stress.at(j) * dV);
                    answer.add(A);
                }
            }
        }
    }
}
void
Quad1MindlinShell3D :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord)
{
    // We need to overload this for practical reasons (this 3d shell has all 9 dofs, but the shell part only cares for the first 8)
    // This elements adds an additional stiffness for the so called drilling dofs, meaning we need to work with all 9 components.
    FloatMatrix b, d;
    FloatArray n, strain, stress;
    FloatArray shellUnknowns(20), drillUnknowns(4), unknowns;

    this->computeVectorOf(EID_MomentumBalance, VM_Total, tStep, unknowns);
    // Split this for practical reasons into normal shell dofs and drilling dofs
    for ( int i = 0; i < 4; ++i ) {
        shellUnknowns(0 + i*5) = unknowns(0 + i*6);
        shellUnknowns(1 + i*5) = unknowns(1 + i*6);
        shellUnknowns(2 + i*5) = unknowns(2 + i*6);
        shellUnknowns(3 + i*5) = unknowns(3 + i*6);
        shellUnknowns(4 + i*5) = unknowns(4 + i*6);
        drillUnknowns(i) = unknowns(5 + i*6);
    }

    FloatArray shellForces(20), drillMoment(4);
    shellForces.zero();
    drillMoment.zero();
    StructuralCrossSection *cs = this->giveStructuralCrossSection();
    double drillCoeff = cs->give(CS_DrillingStiffness);

    IntegrationRule *iRule = integrationRulesArray [ 0 ];
    for ( int i = 0; i < iRule->giveNumberOfIntegrationPoints(); i++ ) {
        GaussPoint *gp = iRule->getIntegrationPoint(i);
        this->computeBmatrixAt(gp, b);
        double dV = this->computeVolumeAround(gp);

        if ( useUpdatedGpRecord ) {
            stress = static_cast< StructuralMaterialStatus * >( this->giveMaterial()->giveStatus(gp) )->giveStressVector();
        } else {
            strain.beProductOf(b, shellUnknowns);
            cs->giveRealStress_Shell(stress, gp, strain, tStep);
        }
        shellForces.plusProduct(b, stress, dV);

        // Drilling stiffness is here for improved numerical properties
        if (drillCoeff > 0.) {
            this->interp.evalN(n, *gp->giveCoordinates(), FEIVoidCellGeometry());
            for ( int j = 0; j < 4; j++) {
                n(j) -= 0.25;
            }
            double dtheta = n.dotProduct(drillUnknowns);
            drillMoment.add(drillCoeff * dV * dtheta, n); ///@todo Decide on how to alpha should be defined.
        }
    }

    answer.resize(24);
    answer.zero();
    answer.assemble(shellForces, this->shellOrdering);

    if (drillCoeff > 0.) {
        answer.assemble(drillMoment, this->drillOrdering);
    }
}
void
Quad1MindlinShell3D :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *stepN, ValueModeType mode)
{
    // Only gravity load
    double dV, density;
    GaussPoint *gp;
    FloatArray forceX, forceY, forceZ, glob_gravity, gravity, n;

    if ( ( forLoad->giveBCGeoType() != BodyLoadBGT ) || ( forLoad->giveBCValType() != ForceLoadBVT ) ) {
        _error("computeBodyLoadVectorAt: unknown load type");
    }

    // note: force is assumed to be in global coordinate system.
    forLoad->computeComponentArrayAt(glob_gravity, stepN, mode);
    // Transform the load into the local c.s.
    gravity.beProductOf(this->lcsMatrix, glob_gravity); ///@todo Check potential transpose here.

    if ( gravity.giveSize() ) {
        IntegrationRule *ir = integrationRulesArray [ 0 ];
        for ( int i = 0; i < ir->giveNumberOfIntegrationPoints(); ++i) {
            gp = ir->getIntegrationPoint(i);

            this->interp.evalN(n, *gp->giveCoordinates(), FEIVoidCellGeometry());
            dV = this->computeVolumeAround(gp) * this->giveCrossSection()->give(CS_Thickness);
            density = this->giveMaterial()->give('d', gp);

            forceX.add(density * gravity.at(1) * dV, n);
            forceY.add(density * gravity.at(2) * dV, n);
            forceZ.add(density * gravity.at(3) * dV, n);
        }

        answer.resize(24);
        answer.zero();

        answer.at(1)  = forceX.at(1);
        answer.at(2)  = forceY.at(1);
        answer.at(3)  = forceZ.at(1);

        answer.at(7)  = forceX.at(2);
        answer.at(8)  = forceY.at(2);
        answer.at(9)  = forceZ.at(2);

        answer.at(13) = forceX.at(3);
        answer.at(14) = forceY.at(3);
        answer.at(15) = forceZ.at(3);

        answer.at(19) = forceX.at(4);
        answer.at(20) = forceY.at(4);
        answer.at(21) = forceZ.at(4);

    } else {
        answer.resize(0);
    }
}
Beispiel #4
0
void
NonlocalMaterialExtensionInterface :: manipulateWeight(double &weight, GaussPoint *gp, GaussPoint *jGp)
{
    Element *ielem = jGp->giveElement();
    IntegrationRule *iRule = ielem->giveDefaultIntegrationRulePtr();

    if ( ielem->giveMaterial()->hasProperty(AVERAGING_TYPE, jGp) ) {
        if ( ielem->giveMaterial()->give(AVERAGING_TYPE, jGp) == 1 ) {
            weight = 1. / ( iRule->giveNumberOfIntegrationPoints() ); //assign the same weights over the whole element
        }
    }
}
void InterfaceElem1d :: drawScalar(oofegGraphicContext &context)
{
    int i, indx, result = 0;
    GaussPoint *gp;
    IntegrationRule *iRule = integrationRulesArray [ giveDefaultIntegrationRule() ];
    TimeStep *tStep = this->giveDomain()->giveEngngModel()->giveCurrentStep();
    FloatArray gcoord(3), v1;
    WCRec p [ 1 ];
    GraphicObj *go;
    double val [ 1 ];

    if ( !context.testElementGraphicActivity(this) ) {
        return;
    }

    if ( context.getInternalVarsDefGeoFlag() ) {
        double defScale = context.getDefScale();
        p [ 0 ].x = ( FPNum ) 0.5 * ( this->giveNode(1)->giveUpdatedCoordinate(1, tStep, defScale) +
                                      this->giveNode(2)->giveUpdatedCoordinate(1, tStep, defScale) );
        p [ 0 ].y = ( FPNum ) 0.5 * ( this->giveNode(1)->giveUpdatedCoordinate(2, tStep, defScale) +
                                      this->giveNode(2)->giveUpdatedCoordinate(2, tStep, defScale) );
        p [ 0 ].z = ( FPNum ) 0.5 * ( this->giveNode(1)->giveUpdatedCoordinate(3, tStep,  defScale) +
                                      this->giveNode(2)->giveUpdatedCoordinate(3, tStep, defScale) );
    } else {
        p [ 0 ].x = ( FPNum )( this->giveNode(1)->giveCoordinate(1) );
        p [ 0 ].y = ( FPNum )( this->giveNode(1)->giveCoordinate(2) );
        p [ 0 ].z = ( FPNum )( this->giveNode(1)->giveCoordinate(3) );
    }

    result += giveIPValue(v1, iRule->getIntegrationPoint(0), context.giveIntVarType(), tStep);


    for ( i = 0; i < iRule->giveNumberOfIntegrationPoints(); i++ ) {
        result = 0;
        gp = iRule->getIntegrationPoint(i);
        result += giveIPValue(v1, gp, context.giveIntVarType(), tStep);
        if ( result != 1 ) {
            continue;
        }

        indx = context.giveIntVarIndx();

        val [ 0 ] = v1.at(indx);
        context.updateFringeTableMinMax(val, 1);

        EASValsSetLayer(OOFEG_VARPLOT_PATTERN_LAYER);
        EASValsSetMType(FILLED_CIRCLE_MARKER);
        go = CreateMarkerWD3D(p, val [ 0 ]);
        EGWithMaskChangeAttributes(LAYER_MASK | FILL_MASK | MTYPE_MASK, go);
        EMAddGraphicsToModel(ESIModel(), go);
        //}
    }
}
Beispiel #6
0
void
CoupledFieldsElement :: computeStiffnessMatrixGen(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep, 
        void (*Nfunc)(GaussPoint*, FloatMatrix), 
        void (*Bfunc)(GaussPoint*, FloatMatrix),
        void (*NStiffness)(FloatMatrix, MatResponseMode, GaussPoint*, TimeStep*), 
        void (*BStiffness)(FloatMatrix, MatResponseMode, GaussPoint*, TimeStep*),
        double (*volumeAround)(GaussPoint*) )
{
    FloatMatrix B, DB, N, DN, D_B, D_N;

    IntegrationRule *iRule = this->giveIntegrationRule(0);
    bool matStiffSymmFlag = this->giveCrossSection()->isCharacteristicMtrxSymmetric(rMode);
    answer.resize(0,0);

    for ( int j = 0; j < iRule->giveNumberOfIntegrationPoints(); j++ ) {
        GaussPoint *gp = iRule->getIntegrationPoint(j);
        
        double dV = this->computeVolumeAround(gp);


        // compute int_V ( N^t * D_N * N )dV
        if ( NStiffness && Nfunc ) {
            Nfunc(gp, N);
            NStiffness(D_N, rMode, gp, tStep);
            DN.beProductOf(D_N, N);
            if ( matStiffSymmFlag ) {
                answer.plusProductSymmUpper(N, DN, dV);
            } else {
                answer.plusProductUnsym(N, DN, dV);
            }
        }


        // compute int_V ( B^t * D_B * B )dV
        if ( BStiffness && Bfunc ) {
            Bfunc(gp, B);
            BStiffness(D_B, rMode, gp, tStep);
            DB.beProductOf(D_B, B);
            if ( matStiffSymmFlag ) {
                answer.plusProductSymmUpper(B, DB, dV);
            } else {
                answer.plusProductUnsym(B, DB, dV);
            }    
        }

    }


    if ( matStiffSymmFlag ) {
        answer.symmetrized();
    }
}
void
ErrorCheckingExportModule :: writeCheck(Domain *domain, TimeStep *tStep)
{
    if ( tStep->isTheFirstStep() ) {
        std :: cout << "#%BEGIN_CHECK% tolerance 1.e-3\n";
    }

    for ( auto &dman : domain->giveDofManagers() ) {
        for ( Dof *dof: *dman ) {
            if ( dof->giveEqn() < 0 ) {
                continue;
            }
            std :: cout << "#NODE tStep " << tStep->giveNumber();
            std :: cout << " number " << dman->giveNumber();
            std :: cout << " dof " << dof->giveDofID();
            std :: cout << " unknown " << 'd';
            std :: cout << " value " << dof->giveUnknown(VM_Total, tStep);
            std :: cout << std :: endl;
        }
    }

    for ( auto &element : domain->giveElements() ) {
        IntegrationRule *iRule = element->giveDefaultIntegrationRulePtr();
        FloatArray ipval;
        for ( int ist: this->writeIST ) {
            for ( int gpnum = 0; gpnum < iRule->giveNumberOfIntegrationPoints(); ++gpnum ) {
                GaussPoint *gp = iRule->getIntegrationPoint(gpnum);
                element->giveIPValue(ipval, gp, (InternalStateType)ist, tStep);
                for ( int component = 1; component <= ipval.giveSize(); ++component ) {
                    std :: cout << "#ELEMENT tStep " << tStep->giveNumber();
                    std :: cout << " number " << element->giveNumber();
                    std :: cout << " gp " << gpnum+1;
                    std :: cout << " keyword " << ist; ///@note This writes IST number and not "stresses"
                    std :: cout << " component " << component;
                    std :: cout << " value " << ipval.at(component);
                    std :: cout << std :: endl;
                }
            }
        }
    }

    if ( !tStep->isNotTheLastStep() ) {
        std :: cout << "#%END_CHECK%" << std :: endl;
    }
}
void
Quad1MindlinShell3D :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep)
{
    // We need to overload this for practical reasons (this 3d shell has all 9 dofs, but the shell part only cares for the first 8)
    // This elements adds an additional stiffness for the so called drilling dofs, meaning we need to work with all 9 components.
    FloatMatrix d, b, db;
    FloatArray n;

    FloatMatrix shellStiffness(20, 20), drillStiffness(4, 4);
    shellStiffness.zero();
    drillStiffness.zero();
    double drillCoeff = this->giveStructuralCrossSection()->give(CS_DrillingStiffness);

    IntegrationRule *iRule = integrationRulesArray [ 0 ];
    for ( int i = 0; i < iRule->giveNumberOfIntegrationPoints(); i++ ) {
        GaussPoint *gp = iRule->getIntegrationPoint(i);
        this->computeBmatrixAt(gp, b);
        double dV = this->computeVolumeAround(gp);

        this->computeConstitutiveMatrixAt(d, rMode, gp, tStep);

        db.beProductOf(d, b);
        shellStiffness.plusProductSymmUpper(b, db, dV);

        // Drilling stiffness is here for improved numerical properties
        if (drillCoeff > 0.) {
            this->interp.evalN(n, *gp->giveCoordinates(), FEIVoidCellGeometry());
            for ( int j = 0; j < 4; j++) {
                n(j) -= 0.25;
            }
            drillStiffness.plusDyadSymmUpper(n, drillCoeff * dV);
        }
    }
    shellStiffness.symmetrized();

    answer.resize(24, 24);
    answer.zero();
    answer.assemble(shellStiffness, this->shellOrdering);

    if (drillCoeff > 0.) {
        drillStiffness.symmetrized();
        answer.assemble(drillStiffness, this->drillOrdering);
    }
}
void
Quad1MindlinShell3D :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep)
// Returns the lumped mass matrix of the receiver.
{
    double mass = 0.;

    IntegrationRule *ir = integrationRulesArray [ 0 ];
    for ( int i = 0; i < ir->giveNumberOfIntegrationPoints(); ++i) {
        GaussPoint *gp = ir->getIntegrationPoint(i);
        mass += this->computeVolumeAround(gp) * this->giveMaterial()->give('d', gp);
    }

    answer.resize(12, 12);
    answer.zero();
    for ( int i = 0; i < 4; i++ ) {
        answer(i*6 + 0, i*6 + 0) = mass*0.25;
        answer(i*6 + 1, i*6 + 1) = mass*0.25;
        answer(i*6 + 2, i*6 + 2) = mass*0.25;
    }
}
Beispiel #10
0
void
CoupledFieldsElement :: giveInternalForcesVectorGen(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord, 
    void (*Nfunc)(GaussPoint*, FloatMatrix), void (*Bfunc)(GaussPoint*, FloatMatrix, int, int), //(GaussPoint*, FloatMatrix)
    void (*NStressFunc)(GaussPoint*, FloatArray), void (*BStressFunc)(GaussPoint*, FloatArray),
    double (*dVFunc)(GaussPoint*))
{
    // General implementation of internal forces that computes
    // f = sum_gp( N^T*GenStress_N + B^T*GenStress_B ) * dV
    
    IntegrationRule *iRule = this->giveIntegrationRule(0);
    FloatArray NStress, BStress, vGenStress, NS, BS;
    FloatMatrix N, B;

    for ( int j = 0; j < this->giveNumberOfIntegrationRules(); j++ ) {
        IntegrationRule *iRule = this->giveIntegrationRule(j);

        for ( int i = 0; i < iRule->giveNumberOfIntegrationPoints(); i++ ) {
            GaussPoint *gp = iRule->getIntegrationPoint(i);
    
            double dV  = this->computeVolumeAround(gp);
            
            // compute generalized stress measures
            if ( NStressFunc && Nfunc ) {
                Nfunc(gp, N);
                NStressFunc(gp, NStress);
                NS.beTProductOf(N, NStress);
                answer.add(dV, NS);
            }

            if ( BStressFunc && Bfunc ) {
                Bfunc(gp, B, 1, 3);
                BStressFunc(gp, BStress);
                BS.beTProductOf(B, BStress);
                answer.add(dV, BS);
            }

            
        }
    }
}
void
Quad10_2D_SUPG :: computeMassDeltaTerm(FloatMatrix &answer, TimeStep *atTime)
{
    FloatMatrix n, b;
    double dV, rho;
    int undofs = this->computeNumberOfDofs(EID_MomentumBalance);
    GaussPoint *gp;

    answer.resize(undofs, undofs);
    answer.zero();
    IntegrationRule *iRule = this->integrationRulesArray [ 1 ];
    /* mtrx for computing t_supg, norm of this mtrx is computed */
    for ( int k = 0; k < iRule->giveNumberOfIntegrationPoints(); k++ ) {
        gp = iRule->getIntegrationPoint(k);
        this->computeNuMatrix(n, gp);
        this->computeUDotGradUMatrix(b, gp, atTime);
        dV  = this->computeVolumeAround(gp);
        rho = this->giveMaterial()->give('d', gp);

        answer.plusProductUnsym(b, n, rho * dV);
    }
}
void
Quad10_2D_SUPG :: computeAdvectionTerm(FloatMatrix &answer, TimeStep *atTime)
{
    FloatMatrix n, b;
    double dV, rho;
    int undofs = this->computeNumberOfDofs(EID_MomentumBalance);
    GaussPoint *gp;

    answer.resize(undofs, undofs);
    answer.zero();

    IntegrationRule *iRule = this->integrationRulesArray [ 1 ];
    /* consistent part + supg stabilization term */
    for ( int k = 0; k < iRule->giveNumberOfIntegrationPoints(); k++ ) {
        gp = iRule->getIntegrationPoint(k);
        this->computeNuMatrix(n, gp);
        this->computeUDotGradUMatrix(b, gp, atTime);
        dV  = this->computeVolumeAround(gp);
        rho = this->giveMaterial()->give('d', gp);
        answer.plusProductUnsym(n, b, rho * dV);
    }
}
void
TR_SHELL01 :: printOutputAt(FILE *file, TimeStep *tStep)
// Performs end-of-step operations.
{
    FloatArray v, aux;
    GaussPoint *gp, *membraneGP;
    IntegrationRule *iRule = this->giveDefaultIntegrationRulePtr();
    fprintf( file, "element %d (%8d) :\n", this->giveLabel(), this->giveNumber() );

    for ( int i = 0; i < iRule->giveNumberOfIntegrationPoints(); i++ ) {
      gp  = iRule->getIntegrationPoint(i);
      fprintf(file, "  GP %2d.%-2d :", iRule->giveNumber(), gp->giveNumber());
      membraneGP = membrane->giveDefaultIntegrationRulePtr()->getIntegrationPoint(gp->giveNumber()-1);
      // Strain - Curvature
      plate->giveIPValue(v, gp, IST_ShellStrainCurvatureTensor, tStep);
      membrane->giveIPValue(aux, membraneGP, IST_ShellStrainCurvatureTensor, tStep);
      v.add(aux);

      fprintf(file, "  strains ");
      fprintf( file,
            " % .4e % .4e % .4e % .4e % .4e % .4e % .4e % .4e % .4e % .4e % .4e % .4e ",
            v.at(1), v.at(2), v.at(3),  2. * v.at(4), 2. * v.at(5), 2. * v.at(6),
            v.at(7), v.at(8), v.at(9),  2. * v.at(10), 2. * v.at(11), 2. * v.at(12) );
      
      // Strain - Curvature
      plate->giveIPValue(v, gp, IST_ShellForceMomentumTensor, tStep);
      membrane->giveIPValue(aux, membraneGP, IST_ShellForceMomentumTensor, tStep);
      v.add(aux);
      
      fprintf(file, "\n              stresses");
      fprintf( file,
            " % .4e % .4e % .4e % .4e % .4e % .4e % .4e % .4e % .4e % .4e % .4e % .4e ",
            v.at(1), v.at(2), v.at(3),  v.at(4), v.at(5), v.at(6),
            v.at(7), v.at(8), v.at(9),  v.at(10), v.at(11), v.at(12) );
      
      fprintf(file, "\n");
    }
}
void
Lattice2d_mt :: updateInternalState(TimeStep *stepN)
// Updates the receiver at end of step.
{
    int i, j;
    IntegrationRule *iRule;
    FloatArray f, r;
    FloatMatrix n;
    TransportMaterial *mat = ( ( TransportMaterial * ) this->giveMaterial() );
    GaussPoint *gp;

    // force updating ip values
    for ( i = 0; i < numberOfIntegrationRules; i++ ) {
        iRule = integrationRulesArray [ i ];
        for ( j = 0; j < iRule->giveNumberOfIntegrationPoints(); j++ ) {
            gp = iRule->getIntegrationPoint(j);
            this->computeNmatrixAt( n, *gp->giveCoordinates() );
            this->computeVectorOf(EID_ConservationEquation, VM_Total, stepN, r);
            f.beProductOf(n, r);
            mat->updateInternalState(f, gp, stepN);
        }
    }
}
void
Quad10_2D_SUPG :: computeLSICTerm(FloatMatrix &answer, TimeStep *atTime)
{
    int undofs = this->computeNumberOfDofs(EID_MomentumBalance);
    double dV, rho;
    GaussPoint *gp;
    FloatMatrix b;

    answer.resize(undofs, undofs);
    answer.zero();

    IntegrationRule *iRule = this->integrationRulesArray [ 1 ];
    for ( int k = 0; k < iRule->giveNumberOfIntegrationPoints(); k++ ) {
        gp = iRule->getIntegrationPoint(k);
        dV  = this->computeVolumeAround(gp);
        rho = this->giveMaterial()->give('d', gp);
        this->computeDivUMatrix(b, gp);

        answer.plusProductSymmUpper(b, b, dV * rho);
    }

    answer.symmetrized();
}
void
Quad10_2D_SUPG :: computeMassEpsilonTerm(FloatMatrix &answer, TimeStep *atTime)
{
    // to compute t_pspg
    int pndofs = this->computeNumberOfDofs(EID_ConservationEquation);
    int undofs = this->computeNumberOfDofs(EID_MomentumBalance);
    double dV;
    FloatMatrix g, n;
    GaussPoint *gp;

    answer.resize(pndofs, undofs);
    answer.zero();

    IntegrationRule *iRule = this->integrationRulesArray [ 1 ];

    for ( int k = 0; k < iRule->giveNumberOfIntegrationPoints(); k++ ) {
        gp = iRule->getIntegrationPoint(k);
        this->computeGradPMatrix(g, gp);
        this->computeNuMatrix(n, gp);
        dV  = this->computeVolumeAround(gp);

        answer.plusProductUnsym(g, n, dV);
    }
}
void
Quad1MindlinShell3D :: computeSurfaceLoadVectorAt(FloatArray &answer, Load *load,
                                                int iSurf, TimeStep *tStep, ValueModeType mode)
{
    BoundaryLoad *surfLoad = static_cast< BoundaryLoad * >(load);
    if ( dynamic_cast< ConstantPressureLoad * >(surfLoad) ) { // Just checking the type of b.c.
        // EXPERIMENTAL CODE:
        IntegrationRule *iRule;
        FloatArray n, gcoords, pressure;

        answer.resize( 24 );
        answer.zero();

        //int approxOrder = surfLoad->giveApproxOrder() + this->giveApproxOrder();

        iRule = this->integrationRulesArray[ 0 ];
        for ( int i = 0; i < iRule->giveNumberOfIntegrationPoints(); i++ ) {
            GaussPoint *gp = iRule->getIntegrationPoint(i);
            double dV = this->computeVolumeAround(gp);
            this->interp.evalN(n, *gp->giveCoordinates(), FEIVoidCellGeometry());
            this->interp.local2global(gcoords, *gp->giveCoordinates(), FEIElementGeometryWrapper(this));
            surfLoad->computeValueAt(pressure, tStep, gcoords, mode);

            answer.at( 3) += n.at(1) * pressure.at(1) * dV;
            answer.at( 9) += n.at(2) * pressure.at(1) * dV;
            answer.at(15) += n.at(3) * pressure.at(1) * dV;
            answer.at(21) += n.at(4) * pressure.at(1) * dV;
        }
        // Second surface is the outside;
        if ( iSurf == 2 ) {
            answer.negated();
        }
    } else {
        OOFEM_ERROR("Quad1MindlinShell3D only supports constant pressure boundary load.");
    }
}
Beispiel #18
0
void
tet21ghostsolid :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep)
{

    IntegrationRule *iRule = integrationRulesArray [ giveDefaultIntegrationRule() ];
#ifdef __FM_MODULE
    FluidDynamicMaterial *fluidMaterial = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial();
#endif

    FloatMatrix Kf, G, Kx, D, B, Ed, EdB, dNx;
    FloatArray Nlin, dNv;

    for (int j = 0; j<iRule->giveNumberOfIntegrationPoints(); j++) {
        GaussPoint *gp = iRule->getIntegrationPoint(j);

        double detJ = fabs( ( this->interpolation.giveTransformationJacobian( * gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ) );
        double weight = gp->giveWeight();

        this->interpolation.evaldNdx( dNx, * gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
        this->interpolation_lin.evalN( Nlin, * gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );

        dNv.resize(30); // dNv = [dN1/dx dN1/dy dN1/dz dN2/dx dN2/dy dN2/dz ... dN10/dz]

        for (int k = 0; k<dNx.giveNumberOfRows(); k++) {
            dNv.at(k*3+1) = dNx.at(k+1,1);
            dNv.at(k*3+2) = dNx.at(k+1,2);
            dNv.at(k*3+3) = dNx.at(k+1,3);
        }

        if (nlGeometry == 0) {

            this->computeBmatrixAt(gp, B);

            // Fluid part
            gp->setMaterialMode(_3dFlow);
#ifdef __FM_MODULE
            fluidMaterial->giveDeviatoricStiffnessMatrix(Ed, TangentStiffness, gp, tStep);
#else
            OOFEM_ERROR("Fluid module missing\n");
#endif
            gp->setMaterialMode(_3dMat);

            EdB.beProductOf(Ed, B);
            Kf.plusProductSymmUpper(B, EdB, detJ*weight);

            // Ghost solid part
            EdB.beProductOf(Dghost, B);
            Kx.plusProductSymmUpper(B, EdB, detJ*weight);

            // Incompressibility part
            G.plusDyadUnsym(dNv, Nlin, -detJ*weight);

        } else {
            OOFEM_ERROR ("No support for large deformations yet!");
        }

    }

    FloatMatrix GT;

    GT.beTranspositionOf(G);
    //GTdeltat.beTranspositionOf(G);
    //GTdeltat.times(deltat);
    Kf.symmetrized();
    Kx.symmetrized();
    //    Kf.printYourself();
    //    G.printYourself();
    //    GT.printYourself();
    //    Kx.printYourself();

    answer.resize(64, 64);
    answer.zero();
#define USEUNCOUPLED 0

#if USEUNCOUPLED == 1
    // Totaly uncoupled
    answer.assemble(Kf, momentum_ordering, momentum_ordering);
    answer.assemble(G, momentum_ordering, conservation_ordering);
    answer.assemble(GT, conservation_ordering, momentum_ordering);
    answer.assemble(Kx, ghostdisplacement_ordering, ghostdisplacement_ordering);
#else
    answer.assemble(Kf, ghostdisplacement_ordering, ghostdisplacement_ordering);
    answer.assemble(Kf, ghostdisplacement_ordering, momentum_ordering);
    answer.assemble(G, ghostdisplacement_ordering, conservation_ordering);
    answer.assemble(GT, conservation_ordering, ghostdisplacement_ordering);
    answer.assemble(GT, conservation_ordering, momentum_ordering);
    answer.assemble(Kx, momentum_ordering, ghostdisplacement_ordering);
#endif

    //answer.printYourself();

}
Beispiel #19
0
void
tet21ghostsolid :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord)
{

    IntegrationRule *iRule = integrationRulesArray [ giveDefaultIntegrationRule() ];
#ifdef __FM_MODULE
    FluidDynamicMaterial *fluidMaterial = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial();
#endif

    FloatMatrix Kf, G, Kx, B, Ed, dNx;
    FloatArray Strain, Stress, Nlin, dNv, a, aVelocity, aPressure, aGhostDisplacement, fluidStress, epsf;
    FloatArray momentum, conservation, auxstress;
    double pressure, epsvol;

    this->computeVectorOf( VM_Total, tStep, a);
    if (!tStep->isTheFirstStep()) {
        // a.printYourself();
    }

    aVelocity.beSubArrayOf(a, momentum_ordering);
    aPressure.beSubArrayOf(a, conservation_ordering);
    aGhostDisplacement.beSubArrayOf(a, ghostdisplacement_ordering);

    for (int j = 0; j<iRule->giveNumberOfIntegrationPoints(); j++) {
        GaussPoint *gp = iRule->getIntegrationPoint(j);

        double detJ = fabs( ( this->interpolation.giveTransformationJacobian( * gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ) );
        double weight = gp->giveWeight();

        this->interpolation.evaldNdx( dNx, * gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
        this->interpolation_lin.evalN( Nlin, * gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );

        dNv.resize(30);
        for (int k = 0; k<dNx.giveNumberOfColumns(); k++) {
            dNv.at(k*3+1) = dNx.at(1,k+1);
            dNv.at(k*3+2) = dNx.at(2,k+1);
            dNv.at(k*3+3) = dNx.at(3,k+1);
        }

        if (nlGeometry == 0) {

            this->computeBmatrixAt(gp, B);
            epsf.beProductOf(B, aVelocity);
            pressure = Nlin.dotProduct(aPressure);

            // Fluid part
            gp->setMaterialMode(_3dFlow);
#ifdef __FM_MODULE
            fluidMaterial->computeDeviatoricStressVector(fluidStress, epsvol, gp, epsf, pressure, tStep);
#else
            OOFEM_ERROR("Missing FM module");
#endif
            gp->setMaterialMode(_3dMat);

            momentum.plusProduct(B, fluidStress, detJ*weight);
            momentum.add(-pressure * detJ * weight, dNv);
            conservation.add(epsvol * detJ * weight, Nlin);

            // Ghost solid part
            Strain.beProductOf(B, aGhostDisplacement);
            Stress.beProductOf(Dghost, Strain);
            auxstress.plusProduct(B, Stress, detJ * weight);

        } else {
            OOFEM_ERROR("No support for large deformations yet!");
        }

    }
    answer.resize(64);
    answer.zero();

#if USEUNCOUPLED == 1
    // Totaly uncoupled
    answer.assemble(momentum, momentum_ordering);
    answer.assemble(conservation, conservation_ordering);
    answer.assemble(auxstress, ghostdisplacement_ordering);
#else
    answer.assemble(momentum, ghostdisplacement_ordering);
    answer.assemble(conservation, conservation_ordering);
    answer.assemble(auxstress, momentum_ordering);
#endif

    // Test linear

    /*    if (this->giveNumber() == 364) {
        FloatMatrix K;
        FloatArray ans;
        this->computeStiffnessMatrix(K, TangentStiffness, tStep);
        ans.beProductOf(K, a);
        ans.printYourself();
        answer.printYourself();
    } */


}
Beispiel #20
0
void
tet21ghostsolid :: computeLoadVector(FloatArray &answer, Load *load, CharType type, ValueModeType mode, TimeStep *tStep)
{

    answer.resize(64);
    answer.zero();

    if ( type != ExternalForcesVector ) {
        answer.resize(0);
        return;
    }

#ifdef __FM_MODULE
    FluidDynamicMaterial *mat = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial();
#endif
    IntegrationRule *iRule = this->integrationRulesArray [ 0 ];
    FloatArray N, gVector, temparray(30), dNv, u, inc, u_prev, vload;
    FloatMatrix dNx, G;

    load->computeComponentArrayAt(gVector, tStep, VM_Total);
    temparray.zero();

    vload.resize(4);
    vload.zero();

    this->giveDisplacementsIncrementData(u_prev, u, inc, tStep);

    for ( int k = 0; k < iRule->giveNumberOfIntegrationPoints(); k++ ) {
        GaussPoint *gp = iRule->getIntegrationPoint(k);
        FloatArray *lcoords = gp->giveNaturalCoordinates();

        double detJ = fabs( this->interpolation.giveTransformationJacobian( * lcoords, FEIElementGeometryWrapper(this) ) );
        double dA = detJ * gp->giveWeight();

        // Body load
        if ( gVector.giveSize() ) {
#ifdef __FM_MODULE
            double rho = mat->give('d', gp);
#else
            OOFEM_ERROR("Missing FM module");
            double rho = 1.0;
#endif
            this->interpolation.evalN( N, * lcoords, FEIElementGeometryWrapper(this) );

            for ( int j = 0; j < N.giveSize(); j++ ) {
                temparray(3 * j + 0) += N(j) * rho * gVector(0) * dA;
                temparray(3 * j + 1) += N(j) * rho * gVector(1) * dA;
                temparray(3 * j + 2) += N(j) * rho * gVector(2) * dA;
            }
        }

        // "load" from previous step
        this->interpolation.evaldNdx( dNx, * gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
        this->interpolation_lin.evalN( N, * gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );

        dNv.resize(30);
        for (int k = 0; k<dNx.giveNumberOfColumns(); k++) {
            dNv.at(k*3+1) = dNx.at(1,k+1);
            dNv.at(k*3+2) = dNx.at(2,k+1);
            dNv.at(k*3+3) = dNx.at(3,k+1);
        }

        G.plusDyadUnsym(N, dNv, dA);
        FloatMatrix GT;
        GT.beTranspositionOf(G);

        vload.plusProduct(GT, u_prev, -0.0 );
        //vload.printYourself();

    }

#if USEUNCOUPLED == 1
    // Totaly uncoupled
    answer.assemble(temparray, this->momentum_ordering);
#else
    answer.assemble(temparray, this->ghostdisplacement_ordering);
    answer.assemble(vload, this->conservation_ordering);
#endif



    // answer.printYourself();
}
Beispiel #21
0
void
MatlabExportModule :: doOutputIntegrationPointFields(TimeStep *tStep,    FILE *FID)
{

    int domainIndex = 1;
    Domain *domain  = emodel->giveDomain( domainIndex );

    // Output header
    fprintf( FID, "\n %%%% Export of internal variables in integration points \n\n" );
    fprintf( FID, "\n %% for interpretation of internal var. numbers see internalstatetype.h\n");


    int numVars = this->internalVarsToExport.giveSize();
    // Output the internalVarsToExport-list
    fprintf( FID, "\tIntegrationPointFields.InternalVarsToExport = [" );
    for ( int i = 1; i <= numVars; i++ ) {
        fprintf( FID, "%i ", this->internalVarsToExport.at(i) );
    }
    fprintf( FID, "];\n" );




    if ( this->IPFieldsElSet > 0 ) {
        Set *set = domain->giveSet( this->IPFieldsElSet );
        elList = set->giveElementList();
    }


    FloatArray valueArray;

    int nelem = this->elList.giveSize();

    fprintf( FID, "\tIntegrationPointFields.Elements = cell(%i,1); \n", nelem );

    for ( int ielem = 1; ielem <= nelem; ielem++ ) {
        Element *el = domain->giveElement( this->elList.at(ielem) );
        fprintf( FID, "\tIntegrationPointFields.Elements{%i}.elementNumber = %i; \n", ielem, el->giveNumber());

        int numIntRules = el->giveNumberOfIntegrationRules();
        fprintf( FID, "\tIntegrationPointFields.Elements{%i}.integrationRule = cell(%i,1); \n", ielem, numIntRules);
        for ( int i = 1; i <= numIntRules; i++ ) {
            IntegrationRule *iRule = el->giveIntegrationRule(i-1);

            fprintf( FID, "\tIntegrationPointFields.Elements{%i}.integrationRule{%i}.ip = cell(%i,1); \n ",
                     ielem, i, iRule->giveNumberOfIntegrationPoints() );

            // Loop over integration points
            for ( GaussPoint *ip: *iRule ) {

                double weight = ip->giveWeight();

                fprintf( FID, "\tIntegrationPointFields.Elements{%i}.integrationRule{%i}.ip{%i}.ipWeight = %e; \n ",
                         ielem, i, ip->giveNumber(), weight);


                // export Gauss point coordinates
                fprintf( FID, "\tIntegrationPointFields.Elements{%i}.integrationRule{%i}.ip{%i}.coords = [",
                         ielem, i, ip->giveNumber());

                FloatArray coords;
                el->computeGlobalCoordinates( coords, ip->giveNaturalCoordinates() );
                for ( int ic = 1; ic <= coords.giveSize(); ic++ ) {
                    fprintf( FID, "%e ", coords.at(ic) );
                }
                fprintf( FID, "]; \n" );

                // export internal variables
                fprintf( FID, "\tIntegrationPointFields.Elements{%i}.integrationRule{%i}.ip{%i}.valArray = cell(%i,1); \n",
                         ielem, i, ip->giveNumber(), numVars);

                for ( int iv = 1; iv <= numVars; iv++ ) {
                    fprintf( FID, "\tIntegrationPointFields.Elements{%i}.integrationRule{%i}.ip{%i}.valArray{%i} = [",
                             ielem, i, ip->giveNumber(), iv);
                    InternalStateType vartype = ( InternalStateType ) this->internalVarsToExport.at(iv);
                    el->giveIPValue(valueArray, ip, vartype, tStep);
                    int nv = valueArray.giveSize();
                    for ( int ic = 1; ic <= nv; ic++ ) {
                        fprintf( FID, "%.6e ", valueArray.at(ic) );
                    }
                    fprintf( FID, "]; \n" );
                }
            }

        }
    }

}
void
Quad10_2D_SUPG :: updateStabilizationCoeffs(TimeStep *atTime)
{
    double Re, norm_un, mu, mu_min, nu, norm_N, norm_N_d, norm_M_d, norm_LSIC, norm_G_c, norm_M_c, norm_N_c, t_p1, t_p2, t_p3, t_s1, t_s2, t_s3, rho;
    FloatMatrix dn, N, N_d, M_d, LSIC, G_c, M_c, N_c;
    FloatArray dN, s, lcoords_nodes, u, lcn, dn_a(2), n, u1(8), u2(8);
    GaussPoint *gp;
    IntegrationRule *iRule;


    iRule = integrationRulesArray [ 1 ];
    mu_min = 1;
    rho = this->giveMaterial()->give('d', integrationRulesArray [ 0 ]->getIntegrationPoint(0));
    for ( int j = 0; j < iRule->giveNumberOfIntegrationPoints(); j++ ) {
        gp = iRule->getIntegrationPoint(j);
        mu = static_cast< FluidDynamicMaterial* >(this->giveMaterial())->giveEffectiveViscosity(gp, atTime);
        if ( mu_min > mu ) {
            mu_min = mu;
        }

        nu = mu_min / rho;
    }

    nu = mu_min / rho;

    //this->computeVectorOf(EID_MomentumBalance, VM_Total, atTime->givePreviousStep(), un);
    this->computeVectorOf(EID_MomentumBalance, VM_Total, atTime, u);

    norm_un = u.computeNorm();

    this->computeAdvectionTerm(N, atTime);
    this->computeAdvectionDeltaTerm(N_d, atTime);
    this->computeMassDeltaTerm(M_d, atTime);
    this->computeLSICTerm(LSIC, atTime);
    this->computeLinearAdvectionTerm_MC(G_c, atTime);
    this->computeMassEpsilonTerm(M_c, atTime);
    this->computeAdvectionEpsilonTerm(N_c, atTime);


    norm_N = N.computeFrobeniusNorm();
    norm_N_d = N_d.computeFrobeniusNorm();
    norm_M_d = M_d.computeFrobeniusNorm();
    norm_LSIC = LSIC.computeFrobeniusNorm();
    norm_G_c = G_c.computeFrobeniusNorm();
    norm_M_c = M_c.computeFrobeniusNorm();
    norm_N_c = N_c.computeFrobeniusNorm();

    if ( ( norm_N == 0 ) || ( norm_N_d == 0 ) || ( norm_M_d == 0 ) ) {
        t_supg = 0;
    } else {
        Re = ( norm_un / nu ) * ( norm_N / norm_N_d );

        t_s1 = norm_N / norm_N_d;

        t_s2 = atTime->giveTimeIncrement() * ( norm_N / norm_M_d ) * 0.5;

        t_s3 = t_s1 * Re;

        t_supg =  1. / sqrt( 1. / ( t_s1 * t_s1 ) + 1. / ( t_s2 * t_s2 ) + 1. / ( t_s3 * t_s3 ) );
        // t_supg = 0;
    }

    if ( norm_LSIC == 0 ) {
        t_lsic = 0;
    } else {
        t_lsic = norm_N / norm_LSIC;

        // t_lsic = 0;
    }

    if ( ( norm_G_c == 0 ) || ( norm_N_c == 0 ) || ( norm_M_c == 0 ) ) {
        t_pspg = 0;
    } else {
        Re = ( norm_un / nu ) * ( norm_N / norm_N_d );

        t_p1 = norm_G_c / norm_N_c;

        t_p2 = atTime->giveTimeIncrement() * ( norm_G_c / norm_M_c ) * 0.5;

        t_p3 = t_p1 * Re;

        t_pspg =  1. / sqrt( 1. / ( t_p1 * t_p1 ) + 1. / ( t_p2 * t_p2 ) + 1. / ( t_p3 * t_p3 ) );
        // t_pspg = 0;
    }

    //t_pspg = 0;
}
Beispiel #23
0
std::vector<std::unique_ptr<EnrichmentItem>> NCPrincipalStress::nucleateEnrichmentItems() {


	SpatialLocalizer *octree = this->mpDomain->giveSpatialLocalizer();
	XfemManager *xMan = mpDomain->giveXfemManager();

	std::vector<std::unique_ptr<EnrichmentItem>> eiList;

	// Center coordinates of newly inserted cracks
	std::vector<FloatArray> center_coord_inserted_cracks;

	// Loop over all elements and all bulk GP.
	for(auto &el : mpDomain->giveElements() ) {

		int numIR = el->giveNumberOfIntegrationRules();

		int csNum = el->giveCrossSection()->giveNumber();

		if(csNum == mCrossSectionInd || true) {

			for(int irInd = 0; irInd < numIR; irInd++) {
				IntegrationRule *ir = el->giveIntegrationRule(irInd);



				int numGP = ir->giveNumberOfIntegrationPoints();

				for(int gpInd = 0; gpInd < numGP; gpInd++) {
					GaussPoint *gp = ir->getIntegrationPoint(gpInd);

	//				int csNum = gp->giveCrossSection()->giveNumber();
	//				printf("csNum: %d\n", csNum);


						StructuralMaterialStatus *ms = dynamic_cast<StructuralMaterialStatus*>(gp->giveMaterialStatus());

						if(ms != NULL) {

							const FloatArray &stress = ms->giveTempStressVector();

							FloatArray principalVals;
							FloatMatrix principalDirs;
							StructuralMaterial::computePrincipalValDir(principalVals, principalDirs, stress, principal_stress);

							if(principalVals[0] > mStressThreshold) {



		//						printf("\nFound GP with stress above threshold.\n");
		//						printf("principalVals: "); principalVals.printYourself();

								FloatArray crackNormal;
								crackNormal.beColumnOf(principalDirs, 1);
		//						printf("crackNormal: "); crackNormal.printYourself();

								FloatArray crackTangent = {-crackNormal(1), crackNormal(0)};
								crackTangent.normalize();
		//						printf("crackTangent: "); crackTangent.printYourself();



								// Create geometry
								FloatArray pc = {gp->giveGlobalCoordinates()(0), gp->giveGlobalCoordinates()(1)};
		//						printf("Global coord: "); pc.printYourself();


								FloatArray ps = pc;
								ps.add(-0.5*mInitialCrackLength, crackTangent);

								FloatArray pe = pc;
								pe.add(0.5*mInitialCrackLength, crackTangent);

								if(mCutOneEl) {
									// If desired, ensure that the crack cuts exactly one element.
									Line line(ps, pe);
									std::vector<FloatArray> intersecPoints;
		//							line.computeIntersectionPoints(el.get(), intersecPoints);

									for ( int i = 1; i <= el->giveNumberOfDofManagers(); i++ ) {
//										int n1 = i;
//										int n2 = 0;
//										if ( i < el->giveNumberOfDofManagers() ) {
//											n2 = i + 1;
//										} else {
//											n2 = 1;
//										}

		//						        const FloatArray &p1 = *(el->giveDofManager(n1)->giveCoordinates());
		//						        const FloatArray &p2 = *(el->giveDofManager(n2)->giveCoordinates());


									}

		//							printf("intersecPoints.size(): %lu\n", intersecPoints.size());

									if(intersecPoints.size() == 2) {
										ps = std::move(intersecPoints[0]);
										pe = std::move(intersecPoints[1]);
									}
									else {
										OOFEM_ERROR("intersecPoints.size() != 2")
									}
								}

								FloatArray points = {ps(0), ps(1), pc(0), pc(1), pe(0), pe(1)};

		//						double diffX = 0.5*(ps(0) + pe(0)) - pc(0);
		//						printf("diffX: %e\n", diffX);

		//						double diffY = 0.5*(ps(1) + pe(1)) - pc(1);
		//						printf("diffY: %e\n", diffY);


								// TODO: Check if nucleation is allowed, by checking for already existing cracks close to the GP.
								// Idea: Nucleation is not allowed if we are within an enriched element. In this way, branching is not
								// completely prohibited, but we avoid initiating multiple similar cracks.
								bool insertionAllowed = true;

								Element *el_s = octree->giveElementContainingPoint(ps);
								if(el_s) {
									if( xMan->isElementEnriched(el_s) ) {
										insertionAllowed = false;
									}
								}

								Element *el_c = octree->giveElementContainingPoint(pc);
								if(el_c) {
									if( xMan->isElementEnriched(el_c) ) {
										insertionAllowed = false;
									}
								}

								Element *el_e = octree->giveElementContainingPoint(pe);
								if(el_e) {
									if( xMan->isElementEnriched(el_e) ) {
										insertionAllowed = false;
									}
								}

								for(const auto &x: center_coord_inserted_cracks) {
									if( x.distance(pc) <  2.0*mInitialCrackLength) {
										insertionAllowed = false;
										break;
										printf("Preventing insertion.\n");
									}
								}

								if(insertionAllowed) {
									int n = xMan->giveNumberOfEnrichmentItems() + 1;
									std::unique_ptr<Crack> crack = std::make_unique<Crack>(n, xMan, mpDomain);


									// Geometry
									std::unique_ptr<BasicGeometry> geom = std::make_unique<PolygonLine>();
									geom->insertVertexBack(ps);
									geom->insertVertexBack(pc);
									geom->insertVertexBack(pe);
									crack->setGeometry(std::move(geom));

									// Enrichment function
									EnrichmentFunction *ef = new HeavisideFunction(1, mpDomain);
									crack->setEnrichmentFunction(ef);

									// Enrichment fronts
//									EnrichmentFront *efStart = new EnrFrontLinearBranchFuncOneEl();
									EnrichmentFront *efStart = new EnrFrontCohesiveBranchFuncOneEl();
									crack->setEnrichmentFrontStart(efStart);

//									EnrichmentFront *efEnd = new EnrFrontLinearBranchFuncOneEl();
									EnrichmentFront *efEnd = new EnrFrontCohesiveBranchFuncOneEl();
									crack->setEnrichmentFrontEnd(efEnd);




									///////////////////////////////////////
									// Propagation law

									// Options
			//					    double radius = 0.5*mInitialCrackLength, angleInc = 10.0, incrementLength = 0.5*mInitialCrackLength, hoopStressThreshold = 0.0;
			//					    bool useRadialBasisFunc = true;

			//						PLHoopStressCirc *pl = new PLHoopStressCirc();
			//						pl->setRadius(radius);
			//						pl->setAngleInc(angleInc);
			//						pl->setIncrementLength(incrementLength);
			//						pl->setHoopStressThreshold(hoopStressThreshold);
			//						pl->setUseRadialBasisFunc(useRadialBasisFunc);

			//					    PLDoNothing *pl = new PLDoNothing();

									PLMaterialForce *pl = new PLMaterialForce();
									pl->setRadius(mMatForceRadius);
									pl->setIncrementLength(mIncrementLength);
//									pl->setIncrementLength(0.25);
//									pl->setCrackPropThreshold(0.25);
									pl->setCrackPropThreshold(mCrackPropThreshold);

									crack->setPropagationLaw(pl);

									crack->updateDofIdPool();

									center_coord_inserted_cracks.push_back(pc);
									eiList.push_back( std::unique_ptr<EnrichmentItem>(std::move(crack)) );

//									printf("Nucleating a crack in NCPrincipalStress::nucleateEnrichmentItems.\n");
//									printf("el->giveGlobalNumber(): %d\n", el->giveGlobalNumber() );

									// We only introduce one crack per element in a single time step.
									break;
								}
							}
						}

				}
			}
		} // If correct csNum
	}