double FEI2dLineLin :: edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { normal.resize(2); normal.at(1) = cellgeo.giveVertexCoordinates(2)->at(xind) - cellgeo.giveVertexCoordinates(1)->at(xind); normal.at(2) = -(cellgeo.giveVertexCoordinates(2)->at(yind) - cellgeo.giveVertexCoordinates(1)->at(yind)); return normal.normalize()*0.5; }
void PolygonLine :: giveTangent(FloatArray &oTangent, const double &iArcPosition) const { double L = computeLength(); double xSegStart = 0.0, xSegEnd = 0.0; double xiSegStart = 0.0, xiSegEnd = 0.0; size_t numSeg = mVertices.size() - 1; const double xiTol = 1.0e-9; for ( size_t i = 0; i < numSeg; i++ ) { xSegEnd += mVertices [ i ].distance(mVertices [ i + 1 ]); xiSegStart = xSegStart / L; xiSegEnd = xSegEnd / L; if ( iArcPosition > xiSegStart-xiTol && iArcPosition < xiSegEnd+xiTol ) { // The given point is within the segment const FloatArray &p1 = mVertices [ i ]; const FloatArray &p2 = mVertices [ i+1 ]; oTangent = {p2(0) - p1(0), p2(1) - p1(1)}; oTangent.normalize(); return; } } OOFEM_ERROR("Arc position not found.") }
double FEI3dHexaLin :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { FloatArray a, b, dNdksi(4), dNdeta(4); double ksi, eta; IntArray snodes; this->computeLocalSurfaceMapping(snodes, isurf); ksi = lcoords.at(1); eta = lcoords.at(2); // No need to divide by 1/4, we'll normalize anyway; dNdksi.at(1) = ( 1. + eta ); dNdksi.at(2) = -( 1. + eta ); dNdksi.at(3) = -( 1. - eta ); dNdksi.at(4) = ( 1. - eta ); dNdeta.at(1) = ( 1. + ksi ); dNdeta.at(2) = ( 1. - ksi ); dNdeta.at(3) = -( 1. - ksi ); dNdeta.at(4) = -( 1. + ksi ); for (int i = 1; i <= 4; ++i) { a.add(dNdksi.at(i), *cellgeo.giveVertexCoordinates(snodes.at(i))); b.add(dNdeta.at(i), *cellgeo.giveVertexCoordinates(snodes.at(i))); } answer.beVectorProductOf(a, b); return answer.normalize()*0.0625; }
void Quad1MindlinShell3D :: computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) { FloatArray u, v; u.beDifferenceOf( * this->giveNode(2)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); v.beDifferenceOf( * this->giveNode(3)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); answer.beVectorProductOf(u, v); answer.normalize(); }
void DKTPlate :: computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) // returns normal vector to midPlane in GaussPoinr gp of receiver { FloatArray u, v; u.beDifferenceOf( * this->giveNode(2)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); v.beDifferenceOf( * this->giveNode(3)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); answer.beVectorProductOf(u, v); answer.normalize(); }
void PrescribedGradientBCWeak :: giveTractionElNormal(size_t iElInd, FloatArray &oNormal, FloatArray &oTangent) const { FloatArray xS, xE; giveTractionElCoord(iElInd, xS, xE); oTangent.beDifferenceOf(xE, xS); oTangent.normalize(); oNormal = { oTangent [ 1 ], -oTangent [ 0 ] }; }
void Lattice2d :: giveCrossSectionCoordinates(FloatArray &coords) { double x1, y1, x2, y2; x1 = this->giveNode(1)->giveCoordinate(1); y1 = this->giveNode(1)->giveCoordinate(2); x2 = this->giveNode(2)->giveCoordinate(1); y2 = this->giveNode(2)->giveCoordinate(2); //Compute normal and shear direction FloatArray normalDirection; FloatArray shearDirection; normalDirection.resize(2); normalDirection.zero(); shearDirection.resize(2); shearDirection.zero(); normalDirection.at(1) = x2 - x1; normalDirection.at(2) = y2 - y1; normalDirection.normalize(); if ( normalDirection.at(2) == 0. ) { shearDirection.at(1) = 0.; shearDirection.at(2) = 1.; } else { shearDirection.at(1) = 1.0; shearDirection.at(2) = -normalDirection.at(1) / normalDirection.at(2); } shearDirection.normalize(); coords.resize(6); coords.at(1) = this->gpCoords.at(1) - shearDirection.at(1) * this->width / 2.; coords.at(2) = this->gpCoords.at(2) - shearDirection.at(2) * this->width / 2.; coords.at(3) = 0.; coords.at(4) = this->gpCoords.at(1) + shearDirection.at(1) * this->width / 2.; coords.at(5) = this->gpCoords.at(2) + shearDirection.at(2) * this->width / 2.; coords.at(6) = 0.; return; }
double FEI2dQuadLin :: edgeEvalNormal(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { int nodeA, nodeB; IntArray edgeNodes; this->computeLocalEdgeMapping(edgeNodes, iedge); nodeA = edgeNodes.at(1); nodeB = edgeNodes.at(2); answer.resize(2); answer.at(1) = -(cellgeo.giveVertexCoordinates(nodeB)->at(yind) - cellgeo.giveVertexCoordinates(nodeA)->at(yind) ); answer.at(2) = (cellgeo.giveVertexCoordinates(nodeB)->at(xind) - cellgeo.giveVertexCoordinates(nodeA)->at(xind) ); return answer.normalize() * 0.5; }
void IntElPoint :: computeLocalSlipDir(FloatArray &normal) { normal.resizeWithValues(3); if ( this->referenceNode ) { // normal normal.beDifferenceOf(*domain->giveNode(this->referenceNode)->giveCoordinates(), *this->giveNode(1)->giveCoordinates()); } else { if ( normal.at(1) == 0 && normal.at(2) == 0 && normal.at(3) == 0 ) { OOFEM_ERROR("Normal is not defined (referenceNode=0,normal=(0,0,0))"); } } normal.normalize(); }
void IntElLine1PhF :: computeTransformationMatrixAt(GaussPoint *gp, FloatMatrix &answer) { // Transformation matrix to the local coordinate system FloatArray G; this->computeCovarBaseVectorAt(gp, G); G.normalize(); answer.resize(2, 2); answer.at(1, 1) = G.at(1); answer.at(2, 1) = -G.at(2); answer.at(1, 2) = G.at(2); answer.at(2, 2) = G.at(1); }
void InterfaceElem1d :: computeLocalSlipDir(FloatArray &normal) { normal.resizeWithValues(3); if ( this->referenceNode ) { // normal normal.at(1) = domain->giveNode(this->referenceNode)->giveCoordinate(1) - this->giveNode(1)->giveCoordinate(1); normal.at(2) = domain->giveNode(this->referenceNode)->giveCoordinate(2) - this->giveNode(1)->giveCoordinate(2); normal.at(3) = domain->giveNode(this->referenceNode)->giveCoordinate(3) - this->giveNode(1)->giveCoordinate(3); } else { if ( normal.at(1) == 0 && normal.at(2) == 0 && normal.at(3) == 0 ) { _error("computeLocalSlipDir: normal is not defined (referenceNode=0,normal=(0,0,0))"); } } normal.normalize(); }
void Structural2DElement :: giveMaterialOrientationAt(FloatArray &x, FloatArray &y, const FloatArray &lcoords) { if ( this->elemLocalCS.isNotEmpty() ) { // User specified orientation x = { elemLocalCS.at(1, 1), elemLocalCS.at(2, 1) }; y = { -x(1), x(0) }; } else { FloatMatrix jac; this->giveInterpolation()->giveJacobianMatrixAt( jac, lcoords, * this->giveCellGeometryWrapper() ); x.beColumnOf(jac, 1); // This is {dx/dxi, dy/dxi, dz/dxi} x.normalize(); y = { -x(1), x(0) }; } }
double FEI2dTrQuad :: edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { IntArray edgeNodes; this->computeLocalEdgeMapping(edgeNodes, iedge); double xi = lcoords(0); double dN1dxi = -0.5 + xi; double dN2dxi = 0.5 + xi; double dN3dxi = -2.0 * xi; normal.resize(2); normal.at(1) = dN1dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(yind) + dN2dxi *cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(yind) + dN3dxi *cellgeo.giveVertexCoordinates( edgeNodes.at(3) )->at(yind); normal.at(2) = -dN1dxi *cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(xind) + - dN2dxi *cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(xind) + - dN3dxi *cellgeo.giveVertexCoordinates( edgeNodes.at(3) )->at(xind); return normal.normalize(); }
double FEI3dHexaQuad :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { FloatArray a, b, dNdksi(8), dNdeta(8); double ksi, eta; IntArray snodes; this->computeLocalSurfaceMapping(snodes, isurf); ksi = lcoords.at(1); eta = lcoords.at(2); // No need to divide by 1/4, we'll normalize anyway; dNdksi.at(1) = 0.25 * ( 1. + eta ) * ( 2.0 * ksi + eta ); dNdksi.at(2) = -0.25 * ( 1. + eta ) * ( -2.0 * ksi + eta ); dNdksi.at(3) = -0.25 * ( 1. - eta ) * ( -2.0 * ksi - eta ); dNdksi.at(4) = 0.25 * ( 1. - eta ) * ( 2.0 * ksi - eta ); dNdksi.at(5) = -ksi * ( 1. + eta ); dNdksi.at(6) = -0.5 * ( 1. - eta * eta ); dNdksi.at(7) = -ksi * ( 1. - eta ); dNdksi.at(8) = 0.5 * ( 1. - eta * eta ); dNdeta.at(1) = 0.25 * ( 1. + ksi ) * ( 2.0 * eta + ksi ); dNdeta.at(2) = 0.25 * ( 1. - ksi ) * ( 2.0 * eta - ksi ); dNdeta.at(3) = -0.25 * ( 1. - ksi ) * ( -2.0 * eta - ksi ); dNdeta.at(4) = -0.25 * ( 1. + ksi ) * ( -2.0 * eta + ksi ); dNdeta.at(5) = 0.5 * ( 1. - ksi * ksi ); dNdeta.at(6) = -eta * ( 1. - ksi ); dNdeta.at(7) = -0.5 * ( 1. - ksi * ksi ); dNdeta.at(8) = -eta * ( 1. + ksi ); for ( int i = 1; i <= 8; ++i ) { a.add(dNdksi.at(i), *cellgeo.giveVertexCoordinates(snodes.at(i))); b.add(dNdeta.at(i), *cellgeo.giveVertexCoordinates(snodes.at(i))); } answer.beVectorProductOf(a, b); return answer.normalize(); }
void PLCrackPrescribedDir::propagateInterfaces(EnrichmentDomain &ioEnrDom) { printf("Entering PLCrackPrescribedDir::propagateInterfaces().\n"); // Fetch crack tip data std::vector<TipInfo> tipInfo; ioEnrDom.giveTipInfos(tipInfo); int tipIndex = 1; FloatArray dir; double angleRad = mAngle*M_PI/180.0; dir.setValues(2, cos(angleRad), sin(angleRad)); dir.normalize(); std::vector<TipPropagation> tipPropagations; TipPropagation tipProp; tipProp.mTipIndex = tipIndex; tipProp.mPropagationDir = dir; tipProp.mPropagationLength = mIncrementLength; tipPropagations.push_back(tipProp); ioEnrDom.propagateTips(tipPropagations); }
void LEPlic :: doCellDLS(FloatArray &fvgrad, int ie, bool coord_upd, bool vof_temp_flag) { int i, ineighbr, nneighbr; double fvi, fvk, wk, dx, dy; bool isBoundaryCell = false; LEPlicElementInterface *interface, *ineghbrInterface; FloatMatrix lhs(2, 2); FloatArray rhs(2), xi(2), xk(2); IntArray currCell(1), neighborList; ConnectivityTable *contable = domain->giveConnectivityTable(); if ( ( interface = ( LEPlicElementInterface * ) ( domain->giveElement(ie)->giveInterface(LEPlicElementInterfaceType) ) ) ) { if ( vof_temp_flag ) { fvi = interface->giveTempVolumeFraction(); } else { fvi = interface->giveVolumeFraction(); } if ( ( fvi > 0. ) && ( fvi <= 1.0 ) ) { // potentially boundary cell if ( ( fvi > 0. ) && ( fvi < 1.0 ) ) { isBoundaryCell = true; } /* DLS (Differential least square reconstruction) * * In the DLS method, volume fraction Taylor series expansion of vf (volume fraction) * is formed from each reference cell volume fraction vf at element center x(i) to each * cell neighbor at point x(k). The sum (vf(i)-vf(k))^2 over all immediate neighbors * is then minimized inthe least square sense. */ // get list of neighbours to current cell including current cell currCell.at(1) = ie; contable->giveElementNeighbourList(neighborList, currCell); // loop over neighbors to assemble normal equations nneighbr = neighborList.giveSize(); interface->giveElementCenter(this, xi, coord_upd); lhs.zero(); rhs.zero(); for ( i = 1; i <= nneighbr; i++ ) { ineighbr = neighborList.at(i); if ( ineighbr == ie ) { continue; // skip itself } if ( ( ineghbrInterface = ( LEPlicElementInterface * ) ( domain->giveElement(ineighbr)->giveInterface(LEPlicElementInterfaceType) ) ) ) { if ( vof_temp_flag ) { fvk = ineghbrInterface->giveTempVolumeFraction(); } else { fvk = ineghbrInterface->giveVolumeFraction(); } if ( fvk < 1.0 ) { isBoundaryCell = true; } ineghbrInterface->giveElementCenter(this, xk, coord_upd); wk = xk.distance(xi); dx = ( xk.at(1) - xi.at(1) ) / wk; dy = ( xk.at(2) - xi.at(2) ) / wk; lhs.at(1, 1) += dx * dx; lhs.at(1, 2) += dx * dy; lhs.at(2, 2) += dy * dy; rhs.at(1) += ( fvi - fvk ) * dx / wk; rhs.at(2) += ( fvi - fvk ) * dy / wk; } } if ( isBoundaryCell ) { // symmetry lhs.at(2, 1) = lhs.at(1, 2); // solve normal equation for volume fraction gradient lhs.solveForRhs(rhs, fvgrad); // compute unit normal fvgrad.normalize(); fvgrad.negated(); #ifdef __OOFEG /* * EASValsSetLayer(OOFEG_DEBUG_LAYER); * WCRec p[2]; * double tx = -fvgrad.at(2), ty=fvgrad.at(1); * p[0].x=xi.at(1)-tx*0.1; * p[0].y=xi.at(2)-ty*0.1; * p[1].x=xi.at(1)+tx*0.1; * p[1].y=xi.at(2)+ty*0.1; * p[0].z = p[1].z = 0.0; * GraphicObj *go = CreateLine3D(p); * EGWithMaskChangeAttributes(LAYER_MASK, go); * EMAddGraphicsToModel(ESIModel(), go); * ESIEventLoop (YES, "Cell DLS finished; Press Ctrl-p to continue"); */ #endif } else { fvgrad.zero(); } } } }
IRResultType OrthotropicLinearElasticMaterial :: initializeFrom(InputRecord *ir) { IRResultType result; // Required by IR_GIVE_FIELD macro double value; int size; FloatArray triplets; result = LinearElasticMaterial :: initializeFrom(ir); if ( result != IRRT_OK ) return result; IR_GIVE_FIELD(ir, value, _IFT_OrthotropicLinearElasticMaterial_ex); propertyDictionary.add(Ex, value); IR_GIVE_FIELD(ir, value, _IFT_OrthotropicLinearElasticMaterial_ey); propertyDictionary.add(Ey, value); IR_GIVE_FIELD(ir, value, _IFT_OrthotropicLinearElasticMaterial_ez); propertyDictionary.add(Ez, value); IR_GIVE_FIELD(ir, value, _IFT_OrthotropicLinearElasticMaterial_nyyz); propertyDictionary.add(NYyz, value); IR_GIVE_FIELD(ir, value, _IFT_OrthotropicLinearElasticMaterial_nyxz); propertyDictionary.add(NYxz, value); IR_GIVE_FIELD(ir, value, _IFT_OrthotropicLinearElasticMaterial_nyxy); propertyDictionary.add(NYxy, value); IR_GIVE_FIELD(ir, value, _IFT_OrthotropicLinearElasticMaterial_gyz); propertyDictionary.add(Gyz, value); IR_GIVE_FIELD(ir, value, _IFT_OrthotropicLinearElasticMaterial_gxz); propertyDictionary.add(Gxz, value); IR_GIVE_FIELD(ir, value, _IFT_OrthotropicLinearElasticMaterial_gxy); propertyDictionary.add(Gxy, value); IR_GIVE_FIELD(ir, value, _IFT_OrthotropicLinearElasticMaterial_talphax); propertyDictionary.add(tAlphax, value); IR_GIVE_FIELD(ir, value, _IFT_OrthotropicLinearElasticMaterial_talphay); propertyDictionary.add(tAlphay, value); IR_GIVE_FIELD(ir, value, _IFT_OrthotropicLinearElasticMaterial_talphaz); propertyDictionary.add(tAlphaz, value); // check for suspicious parameters // ask for dependent parameters (symmetry conditions) and check if reasonable /* * nyzx = this->give(NYzx); * nyzy = this->give(NYzy); * nyyx = this->give(NYyx); * if ( ( nyzx < 0. ) || ( nyzx > 0.5 ) || ( nyzy < 0. ) || ( nyzy > 0.5 ) || ( nyyx < 0. ) || ( nyyx > 0.5 ) ) { * OOFEM_WARNING("suspicious parameters", 1); * } */ // Read local coordinate system of principal axes of ortotrophy // in localCoordinateSystem the unity vectors are stored // COLUMNWISE (this is exception, but allows faster numerical // implementation) // if you wish to align local material orientation with element, use "lcs" keyword as an element parameter // try to read lcs section triplets.clear(); IR_GIVE_OPTIONAL_FIELD(ir, triplets, _IFT_OrthotropicLinearElasticMaterial_lcs); size = triplets.giveSize(); if ( !( ( size == 0 ) || ( size == 6 ) ) ) { OOFEM_WARNING("Warning: lcs in material %d is not properly defined, will be assumed as global", this->giveNumber() ); } if ( size == 6 ) { cs_type = localCS; double n1 = 0.0, n2 = 0.0; localCoordinateSystem = new FloatMatrix(3, 3); for ( int j = 1; j <= 3; j++ ) { localCoordinateSystem->at(j, 1) = triplets.at(j); n1 += triplets.at(j) * triplets.at(j); localCoordinateSystem->at(j, 2) = triplets.at(j + 3); n2 += triplets.at(j + 3) * triplets.at(j + 3); } n1 = sqrt(n1); n2 = sqrt(n2); for ( int j = 1; j <= 3; j++ ) { // normalize e1' e2' localCoordinateSystem->at(j, 1) /= n1; localCoordinateSystem->at(j, 2) /= n2; } // vector e3' computed from vector product of e1', e2' localCoordinateSystem->at(1, 3) = ( localCoordinateSystem->at(2, 1) * localCoordinateSystem->at(3, 2) - localCoordinateSystem->at(3, 1) * localCoordinateSystem->at(2, 2) ); localCoordinateSystem->at(2, 3) = ( localCoordinateSystem->at(3, 1) * localCoordinateSystem->at(1, 2) - localCoordinateSystem->at(1, 1) * localCoordinateSystem->at(3, 2) ); localCoordinateSystem->at(3, 3) = ( localCoordinateSystem->at(1, 1) * localCoordinateSystem->at(2, 2) - localCoordinateSystem->at(2, 1) * localCoordinateSystem->at(1, 2) ); } // try to read ElementCS section if ( cs_type == unknownCS ) { triplets.clear(); IR_GIVE_OPTIONAL_FIELD(ir, triplets, _IFT_OrthotropicLinearElasticMaterial_scs); // cs for shells. // first three numbers are direction of normal n - see orthoelasticmaterial.h for description // shellCS - coordinate system of principal axes is specified in shell coordinate system // this is defined as follows: principal z-axis is perpendicular to mid-section // x-axis is perpendicular to z-axis and normal to user specified vector n. // (so x-axis is parallel to plane, with n beeing normal to this plane). // y-axis is then perpendicular both to x and z axes. // WARNING: this definition of cs is valid only for plates and shells // when vector n is paralel to z-axis an error occurs and program is terminated. // size = triplets.giveSize(); if ( !( ( size == 0 ) || ( size == 3 ) ) ) { OOFEM_WARNING("scs in material %d is not properly defined, will be assumed as global", this->giveNumber() ); } if ( size == 3 ) { cs_type = shellCS; triplets.normalize(); helpPlaneNormal = new FloatArray(triplets); // // store normal defining help plane into row matrix // localCoordinateSystemmust be computed on demand from specific element // } } // if ( cs_type == unknownCS ) { // // if no cs defined assume global one // cs_type = localCS; localCoordinateSystem = new FloatMatrix(3, 3); localCoordinateSystem->beUnitMatrix(); } return IRRT_OK; }
bool XfemStructuralElementInterface :: XfemElementInterface_updateIntegrationRule() { const double tol2 = 1.0e-18; bool partitionSucceeded = false; if ( mpCZMat != NULL ) { mpCZIntegrationRules.clear(); mCZEnrItemIndices.clear(); mCZTouchingEnrItemIndices.clear(); } XfemManager *xMan = this->element->giveDomain()->giveXfemManager(); if ( xMan->isElementEnriched(element) ) { if ( mpCZMat == NULL && mCZMaterialNum > 0 ) { initializeCZMaterial(); } MaterialMode matMode = element->giveMaterialMode(); bool firstIntersection = true; std :: vector< std :: vector< FloatArray > >pointPartitions; mSubTri.clear(); std :: vector< int >enrichingEIs; int elPlaceInArray = xMan->giveDomain()->giveElementPlaceInArray( element->giveGlobalNumber() ); xMan->giveElementEnrichmentItemIndices(enrichingEIs, elPlaceInArray); for ( size_t p = 0; p < enrichingEIs.size(); p++ ) { // Index of current ei int eiIndex = enrichingEIs [ p ]; // Indices of other ei interaction with this ei through intersection enrichment fronts. std :: vector< int >touchingEiIndices; giveIntersectionsTouchingCrack(touchingEiIndices, enrichingEIs, eiIndex, * xMan); if ( firstIntersection ) { // Get the points describing each subdivision of the element double startXi, endXi; bool intersection = false; this->XfemElementInterface_prepareNodesForDelaunay(pointPartitions, startXi, endXi, eiIndex, intersection); if ( intersection ) { firstIntersection = false; // Use XfemElementInterface_partitionElement to subdivide the element for ( int i = 0; i < int ( pointPartitions.size() ); i++ ) { // Triangulate the subdivisions this->XfemElementInterface_partitionElement(mSubTri, pointPartitions [ i ]); } if ( mpCZMat != NULL ) { Crack *crack = dynamic_cast< Crack * >( xMan->giveEnrichmentItem(eiIndex) ); if ( crack == NULL ) { OOFEM_ERROR("Cohesive zones are only available for cracks.") } // We have xi_s and xi_e. Fetch sub polygon. std :: vector< FloatArray >crackPolygon; crack->giveSubPolygon(crackPolygon, startXi, endXi); /////////////////////////////////// // Add cohesive zone Gauss points size_t numSeg = crackPolygon.size() - 1; for ( size_t segIndex = 0; segIndex < numSeg; segIndex++ ) { int czRuleNum = 1; mpCZIntegrationRules.emplace_back( new GaussIntegrationRule(czRuleNum, element) ); // Add index of current ei mCZEnrItemIndices.push_back(eiIndex); // Add indices of other ei, that cause interaction through // intersection enrichment fronts mCZTouchingEnrItemIndices.push_back(touchingEiIndices); // Compute crack normal FloatArray crackTang; crackTang.beDifferenceOf(crackPolygon [ segIndex + 1 ], crackPolygon [ segIndex ]); if ( crackTang.computeSquaredNorm() > tol2 ) { crackTang.normalize(); } FloatArray crackNormal = { -crackTang.at(2), crackTang.at(1) }; mpCZIntegrationRules [ segIndex ]->SetUpPointsOn2DEmbeddedLine(mCSNumGaussPoints, matMode, crackPolygon [ segIndex ], crackPolygon [ segIndex + 1 ]); for ( GaussPoint *gp: *mpCZIntegrationRules [ segIndex ] ) { double gw = gp->giveWeight(); double segLength = crackPolygon [ segIndex ].distance(crackPolygon [ segIndex + 1 ]); gw *= 0.5 * segLength; gp->setWeight(gw); // Fetch material status and set normal StructuralInterfaceMaterialStatus *ms = dynamic_cast< StructuralInterfaceMaterialStatus * >( mpCZMat->giveStatus(gp) ); if ( ms == NULL ) { OOFEM_ERROR("Failed to fetch material status."); } ms->letNormalBe(crackNormal); // Give Gauss point reference to the enrichment item // to simplify post processing. crack->AppendCohesiveZoneGaussPoint(gp); } } } partitionSucceeded = true; } } // if(firstIntersection) else { // Loop over triangles std :: vector< Triangle >allTriCopy; for ( size_t triIndex = 0; triIndex < mSubTri.size(); triIndex++ ) { // Call alternative version of XfemElementInterface_prepareNodesForDelaunay std :: vector< std :: vector< FloatArray > >pointPartitionsTri; double startXi, endXi; bool intersection = false; XfemElementInterface_prepareNodesForDelaunay(pointPartitionsTri, startXi, endXi, mSubTri [ triIndex ], eiIndex, intersection); if ( intersection ) { // Use XfemElementInterface_partitionElement to subdivide triangle j for ( int i = 0; i < int ( pointPartitionsTri.size() ); i++ ) { this->XfemElementInterface_partitionElement(allTriCopy, pointPartitionsTri [ i ]); } // Add cohesive zone Gauss points if ( mpCZMat != NULL ) { Crack *crack = dynamic_cast< Crack * >( xMan->giveEnrichmentItem(eiIndex) ); if ( crack == NULL ) { OOFEM_ERROR("Cohesive zones are only available for cracks.") } // We have xi_s and xi_e. Fetch sub polygon. std :: vector< FloatArray >crackPolygon; crack->giveSubPolygon(crackPolygon, startXi, endXi); int numSeg = crackPolygon.size() - 1; for ( int segIndex = 0; segIndex < numSeg; segIndex++ ) { int czRuleNum = 1; mpCZIntegrationRules.emplace_back( new GaussIntegrationRule(czRuleNum, element) ); size_t newRuleInd = mpCZIntegrationRules.size() - 1; mCZEnrItemIndices.push_back(eiIndex); mCZTouchingEnrItemIndices.push_back(touchingEiIndices); // Compute crack normal FloatArray crackTang; crackTang.beDifferenceOf(crackPolygon [ segIndex + 1 ], crackPolygon [ segIndex ]); if ( crackTang.computeSquaredNorm() > tol2 ) { crackTang.normalize(); } FloatArray crackNormal = { -crackTang.at(2), crackTang.at(1) }; mpCZIntegrationRules [ newRuleInd ]->SetUpPointsOn2DEmbeddedLine(mCSNumGaussPoints, matMode, crackPolygon [ segIndex ], crackPolygon [ segIndex + 1 ]); for ( GaussPoint *gp: *mpCZIntegrationRules [ newRuleInd ] ) { double gw = gp->giveWeight(); double segLength = crackPolygon [ segIndex ].distance(crackPolygon [ segIndex + 1 ]); gw *= 0.5 * segLength; gp->setWeight(gw); // Fetch material status and set normal StructuralInterfaceMaterialStatus *ms = dynamic_cast< StructuralInterfaceMaterialStatus * >( mpCZMat->giveStatus(gp) ); if ( ms == NULL ) { OOFEM_ERROR("Failed to fetch material status."); } ms->letNormalBe(crackNormal); // Give Gauss point reference to the enrichment item // to simplify post processing. crack->AppendCohesiveZoneGaussPoint(gp); } } } } else { allTriCopy.push_back(mSubTri [ triIndex ]); } }
bool Triangle :: pointIsInTriangle(const FloatArray &iP) const { FloatArray P(iP); const double tol2 = 1.0e-18; // Compute triangle normal FloatArray p1p2; p1p2.beDifferenceOf(mVertices [ 1 ], mVertices [ 0 ]); FloatArray p1p3; p1p3.beDifferenceOf(mVertices [ 2 ], mVertices [ 0 ]); // Edge 1 FloatArray t1; t1.beDifferenceOf(mVertices [ 1 ], mVertices [ 0 ]); if(t1.computeSquaredNorm() < tol2) { // The triangle is degenerated return false; } else { t1.normalize(); } FloatArray a1; // Edge 2 FloatArray t2; t2.beDifferenceOf(mVertices [ 2 ], mVertices [ 1 ]); if(t2.computeSquaredNorm() < tol2) { // The triangle is degenerated return false; } else { t2.normalize(); } FloatArray a2; // Edge 3 FloatArray t3; t3.beDifferenceOf(mVertices [ 0 ], mVertices [ 2 ]); if(t3.computeSquaredNorm() < tol2) { // The triangle is degenerated return false; } else { t3.normalize(); } FloatArray a3; // Project point onto triangle plane FloatArray pProj = P; if( p1p2.giveSize() == 2 ) { // 2D a1 = {-t1[1], t1[0]}; a2 = {-t2[1], t2[0]}; a3 = {-t3[1], t3[0]}; } else { // 3D FloatArray N; N.beVectorProductOf(p1p2, p1p3); if(N.computeSquaredNorm() < tol2) { // The triangle is degenerated return false; } else { N.normalize(); } // Compute normal distance from triangle to point FloatArray p1p; p1p.beDifferenceOf(P, mVertices [ 0 ]); double d = p1p.dotProduct(N); pProj.add(-d, N); a1.beVectorProductOf(N, t1); // if(a1.computeSquaredNorm() < tol2) { // // The triangle is degenerated // return false; // } // else { // a1.normalize(); // } a2.beVectorProductOf(N, t2); // if(a2.computeSquaredNorm() < tol2) { // // The triangle is degenerated // return false; // } // else { // a2.normalize(); // } a3.beVectorProductOf(N, t3); // if(a3.computeSquaredNorm() < tol2) { // // The triangle is degenerated // return false; // } // else { // a3.normalize(); // } } // Check if the point is on the correct side of all edges FloatArray p1pProj; p1pProj.beDifferenceOf(pProj, mVertices [ 0 ]); if ( p1pProj.dotProduct(a1) < 0.0 ) { return false; } FloatArray p2pProj; p2pProj.beDifferenceOf(pProj, mVertices [ 1 ]); if ( p2pProj.dotProduct(a2) < 0.0 ) { return false; } FloatArray p3pProj; p3pProj.beDifferenceOf(pProj, mVertices [ 2 ]); if ( p3pProj.dotProduct(a3) < 0.0 ) { return false; } return true; }
void PolygonLine :: computeNormalSignDist(double &oDist, const FloatArray &iPoint) const { const FloatArray &point = {iPoint[0], iPoint[1]}; oDist = std :: numeric_limits< double > :: max(); int numSeg = this->giveNrVertices() - 1; // TODO: This can probably be done in a nicer way. // Ensure that we work in 2d. const int dim = 2; for ( int segId = 1; segId <= numSeg; segId++ ) { // Crack segment const FloatArray &crackP1( this->giveVertex ( segId ) ); const FloatArray &crackP2( this->giveVertex ( segId + 1 ) ); double dist2 = 0.0; if ( segId == 1 ) { // Vector from start P1 to point X FloatArray u = {point.at(1) - crackP1.at(1), point.at(2) - crackP1.at(2)}; // Line tangent vector FloatArray t = {crackP2.at(1) - crackP1.at(1), crackP2.at(2) - crackP1.at(2)}; double l2 = t.computeSquaredNorm(); if ( l2 > 0.0 ) { double l = t.normalize(); double s = dot(u, t); if ( s > l ) { // X is closest to P2 dist2 = point.distance_square(crackP2); } else { double xi = s / l; FloatArray q = ( 1.0 - xi ) * crackP1 + xi * crackP2; dist2 = point.distance_square(q); } } else { // If the points P1 and P2 coincide, // we can compute the distance to any // of these points. dist2 = point.distance_square(crackP1); } } else if ( segId == numSeg ) { // Vector from start P1 to point X FloatArray u = {point.at(1) - crackP1.at(1), point.at(2) - crackP1.at(2)}; // Line tangent vector FloatArray t = {crackP2.at(1) - crackP1.at(1), crackP2.at(2) - crackP1.at(2)}; double l2 = t.computeSquaredNorm(); if ( l2 > 0.0 ) { double l = t.normalize(); double s = dot(u, t); if ( s < 0.0 ) { // X is closest to P1 dist2 = point.distance_square(crackP1); } else { double xi = s / l; FloatArray q = ( 1.0 - xi ) * crackP1 + xi * crackP2; dist2 = point.distance_square(q); } } else { // If the points P1 and P2 coincide, // we can compute the distance to any // of these points. dist2 = point.distance_square(crackP1); } } else { double arcPos = -1.0, dummy; dist2 = point.distance_square(crackP1, crackP2, arcPos, dummy); } if ( dist2 < oDist*oDist ) { FloatArray lineToP; lineToP.beDifferenceOf(point, crackP1, dim); FloatArray t; t.beDifferenceOf(crackP2, crackP1, dim); FloatArray n = {-t.at(2), t.at(1)}; oDist = sgn( lineToP.dotProduct(n) ) * sqrt(dist2); } } }
void Quad1MindlinShell3D :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) { FloatArray n, ns; FloatMatrix dn, dns; const FloatArray &localCoords = gp->giveNaturalCoordinates(); this->interp.evaldNdx( dn, localCoords, FEIVertexListGeometryWrapper(lnodes) ); this->interp.evalN( n, localCoords, FEIVoidCellGeometry() ); answer.resize(8, 4 * 5); answer.zero(); // enforce one-point reduced integration if requested if ( this->reducedIntegrationFlag ) { FloatArray lc(2); lc.zero(); // set to element center coordinates this->interp.evaldNdx( dns, lc, FEIVertexListGeometryWrapper(lnodes) ); this->interp.evalN( ns, lc, FEIVoidCellGeometry() ); } else { dns = dn; ns = n; } // Note: This is just 5 dofs (sixth column is all zero, torsional stiffness handled separately.) for ( int i = 0; i < 4; ++i ) { ///@todo Check the rows for both parts here, to be consistent with _3dShell material definition // Part related to the membrane (columns represent coefficients for D_u, D_v) answer(0, 0 + i * 5) = dn(i, 0);//eps_x = du/dx answer(1, 1 + i * 5) = dn(i, 1);//eps_y = dv/dy answer(2, 0 + i * 5) = dn(i, 1);//gamma_xy = du/dy+dv/dx answer(2, 1 + i * 5) = dn(i, 0); // Part related to the plate (columns represent the dofs D_w, R_u, R_v) ///@todo Check sign here answer(3 + 0, 2 + 2 + i * 5) = dn(i, 0);// kappa_x = d(fi_y)/dx answer(3 + 1, 2 + 1 + i * 5) =-dn(i, 1);// kappa_y = -d(fi_x)/dy answer(3 + 2, 2 + 2 + i * 5) = dn(i, 1);// kappa_xy=d(fi_y)/dy-d(fi_x)/dx answer(3 + 2, 2 + 1 + i * 5) =-dn(i, 0); // shear strains answer(3 + 3, 2 + 0 + i * 5) = dns(i, 0);// gamma_xz = fi_y+dw/dx answer(3 + 3, 2 + 2 + i * 5) = ns(i); answer(3 + 4, 2 + 0 + i * 5) = dns(i, 1);// gamma_yz = -fi_x+dw/dy answer(3 + 4, 2 + 1 + i * 5) = -ns(i); } #if 0 // Experimental MITC4 support. // Based on "Short communication A four-node plate bending element based on mindling/reissner plate theory and a mixed interpolation" // KJ Bathe, E Dvorkin double x1, x2, x3, x4; double y1, y2, y3, y4; double Ax, Bx, Cx, Ay, By, Cy; double r = localCoords[0]; double s = localCoords[1]; x1 = lnodes[0][0]; x2 = lnodes[1][0]; x3 = lnodes[2][0]; x4 = lnodes[3][0]; y1 = lnodes[0][1]; y2 = lnodes[1][1]; y3 = lnodes[2][1]; y4 = lnodes[3][1]; Ax = x1 - x2 - x3 + x4; Bx = x1 - x2 + x3 - x4; Cx = x1 + x2 - x3 - x4; Ay = y1 - y2 - y3 + y4; By = y1 - y2 + y3 - y4; Cy = y1 + y2 - y3 - y4; FloatMatrix jac; this->interp.giveJacobianMatrixAt(jac, localCoords, FEIVertexListGeometryWrapper(lnodes) ); double detJ = jac.giveDeterminant(); double rz = sqrt( sqr(Cx + r*Bx) + sqr(Cy + r*By)) / ( 16 * detJ ); double sz = sqrt( sqr(Ax + s*Bx) + sqr(Ay + s*By)) / ( 16 * detJ ); // TODO: Not sure about this part (the reference is not explicit about these angles. / Mikael // Not sure about the transpose either. OOFEM_WARNING("The MITC4 implementation isn't verified yet. Highly experimental"); FloatArray dxdr = {jac(0,0), jac(0,1)}; dxdr.normalize(); FloatArray dxds = {jac(1,0), jac(1,1)}; dxds.normalize(); double c_b = dxdr(0); //cos(beta); double s_b = dxdr(1); //sin(beta); double c_a = dxds(0); //cos(alpha); double s_a = dxds(1); //sin(alpha); // gamma_xz = "fi_y+dw/dx" in standard formulation answer(6, 2 + 5*0) = rz * s_b * ( (1+s)) - sz * s_a * ( (1+r)); answer(6, 2 + 5*1) = rz * s_b * (-(1+s)) - sz * s_a * ( (1-r)); answer(6, 2 + 5*2) = rz * s_b * (-(1-s)) - sz * s_a * (-(1-r)); answer(6, 2 + 5*3) = rz * s_b * ( (1-s)) - sz * s_a * (-(1+r)); answer(6, 3 + 5*0) = rz * s_b * (y2-y1) * 0.5 * (1+s) - sz * s_a * (y4-y1) * 0.5 * (1+r); // tx1 answer(6, 4 + 5*0) = rz * s_b * (x1-x2) * 0.5 * (1+s) - sz * s_a * (x1-x4) * 0.5 * (1+r); // ty1 answer(6, 3 + 5*1) = rz * s_b * (y2-y1) * 0.5 * (1+s) - sz * s_a * (y3-x2) * 0.5 * (1+r); // tx2 answer(6, 4 + 5*1) = rz * s_b * (x1-x2) * 0.5 * (1+s) - sz * s_a * (x2-x3) * 0.5 * (1+r); // ty2 answer(6, 3 + 5*2) = rz * s_b * (y3-y4) * 0.5 * (1-s) - sz * s_a * (y3-y2) * 0.5 * (1-r); // tx3 answer(6, 4 + 5*2) = rz * s_b * (x4-x3) * 0.5 * (1-s) - sz * s_a * (x2-x3) * 0.5 * (1-r); // ty3 answer(6, 3 + 5*3) = rz * s_b * (y3-y4) * 0.5 * (1-s) - sz * s_a * (y4-y1) * 0.5 * (1-r); // tx4 answer(6, 4 + 5*3) = rz * s_b * (x4-x3) * 0.5 * (1-s) - sz * s_a * (x1-x4) * 0.5 * (1-r); // ty4 // gamma_yz = -fi_x+dw/dy in standard formulation answer(7, 2 + 5*0) = - rz * c_b * ( (1+s)) + sz * c_a * ( (1+r)); answer(7, 2 + 5*1) = - rz * c_b * (-(1+s)) + sz * c_a * ( (1-r)); answer(7, 2 + 5*2) = - rz * c_b * (-(1-s)) + sz * c_a * (-(1-r)); answer(7, 2 + 5*3) = - rz * c_b * ( (1-s)) + sz * c_a * (-(1+r)); answer(7, 3 + 5*0) = - rz * c_b * (y2-y1) * 0.5 * (1+s) + sz * c_a * (y4-y1) * 0.5 * (1+r); // tx1 answer(7, 4 + 5*0) = - rz * c_b * (x1-x2) * 0.5 * (1+s) + sz * c_a * (x1-x4) * 0.5 * (1+r); // ty1 answer(7, 3 + 5*1) = - rz * c_b * (y2-y1) * 0.5 * (1+s) + sz * c_a * (y3-x2) * 0.5 * (1+r); // tx2 answer(7, 4 + 5*1) = - rz * c_b * (x1-x2) * 0.5 * (1+s) + sz * c_a * (x2-x3) * 0.5 * (1+r); // ty2 answer(7, 3 + 5*2) = - rz * c_b * (y3-y4) * 0.5 * (1-s) + sz * c_a * (y3-y2) * 0.5 * (1-r); // tx3 answer(7, 4 + 5*2) = - rz * c_b * (x4-x3) * 0.5 * (1-s) + sz * c_a * (x2-x3) * 0.5 * (1-r); // ty3 answer(7, 3 + 5*3) = - rz * c_b * (y3-y4) * 0.5 * (1-s) + sz * c_a * (y4-y1) * 0.5 * (1-r); // tx4 answer(7, 4 + 5*3) = - rz * c_b * (x4-x3) * 0.5 * (1-s) + sz * c_a * (x1-x4) * 0.5 * (1-r); // ty4 #endif }
void Lattice2d :: drawSpecial(oofegGraphicContext &gc, TimeStep *tStep) { WCRec l [ 2 ]; GraphicObj *tr; GaussPoint *gp; FloatArray crackStatuses, cf; if ( !gc.testElementGraphicActivity(this) ) { return; } if ( gc.giveIntVarType() == IST_CrackState ) { gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0); this->giveIPValue(crackStatuses, gp, IST_CrackStatuses, tStep); if ( crackStatuses(0) == 1. || crackStatuses(0) == 2. || crackStatuses(0) == 3 || crackStatuses(0) == 4 ) { double x1, y1, x2, y2; x1 = this->giveNode(1)->giveCoordinate(1); y1 = this->giveNode(1)->giveCoordinate(2); x2 = this->giveNode(2)->giveCoordinate(1); y2 = this->giveNode(2)->giveCoordinate(2); //Compute normal and shear direction FloatArray normalDirection; FloatArray shearDirection; normalDirection.resize(2); normalDirection.zero(); shearDirection.resize(2); shearDirection.zero(); normalDirection.at(1) = x2 - x1; normalDirection.at(2) = y2 - y1; normalDirection.normalize(); if ( normalDirection.at(2) == 0. ) { shearDirection.at(1) = 0.; shearDirection.at(2) = 1.; } else { shearDirection.at(1) = 1.0; shearDirection.at(2) = -normalDirection.at(1) / normalDirection.at(2); } shearDirection.normalize(); l [ 0 ].x = ( FPNum ) this->gpCoords.at(1) - shearDirection.at(1) * this->width / 2.; l [ 0 ].y = ( FPNum ) this->gpCoords.at(2) - shearDirection.at(2) * this->width / 2.; l [ 0 ].z = 0.; l [ 1 ].x = ( FPNum ) this->gpCoords.at(1) + shearDirection.at(1) * this->width / 2.; ; l [ 1 ].y = ( FPNum ) this->gpCoords.at(2) + shearDirection.at(2) * this->width / 2.; l [ 1 ].z = 0.; EASValsSetLayer(OOFEG_CRACK_PATTERN_LAYER); EASValsSetLineWidth(OOFEG_CRACK_PATTERN_WIDTH); if ( ( crackStatuses(0) == 1. ) ) { EASValsSetColor( gc.getActiveCrackColor() ); } else if ( crackStatuses(0) == 2. ) { EASValsSetColor( gc.getCrackPatternColor() ); } else if ( crackStatuses(0) == 3. ) { EASValsSetColor( gc.getActiveCrackColor() ); } else if ( crackStatuses(0) == 4. ) { EASValsSetColor( gc.getActiveCrackColor() ); } tr = CreateLine3D(l); EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, tr); EMAddGraphicsToModel(ESIModel(), tr); } } }
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 }