bool EnrichmentItem :: tipIsTouchingEI(const TipInfo &iTipInfo) { double tol = 1.0e-9; SpatialLocalizer *localizer = giveDomain()->giveSpatialLocalizer(); Element *tipEl = localizer->giveElementContainingPoint(iTipInfo.mGlobalCoord); if ( tipEl != NULL ) { // Check if the candidate tip is located on the current crack FloatArray N; FloatArray locCoord; tipEl->computeLocalCoordinates(locCoord, iTipInfo.mGlobalCoord); FEInterpolation *interp = tipEl->giveInterpolation(); interp->evalN( N, locCoord, FEIElementGeometryWrapper(tipEl) ); double normalSignDist; evalLevelSetNormal( normalSignDist, iTipInfo.mGlobalCoord, N, tipEl->giveDofManArray() ); double tangSignDist; evalLevelSetTangential( tangSignDist, iTipInfo.mGlobalCoord, N, tipEl->giveDofManArray() ); if ( fabs(normalSignDist) < tol && tangSignDist > tol ) { return true; } } return false; }
int PrimaryField :: __evaluateAt(FloatArray &answer, FloatArray& coords, ValueModeType mode, TimeStep *atTime, IntArray *dofId) { Element *bgelem; Domain *domain = emodel->giveDomain(domainIndx); SpatialLocalizer *sl = domain->giveSpatialLocalizer(); // locate background element if ( ( bgelem = sl->giveElementContainingPoint(coords) ) == NULL ) { //_error ("PrimaryField::evaluateAt: point not found in domain\n"); return 1; } EIPrimaryFieldInterface *interface = ( EIPrimaryFieldInterface * ) ( bgelem->giveInterface(EIPrimaryFieldInterfaceType) ); if ( interface ) { if (dofId) { return interface->EIPrimaryFieldI_evaluateFieldVectorAt(answer, * this, coords, *dofId, mode, atTime); } else { // use element default dof id mask IntArray elemDofId; bgelem->giveElementDofIDMask(this->giveEquationID(), elemDofId); return interface->EIPrimaryFieldI_evaluateFieldVectorAt(answer, * this, coords, elemDofId, mode, atTime); } } else { _error("ScalarPrimaryField::operator(): background element does not support EIPrimaryFiledInterface\n"); return 1; // failed } }
void MMAContainingElementProjection :: __init(Domain *dold, IntArray &type, FloatArray &coords, Set &elemSet, TimeStep *tStep, bool iCohesiveZoneGP) { SpatialLocalizer *sl = dold->giveSpatialLocalizer(); FloatArray jGpCoords; double distance, minDist = 1.e6; Element *srcElem; if ( ( srcElem = sl->giveElementContainingPoint(coords, elemSet) ) ) { this->source = NULL; for ( GaussPoint *jGp: *srcElem->giveDefaultIntegrationRulePtr() ) { if ( srcElem->computeGlobalCoordinates( jGpCoords, jGp->giveNaturalCoordinates() ) ) { distance = coords.distance(jGpCoords); if ( distance < minDist ) { minDist = distance; this->source = jGp; } } } if ( !source ) { OOFEM_ERROR("no suitable source found"); } } else { OOFEM_ERROR("No suitable element found"); } }
bool PLCrackPrescribedDir :: propagateInterface(Domain &iDomain, EnrichmentFront &iEnrFront, TipPropagation &oTipProp) { if ( !iEnrFront.propagationIsAllowed() ) { return false; } const TipInfo &tipInfo = iEnrFront.giveTipInfo(); SpatialLocalizer *localizer = iDomain.giveSpatialLocalizer(); // It is meaningless to propagate a tip that is not inside any element if ( tipInfo.mGlobalCoord.giveSize() == 0 ) { return false; } Element *el = localizer->giveElementContainingPoint(tipInfo.mGlobalCoord); if ( el == NULL ) { return false; } double angleRad = mAngle * M_PI / 180.0; FloatArray dir = { cos(angleRad), sin(angleRad) }; oTipProp.mTipIndex = tipInfo.mTipIndex; oTipProp.mPropagationDir = dir; oTipProp.mPropagationLength = mIncrementLength; return true; }
void MMALeastSquareProjection :: __init(Domain *dold, IntArray &type, FloatArray &coords, Set &elemSet, TimeStep *tStep, bool iCohesiveZoneGP) //(Domain* dold, IntArray& varTypes, GaussPoint* gp, TimeStep* tStep) { GaussPoint *sourceIp; Element *sourceElement; SpatialLocalizer *sl = dold->giveSpatialLocalizer(); IntegrationRule *iRule; IntArray patchList; this->patchDomain = dold; // find the closest IP on old mesh sourceElement = sl->giveElementContainingPoint(coords, elemSet); if ( !sourceElement ) { OOFEM_ERROR("no suitable source element found"); } // determine the type of patch Element_Geometry_Type egt = sourceElement->giveGeometryType(); if ( egt == EGT_line_1 ) { this->patchType = MMALSPPatchType_1dq; } else if ( ( egt == EGT_triangle_1 ) || ( egt == EGT_quad_1 ) ) { this->patchType = MMALSPPatchType_2dq; } else { OOFEM_ERROR("unsupported material mode"); } /* Determine the state of closest point. * Only IP in the neighbourhood with same state can be used * to interpolate the values. */ FloatArray dam; int state = 0; if ( this->stateFilter ) { iRule = sourceElement->giveDefaultIntegrationRulePtr(); for ( GaussPoint *gp: *iRule ) { sourceElement->giveIPValue(dam, gp, IST_PrincipalDamageTensor, tStep); if ( dam.computeNorm() > 1.e-3 ) { state = 1; // damaged } } } // from source neighbours the patch will be constructed Element *element; IntArray neighborList; patchList.resize(1); patchList.at(1) = sourceElement->giveNumber(); int minNumberOfPoints = this->giveNumberOfUnknownPolynomialCoefficients(this->patchType); int actualNumberOfPoints = sourceElement->giveDefaultIntegrationRulePtr()->giveNumberOfIntegrationPoints(); int nite = 0; int elemFlag; // check if number of IP in patchList is sufficient // some recursion control would be appropriate while ( ( actualNumberOfPoints < minNumberOfPoints ) && ( nite <= 2 ) ) { //if not, construct the neighborhood dold->giveConnectivityTable()->giveElementNeighbourList(neighborList, patchList); // count number of available points patchList.clear(); actualNumberOfPoints = 0; for ( int i = 1; i <= neighborList.giveSize(); i++ ) { if ( this->stateFilter ) { element = patchDomain->giveElement( neighborList.at(i) ); // exclude elements in different regions if ( !elemSet.hasElement( element->giveNumber() ) ) { continue; } iRule = element->giveDefaultIntegrationRulePtr(); elemFlag = 0; for ( GaussPoint *gp: *iRule ) { element->giveIPValue(dam, gp, IST_PrincipalDamageTensor, tStep); if ( state && ( dam.computeNorm() > 1.e-3 ) ) { actualNumberOfPoints++; elemFlag = 1; } else if ( ( state == 0 ) && ( dam.computeNorm() < 1.e-3 ) ) { actualNumberOfPoints++; elemFlag = 1; } } if ( elemFlag ) { // include this element with corresponding state in neighbor search. patchList.followedBy(neighborList.at(i), 10); } } else { // if (! yhis->stateFilter) element = patchDomain->giveElement( neighborList.at(i) ); // exclude elements in different regions if ( !elemSet.hasElement( element->giveNumber() ) ) { continue; } actualNumberOfPoints += element->giveDefaultIntegrationRulePtr()->giveNumberOfIntegrationPoints(); patchList.followedBy(neighborList.at(i), 10); } } // end loop over neighbor list nite++; } if ( nite > 2 ) { // not enough points -> take closest point projection patchGPList.clear(); sourceIp = sl->giveClosestIP(coords, elemSet); patchGPList.push_front(sourceIp); //fprintf(stderr, "MMALeastSquareProjection: too many neighbor search iterations\n"); //exit (1); return; } #ifdef MMALSP_ONLY_CLOSEST_POINTS // select only the nval closest IP points GaussPoint **gpList = ( GaussPoint ** ) malloc(sizeof( GaussPoint * ) * actualNumberOfPoints); FloatArray dist(actualNumberOfPoints), srcgpcoords; int npoints = 0; // check allocation of gpList if ( gpList == NULL ) { OOFEM_FATAL("memory allocation error"); } for ( int ielem = 1; ielem <= patchList.giveSize(); ielem++ ) { element = patchDomain->giveElement( patchList.at(ielem) ); iRule = element->giveDefaultIntegrationRulePtr(); for ( GaussPoint *srcgp: *iRule ) { if ( element->computeGlobalCoordinates( srcgpcoords, * ( srcgp->giveNaturalCoordinates() ) ) ) { element->giveIPValue(dam, srcgp, IST_PrincipalDamageTensor, tStep); if ( this->stateFilter ) { // consider only points with same state if ( ( ( state == 1 ) && ( norm(dam) > 1.e-3 ) ) || ( ( ( state == 0 ) && norm(dam) < 1.e-3 ) ) ) { npoints++; dist.at(npoints) = coords.distance(srcgpcoords); gpList [ npoints - 1 ] = srcgp; } } else { // take all points into account npoints++; dist.at(npoints) = coords.distance(srcgpcoords); gpList [ npoints - 1 ] = srcgp; } } else { OOFEM_ERROR("computeGlobalCoordinates failed"); } } } if ( npoints != actualNumberOfPoints ) { OOFEM_ERROR("internal error"); } //minNumberOfPoints = min (actualNumberOfPoints, minNumberOfPoints+2); patchGPList.clear(); // now find the minNumberOfPoints with smallest distance // from point of interest double swap, minDist; int minDistIndx = 0; // loop over all points for ( int i = 1; i <= minNumberOfPoints; i++ ) { minDist = dist.at(i); minDistIndx = i; // search for point with i-th smallest distance for ( j = i + 1; j <= actualNumberOfPoints; j++ ) { if ( dist.at(j) < minDist ) { minDist = dist.at(j); minDistIndx = j; } } // remember this ip patchGPList.push_front(gpList [ minDistIndx - 1 ]); swap = dist.at(i); dist.at(i) = dist.at(minDistIndx); dist.at(minDistIndx) = swap; srcgp = gpList [ i - 1 ]; gpList [ i - 1 ] = gpList [ minDistIndx - 1 ]; gpList [ minDistIndx - 1 ] = srcgp; } if ( patchGPList.size() != minNumberOfPoints ) { OOFEM_ERROR("internal error 2"); exit(1); } free(gpList); #else // take all neighbors patchGPList.clear(); for ( int ielem = 1; ielem <= patchList.giveSize(); ielem++ ) { element = patchDomain->giveElement( patchList.at(ielem) ); iRule = element->giveDefaultIntegrationRulePtr(); for ( GaussPoint *gp: *iRule ) { patchGPList.push_front( gp ); } } #endif }
void POIExportModule :: exportPrimVarAs(UnknownType valID, FILE *stream, TimeStep *tStep) { Domain *d = emodel->giveDomain(1); int j; FloatArray pv, coords(3); InternalStateValueType type = ISVT_UNDEFINED; if ( valID == DisplacementVector ) { type = ISVT_VECTOR; } else if ( valID == FluxVector ) { type = ISVT_SCALAR; } else { OOFEM_ERROR("POIExportModule::exportPrimVarAs: unsupported UnknownType"); } // print header if ( type == ISVT_SCALAR ) { fprintf(stream, "SCALARS prim_scalar_%d\n", ( int ) valID); } else if ( type == ISVT_VECTOR ) { fprintf(stream, "VECTORS vector_%d float\n", ( int ) valID); } else { fprintf(stderr, "POIExportModule::exportPrimVarAs: unsupported variable type\n"); } SpatialLocalizer *sl = d->giveSpatialLocalizer(); // loop over POIs std::list< POI_dataType > :: iterator PoiIter; for ( PoiIter = POIList.begin(); PoiIter != POIList.end(); ++PoiIter ) { coords.at(1) = ( * PoiIter ).x; coords.at(2) = ( * PoiIter ).y; coords.at(3) = ( * PoiIter ).z; //region = (*PoiIter).region; Element *source = sl->giveElementContainingPoint(coords, NULL); if ( source ) { // ask interface EIPrimaryUnknownMapperInterface *interface = ( EIPrimaryUnknownMapperInterface * ) ( source->giveInterface(EIPrimaryUnknownMapperInterfaceType) ); if ( interface ) { interface->EIPrimaryUnknownMI_computePrimaryUnknownVectorAt(VM_Total, tStep, coords, pv); } else { pv.resize(0); OOFEM_WARNING2( "POIExportModule::exportPrimVarAs: element %d with no EIPrimaryUnknownMapperInterface support", source->giveNumber() ); } fprintf(stream, "%10d ", ( * PoiIter ).id); if ( pv.giveSize() ) { for ( j = 1; j <= pv.giveSize(); j++ ) { fprintf( stream, " %15e ", pv.at(j) ); } } fprintf(stream, "\n"); } else { OOFEM_ERROR4( "POIExportModule::exportPrimVarAs: no element containing POI(%e,%e,%e) found", coords.at(1), coords.at(2), coords.at(3) ); } } }
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); } } } }
int EIPrimaryUnknownMapper :: evaluateAt(FloatArray &answer, IntArray &dofMask, ValueModeType mode, Domain *oldd, FloatArray &coords, IntArray ®List, TimeStep *tStep) { Element *oelem; EIPrimaryUnknownMapperInterface *interface; SpatialLocalizer *sl = oldd->giveSpatialLocalizer(); ///@todo Change to the other version after checking that it works properly. Will render "giveElementCloseToPoint" obsolete (superseeded by giveElementClosestToPoint). #if 1 if ( regList.isEmpty() ) { oelem = sl->giveElementContainingPoint(coords); } else { oelem = sl->giveElementContainingPoint(coords, & regList); } if ( !oelem ) { if ( regList.isEmpty() ) { oelem = oldd->giveSpatialLocalizer()->giveElementCloseToPoint(coords); } else { oelem = oldd->giveSpatialLocalizer()->giveElementCloseToPoint(coords, & regList); } if ( !oelem ) { OOFEM_WARNING("Couldn't find any element containing point."); return false; } } #else FloatArray lcoords, closest; if ( regList.isEmpty() ) { oelem = sl->giveElementClosestToPoint(lcoords, closest, coords, 0); } else { // Take the minimum of any region double mindist = 0.0, distance; oelem = NULL; for ( int i = 1; i < regList.giveSize(); ++i ) { Element *tmpelem = sl->giveElementClosestToPoint( lcoords, closest, coords, regList.at(i) ); distance = closest.distance_square(coords); if ( tmpelem != NULL ) { distance = closest.distance_square(coords); if ( distance < mindist || i == 1 ) { mindist = distance; oelem = tmpelem; if ( distance == 0.0 ) { break; } } } } } if ( !oelem ) { OOFEM_WARNING("Couldn't find any element containing point."); return false; } #endif interface = static_cast< EIPrimaryUnknownMapperInterface * >( oelem->giveInterface(EIPrimaryUnknownMapperInterfaceType) ); if ( interface ) { oelem->giveElementDofIDMask(dofMask); #if 1 FloatArray lcoords; if ( oelem->computeLocalCoordinates(lcoords, coords) ) { interface->EIPrimaryUnknownMI_computePrimaryUnknownVectorAtLocal(mode, tStep, lcoords, answer); } else { answer.clear(); } #else interface->EIPrimaryUnknownMI_computePrimaryUnknownVectorAtLocal(mode, tStep, lcoords, answer); #endif } else { OOFEM_ERROR("Element does not support EIPrimaryUnknownMapperInterface"); } return true; }
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 }