double
UserDefDirichletBC :: give(Dof *dof, ValueModeType mode, TimeStep *stepN)
{
    double factor = this->giveLoadTimeFunction()->evaluate(stepN, mode);
    DofManager *dMan = dof->giveDofManager();


    /*
     * The Python function takes two input arguments:
     * 	1) An array with node coordinates
     * 	2) The dof id
     */
    int numArgs = 3;

    // Create array with node coordinates
    int dim = dMan->giveCoordinates()->giveSize();
    PyObject *pArgArray = PyList_New(dim);

    PyObject *pArgs = PyTuple_New(numArgs);

    for (int i = 0; i < dim; i++) {
        PyList_SET_ITEM(pArgArray, i, PyFloat_FromDouble( dMan->giveCoordinate(i+1) ));
    }
    // PyTuple_SetItem takes over responsibility for objects passed
    // to it -> no DECREF
    PyTuple_SetItem(pArgs, 0, pArgArray);


    // Dof number
    PyObject *pValDofNum = PyLong_FromLong(dof->giveDofID());
    PyTuple_SetItem(pArgs, 1, pValDofNum);


    // Time
    PyObject *pTargetTime = PyFloat_FromDouble( stepN->giveTargetTime() );
    PyTuple_SetItem(pArgs, 2, pTargetTime);

    // Value returned from the Python function
    PyObject *pRetVal;

    if ( PyCallable_Check(mpFunc) ) {
        pRetVal = PyObject_CallObject(mpFunc, pArgs);
    } else {
        OOFEM_ERROR("UserDefDirichletBC :: give: Python function is not callable.");
    }

    // Get return value
    double retVal = 0.0;
    if ( pRetVal != NULL ) {
        retVal = PyFloat_AsDouble(pRetVal);
    }
    else {
        OOFEM_ERROR("UserDefDirichletBC :: give: Failed to fetch Python return value.");
    }

    // Decrement reference count on pointers
    Py_DECREF(pArgs);
    Py_DECREF(pRetVal);

    return retVal*factor;
}
Esempio n. 2
0
void PLHoopStressCirc :: propagateInterfaces(Domain &iDomain, EnrichmentDomain &ioEnrDom)
{
    // Fetch crack tip data
    TipInfo tipInfoStart, tipInfoEnd;
    ioEnrDom.giveTipInfos(tipInfoStart, tipInfoEnd);
    std :: vector< TipInfo >tipInfo = {tipInfoStart, tipInfoEnd};

    SpatialLocalizer *localizer = iDomain.giveSpatialLocalizer();

    for ( size_t tipIndex = 0; tipIndex < tipInfo.size(); tipIndex++ ) {
        // Construct circle points on an arc from -90 to 90 degrees
        double angle = -90.0 + mAngleInc;
        std :: vector< double >angles;
        while ( angle <= ( 90.0 - mAngleInc ) ) {
            angles.push_back(angle * M_PI / 180.0);
            angle += mAngleInc;
        }

        const FloatArray &xT    = tipInfo [ tipIndex ].mGlobalCoord;
        const FloatArray &t             = tipInfo [ tipIndex ].mTangDir;
        const FloatArray &n             = tipInfo [ tipIndex ].mNormalDir;

        // It is meaningless to propagate a tip that is not inside any element
        Element *el = localizer->giveElementContainingPoint(tipInfo [ tipIndex ].mGlobalCoord);
        if ( el != NULL ) {
            std :: vector< FloatArray >circPoints;

            for ( size_t i = 0; i < angles.size(); i++ ) {
                FloatArray tangent(2);
                tangent.zero();
                tangent.add(cos(angles [ i ]), t);
                tangent.add(sin(angles [ i ]), n);
                tangent.normalize();

                FloatArray x(xT);
                x.add(mRadius, tangent);
                circPoints.push_back(x);
            }



            std :: vector< double >sigTTArray, sigRTArray;

            // Loop over circle points
            for ( size_t pointIndex = 0; pointIndex < circPoints.size(); pointIndex++ ) {
                FloatArray stressVec;

                if ( mUseRadialBasisFunc ) {
                    // Interpolate stress with radial basis functions

                    // Choose a cut-off length l:
                    // take the distance between two nodes in the element containing the
                    // crack tip multiplied by a constant factor.
                    // ( This choice implies that we hope that the element has reasonable
                    // aspect ratio.)
                    const FloatArray &x1 = * ( el->giveDofManager(1)->giveCoordinates() );
                    const FloatArray &x2 = * ( el->giveDofManager(2)->giveCoordinates() );
                    const double l = 1.0 * x1.distance(x2);

                    // Use the octree to get all elements that have
                    // at least one Gauss point in a certain region around the tip.
                    const double searchRadius = 3.0 * l;
                    std :: set< int >elIndices;
                    localizer->giveAllElementsWithIpWithinBox(elIndices, circPoints [ pointIndex ], searchRadius);


                    // Loop over the elements and Gauss points obtained.
                    // Evaluate the interpolation.
                    FloatArray sumQiWiVi;
                    double sumWiVi = 0.0;
                    for ( int elIndex: elIndices ) {
                        Element *gpEl = iDomain.giveElement(elIndex);
                        IntegrationRule *iRule = gpEl->giveDefaultIntegrationRulePtr();

                        for ( GaussPoint *gp_i: *iRule ) {

                            ////////////////////////////////////////
                            // Compute global gp coordinates
                            FloatArray N;
                            FEInterpolation *interp = gpEl->giveInterpolation();
                            interp->evalN( N, * ( gp_i->giveCoordinates() ), FEIElementGeometryWrapper(gpEl) );


                            // Compute global coordinates of Gauss point
                            FloatArray globalCoord(2);
                            globalCoord.zero();

                            for ( int i = 1; i <= gpEl->giveNumberOfDofManagers(); i++ ) {
                                DofManager *dMan = gpEl->giveDofManager(i);
                                globalCoord.at(1) += N.at(i) * dMan->giveCoordinate(1);
                                globalCoord.at(2) += N.at(i) * dMan->giveCoordinate(2);
                            }


                            ////////////////////////////////////////
                            // Compute weight of kernel function

                            FloatArray tipToGP;
                            tipToGP.beDifferenceOf(globalCoord, xT);
                            bool inFrontOfCrack = true;
                            if ( tipToGP.dotProduct(t) < 0.0 ) {
                                inFrontOfCrack = false;
                            }

                            double r = circPoints [ pointIndex ].distance(globalCoord);

                            if ( r < l && inFrontOfCrack ) {
                                double w = ( ( l - r ) / ( pow(2.0 * M_PI, 1.5) * pow(l, 3) ) ) * exp( -0.5 * pow(r, 2) / pow(l, 2) );

                                // Compute gp volume
                                double V = gpEl->computeVolumeAround(gp_i);

                                // Get stress
                                StructuralMaterialStatus *ms = dynamic_cast< StructuralMaterialStatus * >( gp_i->giveMaterialStatus() );
                                if ( ms == NULL ) {
                                    OOFEM_ERROR("failed to fetch MaterialStatus.");
                                }

                                FloatArray stressVecGP = ms->giveStressVector();

                                if ( sumQiWiVi.giveSize() != stressVecGP.giveSize() ) {
                                    sumQiWiVi.resize( stressVecGP.giveSize() );
                                    sumQiWiVi.zero();
                                }

                                // Add to numerator
                                sumQiWiVi.add(w * V, stressVecGP);

                                // Add to denominator
                                sumWiVi += w * V;
                            }
                        }
                    }


                    if ( fabs(sumWiVi) > 1.0e-12 ) {
                        stressVec.beScaled(1.0 / sumWiVi, sumQiWiVi);
                    } else {
                        // Take stress from closest Gauss point
                        int region = 1;
                        bool useCZGP = false;
                        GaussPoint &gp = * ( localizer->giveClosestIP(circPoints [ pointIndex ], region, useCZGP) );


                        // Compute stresses
                        StructuralMaterialStatus *ms = dynamic_cast< StructuralMaterialStatus * >( gp.giveMaterialStatus() );
                        if ( ms == NULL ) {
                            OOFEM_ERROR("failed to fetch MaterialStatus.");
                        }

                        stressVec = ms->giveStressVector();
                    }
                } else {
                    // Take stress from closest Gauss point
                    int region = 1;
                    bool useCZGP = false;
                    GaussPoint &gp = * ( localizer->giveClosestIP(circPoints [ pointIndex ], region, useCZGP) );


                    // Compute stresses
                    StructuralMaterialStatus *ms = dynamic_cast< StructuralMaterialStatus * >( gp.giveMaterialStatus() );
                    if ( ms == NULL ) {
                        OOFEM_ERROR("failed to fetch MaterialStatus.");
                    }

                    stressVec = ms->giveStressVector();
                }

                FloatMatrix stress(2, 2);

                int shearPos = stressVec.giveSize();

                stress.at(1, 1) = stressVec.at(1);
                stress.at(1, 2) = stressVec.at(shearPos);
                stress.at(2, 1) = stressVec.at(shearPos);
                stress.at(2, 2) = stressVec.at(2);


                // Rotation matrix
                FloatMatrix rot(2, 2);
                rot.at(1, 1) =  cos(angles [ pointIndex ]);
                rot.at(1, 2) = -sin(angles [ pointIndex ]);
                rot.at(2, 1) =  sin(angles [ pointIndex ]);
                rot.at(2, 2) =  cos(angles [ pointIndex ]);

                FloatArray tRot, nRot;
                tRot.beProductOf(rot, t);
                nRot.beProductOf(rot, n);

                FloatMatrix rotTot(2, 2);
                rotTot.setColumn(tRot, 1);
                rotTot.setColumn(nRot, 2);


                FloatMatrix tmp, stressRot;

                tmp.beTProductOf(rotTot, stress);
                stressRot.beProductOf(tmp, rotTot);


                const double sigThetaTheta      =               stressRot.at(2, 2);
                sigTTArray.push_back(sigThetaTheta);

                const double sigRTheta          =               stressRot.at(1, 2);
                sigRTArray.push_back(sigRTheta);
            }

            //////////////////////////////
            // Compute propagation angle

            // Find angles that fulfill sigRT = 0
            const double stressTol = 1.0e-9;
            double maxSigTT = 0.0, maxAngle = 0.0;
            bool foundZeroLevel = false;
            for ( size_t segIndex = 0; segIndex < ( circPoints.size() - 1 ); segIndex++ ) {
                // If the shear stress sigRT changes sign over the segment
                if ( sigRTArray [ segIndex ] * sigRTArray [ segIndex + 1 ] < stressTol ) {
                    // Compute location of zero level
                    double xi = EnrichmentItem :: calcXiZeroLevel(sigRTArray [ segIndex ], sigRTArray [ segIndex + 1 ]);

                    double theta                    = 0.5 * ( 1.0 - xi ) * angles [ segIndex ]         + 0.5 * ( 1.0 + xi ) * angles [ segIndex + 1 ];
                    double sigThetaTheta    = 0.5 * ( 1.0 - xi ) * sigTTArray [ segIndex ] + 0.5 * ( 1.0 + xi ) * sigTTArray [ segIndex + 1 ];

                    //					printf("Found candidate: theta: %e sigThetaTheta: %e\n", theta, sigThetaTheta);

                    if ( sigThetaTheta > maxSigTT ) {
                        foundZeroLevel = true;
                        maxSigTT = sigThetaTheta;
                        maxAngle = theta;
                    }
                }
            }

            if ( !foundZeroLevel ) {
                printf("No zero level was found.\n");
            }

            if ( iDomain.giveXfemManager()->giveVtkDebug() ) {
                XFEMDebugTools :: WriteArrayToMatlab("sigTTvsAngle.m", angles, sigTTArray);
                XFEMDebugTools :: WriteArrayToMatlab("sigRTvsAngle.m", angles, sigRTArray);

                XFEMDebugTools :: WriteArrayToGnuplot("sigTTvsAngle.dat", angles, sigTTArray);
                XFEMDebugTools :: WriteArrayToGnuplot("sigRTvsAngle.dat", angles, sigRTArray);
            }

            // Compare with threshold
            if ( maxSigTT > mHoopStressThreshold && foundZeroLevel ) {
                // Rotation matrix
                FloatMatrix rot(2, 2);
                rot.at(1, 1) =  cos(maxAngle);
                rot.at(1, 2) = -sin(maxAngle);
                rot.at(2, 1) =  sin(maxAngle);
                rot.at(2, 2) =  cos(maxAngle);

                FloatArray dir;
                dir.beProductOf(rot, tipInfo [ tipIndex ].mTangDir);

                // Fill up struct
                std :: vector< TipPropagation >tipPropagations;
                TipPropagation tipProp;
                tipProp.mTipIndex = tipIndex;
                tipProp.mPropagationDir = dir;
                tipProp.mPropagationLength = mIncrementLength;
                tipPropagations.push_back(tipProp);


                // Propagate
                ioEnrDom.propagateTips(tipPropagations);
            }
        }
    }
}
Esempio n. 3
0
void LSPrimaryVariableMapper :: mapPrimaryVariables(FloatArray &oU, Domain &iOldDom, Domain &iNewDom, ValueModeType iMode, TimeStep &iTStep)
{
    EngngModel *engngMod = iNewDom.giveEngngModel();
    EModelDefaultEquationNumbering num;


    const int dim = iNewDom.giveNumberOfSpatialDimensions();

    int numElNew = iNewDom.giveNumberOfElements();

    // Count dofs
    int numDofsNew = engngMod->giveNumberOfDomainEquations( 1, num );


    oU.resize(numDofsNew);
    oU.zero();

    FloatArray du(numDofsNew);
    du.zero();

    FloatArray res(numDofsNew);

#ifdef __PETSC_MODULE
    PetscSparseMtrx *K = dynamic_cast<PetscSparseMtrx*>( classFactory.createSparseMtrx(SMT_PetscMtrx) );
    SparseLinearSystemNM *solver = classFactory.createSparseLinSolver(ST_Petsc, & iOldDom, engngMod);
#else
    SparseMtrx *K = classFactory.createSparseMtrx(SMT_Skyline);
    SparseLinearSystemNM *solver = classFactory.createSparseLinSolver(ST_Direct, & iOldDom, engngMod);
#endif


    K->buildInternalStructure( engngMod, 1, num );

    int maxIter = 1;

    for ( int iter = 0; iter < maxIter; iter++ ) {
        K->zero();
        res.zero();


        // Contribution from elements
        for ( int elIndex = 1; elIndex <= numElNew; elIndex++ ) {
            StructuralElement *elNew = dynamic_cast< StructuralElement * >( iNewDom.giveElement(elIndex) );
            if ( elNew == NULL ) {
                OOFEM_ERROR("Failed to cast Element new to StructuralElement.");
            }

            ///////////////////////////////////
            // Compute residual

            // Count element dofs
            int numElNodes = elNew->giveNumberOfDofManagers();
            int numElDofs = 0;
            for ( int i = 1; i <= numElNodes; i++ ) {
                numElDofs += elNew->giveDofManager(i)->giveNumberOfDofs();
            }

            FloatArray elRes(numElDofs);
            elRes.zero();

            IntArray elDofsGlob;
            elNew->giveLocationArray( elDofsGlob, num );


            // Loop over Gauss points
            for ( int intRuleInd = 0; intRuleInd < elNew->giveNumberOfIntegrationRules(); intRuleInd++ ) {
                IntegrationRule *iRule = elNew->giveIntegrationRule(intRuleInd);

                for ( GaussPoint *gp: *iRule ) {

                    // New N-matrix
                    FloatMatrix NNew;
                    elNew->computeNmatrixAt(* ( gp->giveNaturalCoordinates() ), NNew);


                    //////////////
                    // Global coordinates of GP
                    const int nDofMan = elNew->giveNumberOfDofManagers();

                    FloatArray Nc;
                    FEInterpolation *interp = elNew->giveInterpolation();
                    const FloatArray &localCoord = * ( gp->giveNaturalCoordinates() );
                    interp->evalN( Nc, localCoord, FEIElementGeometryWrapper(elNew) );

                    const IntArray &elNodes = elNew->giveDofManArray();

                    FloatArray globalCoord(dim);
                    globalCoord.zero();

                    for ( int i = 1; i <= nDofMan; i++ ) {
                        DofManager *dMan = elNew->giveDofManager(i);

                        for ( int j = 1; j <= dim; j++ ) {
                            globalCoord.at(j) += Nc.at(i) * dMan->giveCoordinate(j);
                        }
                    }
                    //////////////


                    // Localize element and point in the old domain
                    FloatArray localCoordOld(dim), pointCoordOld(dim);
                    StructuralElement *elOld = dynamic_cast< StructuralElement * >( iOldDom.giveSpatialLocalizer()->giveElementClosestToPoint(localCoordOld, pointCoordOld, globalCoord, 0) );
                    if ( elOld == NULL ) {
                        OOFEM_ERROR("Failed to cast Element old to StructuralElement.");
                    }


                    // Compute N-Matrix for the old element
                    FloatMatrix NOld;
                    elOld->computeNmatrixAt(localCoordOld, NOld);

                    // Fetch nodal displacements for the new element
                    FloatArray nodeDispNew( elDofsGlob.giveSize() );


                    int dofsPassed = 1;
                    for ( int i = 1; i <= elNodes.giveSize(); i++ ) {
                        DofManager *dMan = elNew->giveDofManager(i);

                        for ( Dof *dof: *dMan ) {
                            if ( elDofsGlob.at(dofsPassed) != 0 ) {
                                nodeDispNew.at(dofsPassed) = oU.at( elDofsGlob.at(dofsPassed) );
                            } else {
                                if ( dof->hasBc(& iTStep) ) {
                                    nodeDispNew.at(dofsPassed) = dof->giveBcValue(iMode, & iTStep);
                                }
                            }

                            dofsPassed++;
                        }
                    }


                    FloatArray newDisp;
                    newDisp.beProductOf(NNew, nodeDispNew);


                    // Fetch nodal displacements for the old element
                    FloatArray nodeDispOld;
                    dofsPassed = 1;
                    IntArray elDofsGlobOld;
                    elOld->giveLocationArray( elDofsGlobOld, num );

//                    elOld->computeVectorOf(iMode, &(iTStep), nodeDisp);
                    int numElNodesOld = elOld->giveNumberOfDofManagers();
                    for(int nodeIndOld = 1; nodeIndOld <= numElNodesOld; nodeIndOld++) {
                        DofManager *dManOld = elOld->giveDofManager(nodeIndOld);

                        for ( Dof *dof: *dManOld ) {
                            if ( elDofsGlobOld.at(dofsPassed) != 0 ) {
                                FloatArray dofUnknowns;
                                dof->giveUnknowns(dofUnknowns, iMode, &iTStep);

#ifdef DEBUG
                                if(!dofUnknowns.isFinite()) {
                                    OOFEM_ERROR("!dofUnknowns.isFinite()")
                                }

                                if(dofUnknowns.giveSize() < 1) {
                                    OOFEM_ERROR("dofUnknowns.giveSize() < 1")
                                }
#endif
                                nodeDispOld.push_back(dofUnknowns.at(1));
                            } else {
                                if ( dof->hasBc(& iTStep) ) {
//                                    printf("hasBC.\n");
#ifdef DEBUG
                                    if(!std::isfinite(dof->giveBcValue(iMode, & iTStep))) {
                                        OOFEM_ERROR("!std::isfinite(dof->giveBcValue(iMode, & iTStep))")
                                    }
#endif
                                    nodeDispOld.push_back( dof->giveBcValue(iMode, & iTStep) );
                                }
                                else {
//                                    printf("Unhandled case in LSPrimaryVariableMapper :: mapPrimaryVariables().\n");
                                    nodeDispOld.push_back( 0.0 );
                                }
                            }

                            dofsPassed++;
                        }

                    }


                    FloatArray oldDisp;
                    oldDisp.beProductOf(NOld, nodeDispOld);

                    FloatArray temp, du;

#ifdef DEBUG
                    if(!oldDisp.isFinite()) {
                        OOFEM_ERROR("!oldDisp.isFinite()")
                    }

                    if(!newDisp.isFinite()) {
                        OOFEM_ERROR("!newDisp.isFinite()")
                    }
#endif

                    du.beDifferenceOf(oldDisp, newDisp);
                    temp.beTProductOf(NNew, du);
                    double dV = elNew->computeVolumeAround(gp);
                    elRes.add(dV, temp);
                }
            }