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 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; }
void FreeWarping :: computeResultAtCenterOfGravity(TimeStep *tStep) { int noCS = this->giveDomain(1)->giveNumberOfCrossSectionModels(); //number of warping Crosssections SolutionAtCG.resize(noCS); Element *closestElement; FloatArray lcoords, closest, lcg; SpatialLocalizer *sp = this->giveDomain(1)->giveSpatialLocalizer(); sp->init(); lcoords.resize(2); closest.resize(2); lcg.resize(2); for ( int j = 1; j <= noCS; ++j ) { lcg.at(1) = CG.at(j, 1); lcg.at(2) = CG.at(j, 2); closestElement = sp->giveElementClosestToPoint(lcoords, closest, lcg, 0); StructuralElement *sE = dynamic_cast< StructuralElement * >(closestElement); FloatArray u, r, b; FloatMatrix N; sE->computeNmatrixAt(lcoords, N); sE->computeVectorOf(VM_Total, tStep, u); u.resizeWithValues(3); r.beProductOf(N, u); SolutionAtCG.at(j) = r.at(1); } }
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; }
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 POIExportModule :: exportPrimVarAs(UnknownType valID, FILE *stream, TimeStep *tStep) { Domain *d = emodel->giveDomain(1); FloatArray pv, coords(3), lcoords, closest; InternalStateValueType type = ISVT_UNDEFINED; if ( valID == DisplacementVector ) { type = ISVT_VECTOR; } else if ( valID == FluxVector ) { type = ISVT_SCALAR; } else { OOFEM_ERROR("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 { OOFEM_ERROR("unsupported variable type"); } SpatialLocalizer *sl = d->giveSpatialLocalizer(); // loop over POIs for ( auto &poi: POIList ) { coords.at(1) = poi.x; coords.at(3) = poi.z; //region = poi.region; Element *source = sl->giveElementClosestToPoint(lcoords, closest, coords); if ( source ) { // ask interface EIPrimaryUnknownMapperInterface *interface = static_cast< EIPrimaryUnknownMapperInterface * >( source->giveInterface(EIPrimaryUnknownMapperInterfaceType) ); if ( interface ) { interface->EIPrimaryUnknownMI_computePrimaryUnknownVectorAtLocal(VM_Total, tStep, lcoords, pv); } else { pv.clear(); OOFEM_WARNING("element %d with no EIPrimaryUnknownMapperInterface support", source->giveNumber() ); } fprintf(stream, "%10d ", poi.id); if ( pv.giveSize() ) { for ( int j = 1; j <= pv.giveSize(); j++ ) { fprintf( stream, " %15e ", pv.at(j) ); } } fprintf(stream, "\n"); } else { OOFEM_ERROR("no element containing POI(%e,%e,%e) found", coords.at(1), coords.at(2), coords.at(3) ); } } }
void Delamination :: findInitiationFronts(bool &failureChecked, const IntArray &CSnumbers, std :: vector< IntArray > &CSinterfaceNumbers, std :: vector< IntArray > &CSDofManNumbers, std :: vector< FloatArray > &initiationFactors, TimeStep *tStep) { // Loop through all cross sections associated with delaminations // Returns // CSinterfaceNumbers: the failed interface number associated with the cross sections. // CSDofManNumbers: the dofmanagers that should be enriched (associated with the cross sections) IntArray failedElementInterfaces; IntArray elementNumbers; SpatialLocalizer *localizer = this->giveDomain()->giveSpatialLocalizer(); // NB: Assumes that elements can only be included in one cross section. for ( int iCS = 1 ; iCS <= CSnumbers.giveSize() ; iCS++ ) { int eltSetNumber = this->giveDomain()->giveCrossSection(CSnumbers.at(iCS))->giveSetNumber(); //printf("Cross section No. %i, set No. %i \n",CSnumbers.at(iCS),eltSetNumber); IntArray elementNumbers = this->giveDomain()->giveSet(eltSetNumber)->giveElementList(); for ( auto eltNumber : elementNumbers ) { Element *elt = this->giveDomain()->giveGlobalElement(eltNumber); if ( Shell7BaseXFEM *shellElt = dynamic_cast < Shell7BaseXFEM * > (elt) ) { //bool recoverStresses = true; shellElt->giveFailedInterfaceNumber(failedElementInterfaces, initiationFactors[iCS-1], tStep, this->recoverStresses); //failedElementInterfaces.printYourself("failedElementInterfaces"); for (int eltInt : failedElementInterfaces ) { CSinterfaceNumbers[iCS-1].insertSortedOnce(eltInt); } if ( !failedElementInterfaces.isEmpty() ) { for (int iDF : shellElt->giveDofManArray() ) { //printf("element node %d \n",iDF); if ( this->initiationRadius > 0.0 ) { const FloatArray gCoords = this->giveDomain()->giveNode(iDF)->giveNodeCoordinates(); std :: list< int > nodeList; localizer->giveAllNodesWithinBox(nodeList,gCoords,initiationRadius); for ( int jNode : nodeList ) { //printf("nodeList node %d \n",jNode); CSDofManNumbers[iCS-1].insertSortedOnce(jNode); } } else { CSDofManNumbers[iCS-1].insertSortedOnce(iDF); } } } } } } failureChecked = true; }
void PrescribedGradientBCWeak :: assembleTangentGPContributionNew(FloatMatrix &oTangent, TracSegArray &iEl, GaussPoint &iGP, const double &iScaleFactor, const FloatArray &iBndCoord) { int dim = domain->giveNumberOfSpatialDimensions(); double detJ = 0.5 * iEl.giveLength(); ////////////////////////////////// // Compute traction N-matrix // For now, assume piecewise constant approx FloatArray Ntrac = FloatArray { 1.0 }; FloatMatrix NtracMat; NtracMat.beNMatrixOf(Ntrac, dim); ////////////////////////////////// // Compute displacement N-matrix // Identify the displacement element // we are currently standing in // and compute local coordinates on // the displacement element SpatialLocalizer *localizer = domain->giveSpatialLocalizer(); FloatArray dispElLocCoord, closestPoint; Element *dispEl = localizer->giveElementClosestToPoint(dispElLocCoord, closestPoint, iBndCoord ); // Compute basis functions XfemElementInterface *xfemElInt = dynamic_cast< XfemElementInterface * >( dispEl ); FloatMatrix NdispMat; if ( xfemElInt != NULL && domain->hasXfemManager() ) { // If the element is an XFEM element, we use the XfemElementInterface to compute the N-matrix // of the enriched element. xfemElInt->XfemElementInterface_createEnrNmatrixAt(NdispMat, dispElLocCoord, * dispEl, false); } else { // Otherwise, use the usual N-matrix. const int numNodes = dispEl->giveNumberOfDofManagers(); FloatArray N(numNodes); const int dim = dispEl->giveSpatialDimension(); NdispMat.resize(dim, dim * numNodes); NdispMat.zero(); dispEl->giveInterpolation()->evalN( N, dispElLocCoord, FEIElementGeometryWrapper(dispEl) ); NdispMat.beNMatrixOf(N, dim); } FloatMatrix contrib; contrib.beTProductOf(NtracMat, NdispMat); contrib.times( iScaleFactor * detJ * iGP.giveWeight() ); oTangent = contrib; }
void POIExportModule :: exportPrimVarAs(UnknownType valID, FILE *stream, TimeStep *tStep) { Domain *d = emodel->giveDomain(1); FloatArray pv, coords(3), lcoords, closest; InternalStateValueType type = ISVT_UNDEFINED; if ( valID == DisplacementVector ) { type = ISVT_VECTOR; } else if ( valID == FluxVector || valID == Humidity ) { type = ISVT_SCALAR; } else { OOFEM_ERROR("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 { OOFEM_ERROR("unsupported variable type"); } SpatialLocalizer *sl = d->giveSpatialLocalizer(); // loop over POIs for ( auto &poi: POIList ) { coords.at(1) = poi.x; coords.at(3) = poi.z; //region = poi.region; Element *source = sl->giveElementClosestToPoint(lcoords, closest, coords); if ( source ) { // ask interface source->computeField(VM_Total, tStep, lcoords, pv); fprintf(stream, "%10d ", poi.id); for ( auto &p : pv ) { fprintf( stream, " %15e ", p ); } fprintf(stream, "\n"); } else { OOFEM_ERROR("no element containing POI(%e,%e,%e) found", coords.at(1), coords.at(2), coords.at(3) ); } } }
void MMAClosestIPTransfer :: __init(Domain *dold, IntArray &type, FloatArray &coords, Set &elemSet, TimeStep *tStep, bool iCohesiveZoneGP) { SpatialLocalizer *sl = dold->giveSpatialLocalizer(); this->source = sl->giveClosestIP(coords, elemSet, iCohesiveZoneGP); if ( !source ) { OOFEM_ERROR("no suitable source found"); } mpMaterialStatus = dynamic_cast<MaterialStatus*>(source->giveMaterialStatus()); if( mpMaterialStatus == NULL ) { OOFEM_ERROR("Could not find material status."); } }
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(); 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; } interface = static_cast< EIPrimaryUnknownMapperInterface * >( oelem->giveInterface(EIPrimaryUnknownMapperInterfaceType) ); if ( interface ) { oelem->giveElementDofIDMask(dofMask); interface->EIPrimaryUnknownMI_computePrimaryUnknownVectorAtLocal(mode, tStep, lcoords, answer); } else { OOFEM_ERROR("Element does not support EIPrimaryUnknownMapperInterface"); } return true; }
void PrescribedGradientBCWeak :: computeIntForceGPContrib(FloatArray &oContrib_disp, IntArray &oDisp_loc_array, FloatArray &oContrib_trac, IntArray &oTrac_loc_array,TracSegArray &iEl, GaussPoint &iGP, int iDim, TimeStep *tStep, const FloatArray &iBndCoord, const double &iScaleFac, ValueModeType mode, CharType type, const UnknownNumberingScheme &s) { SpatialLocalizer *localizer = domain->giveSpatialLocalizer(); FloatMatrix contrib; assembleTangentGPContributionNew(contrib, iEl, iGP, iScaleFac, iBndCoord); // Compute vector of traction unknowns FloatArray tracUnknowns; iEl.mFirstNode->giveUnknownVector(tracUnknowns, giveTracDofIDs(), mode, tStep); iEl.giveTractionLocationArray(oTrac_loc_array, type, s); FloatArray dispElLocCoord, closestPoint; Element *dispEl = localizer->giveElementClosestToPoint(dispElLocCoord, closestPoint, iBndCoord ); // Compute vector of displacement unknowns FloatArray dispUnknowns; int numDMan = dispEl->giveNumberOfDofManagers(); for(int i = 1; i <= numDMan; i++) { FloatArray nodeUnknowns; DofManager *dMan = dispEl->giveDofManager(i); IntArray dispIDs = giveRegularDispDofIDs(); if(domain->hasXfemManager()) { XfemManager *xMan = domain->giveXfemManager(); dispIDs.followedBy(xMan->giveEnrichedDofIDs(*dMan)); } dMan->giveUnknownVector(nodeUnknowns, dispIDs,mode, tStep); dispUnknowns.append(nodeUnknowns); } dispEl->giveLocationArray(oDisp_loc_array, s); oContrib_disp.beTProductOf(contrib, tracUnknowns); oContrib_disp.negated(); oContrib_trac.beProductOf(contrib, dispUnknowns); oContrib_trac.negated(); }
void PrescribedGradientBCPeriodic :: findSlaveToMasterMap() { FloatArray coord; SpatialLocalizer *sl = this->domain->giveSpatialLocalizer(); //Set *masterSet = this->domain->giveSet(2); const IntArray &nodes = this->domain->giveSet(this->set)->giveNodeList(); // Split into slave set and master set? int nsd = jump.giveSize(); std :: vector< FloatArray > jumps; // Construct all the possible jumps; jumps.reserve((2 << (nsd-1)) - 1); if ( nsd != 3 ) { OOFEM_ERROR("Only 3d implemented yet!"); } jumps.emplace_back(jump); jumps.emplace_back(FloatArray{jump.at(1), jump.at(2), 0.}); jumps.emplace_back(FloatArray{jump.at(1), 0., jump.at(3)}); jumps.emplace_back(FloatArray{0., jump.at(2), jump.at(3)}); jumps.emplace_back(FloatArray{jump.at(1), 0., 0.}); jumps.emplace_back(FloatArray{0., jump.at(2), 0.}); jumps.emplace_back(FloatArray{0., 0., jump.at(3)}); this->slavemap.clear(); for ( int inode : nodes ) { Node *masterNode = NULL; Node *node = this->domain->giveNode(inode); const FloatArray &masterCoord = *node->giveCoordinates(); //printf("node %d\n", node->giveLabel()); masterCoord.printYourself(); // The difficult part, what offset to subtract to find the master side; for ( FloatArray &testJump : jumps ) { coord.beDifferenceOf(masterCoord, testJump); masterNode = sl->giveNodeClosestToPoint(coord, fabs(jump.at(1))*1e-5); if ( masterNode != NULL ) { //printf("Found master (%d) to node %d (distance = %e)\n", masterNode->giveNumber(), node->giveNumber(), // masterNode->giveCoordinates()->distance(coord)); break; } } if ( masterNode != NULL ) { this->slavemap.insert({node->giveNumber(), masterNode->giveNumber()}); } else { OOFEM_ERROR("Couldn't find master node!"); } } }
bool PLnodeRadius :: propagateInterface(Domain &iDomain, EnrichmentFront &iEnrFront, TipPropagation &oTipProp) { if ( !iEnrFront.propagationIsAllowed() ) { printf("EnrichmentFront.propagationIsAllowed is false \n"); return false; } const TipInfo &tipInfo = iEnrFront.giveTipInfo(); // includes the dofman numbers which represent the boundary of the EI. //tipInfo.mTipDofManNumbers.printYourself(); // No listbased tip (or EI) present, so nothing to propagate. if ( tipInfo.mTipDofManNumbers.giveSize() == 0 ) { printf("No dofmans in tip; nothing to propagate. \n"); return false; } // Localise nodes within certain radius from tip nodes oTipProp.mPropagationDofManNumbers.clear(); SpatialLocalizer *localizer = iDomain.giveSpatialLocalizer(); for ( int i = 1 ; i <= tipInfo.mTipDofManNumbers.giveSize() ; i++ ) { //DofManager *dofMan = iDomain.giveDofManager(tipInfo.mTipDofManNumbers.at(i)); //const FloatArray gCoords = dofMan->giveCoordinates(); Node *iNode = iDomain.giveNode(tipInfo.mTipDofManNumbers.at(i)); const FloatArray gCoords = iNode->giveNodeCoordinates(); std :: list< int > nodeList; localizer->giveAllNodesWithinBox(nodeList,gCoords,mRadius); for ( int jNode : nodeList ) { //printf("nodeList node %d \n",jNode); oTipProp.mPropagationDofManNumbers.insertSortedOnce(jNode); } } //oTipProp.mPropagationDofManNumbers.printYourself(" The following noded will be propagated to:"); return true; }
bool PLMaterialForce :: propagateInterface(Domain &iDomain, EnrichmentFront &iEnrFront, TipPropagation &oTipProp) { // printf("Entering PLMaterialForce :: propagateInterface().\n"); if ( !iEnrFront.propagationIsAllowed() ) { return false; } // Fetch crack tip data const TipInfo &tipInfo = iEnrFront.giveTipInfo(); // Check if the tip is located in the domain SpatialLocalizer *localizer = iDomain.giveSpatialLocalizer(); FloatArray lCoords, closest; // printf("tipInfo.mGlobalCoord: \n"); tipInfo.mGlobalCoord.printYourself(); if( tipInfo.mGlobalCoord.giveSize() == 0 ) { return false; } localizer->giveElementClosestToPoint(lCoords, closest, tipInfo.mGlobalCoord); if(closest.distance(tipInfo.mGlobalCoord) > 1.0e-9) { // printf("Tip is outside all elements.\n"); return false; } FloatArray matForce; TimeStep *tStep = iDomain.giveEngngModel()->giveCurrentStep(); mpMaterialForceEvaluator->computeMaterialForce(matForce, iDomain, tipInfo, tStep, mRadius); // printf("matForce: "); matForce.printYourself(); if(matForce.giveSize() == 0) { return false; } double forceNorm = matForce.computeNorm(); // printf("forceNorm: %e mCrackPropThreshold: %e\n", forceNorm, mCrackPropThreshold); if(forceNorm < mCrackPropThreshold || forceNorm < 1.0e-20) { return false; } printf("forceNorm: %e mCrackPropThreshold: %e\n", forceNorm, mCrackPropThreshold); printf("Propagating crack in PLMaterialForce :: propagateInterface.\n"); // printf("Tip coord: "); tipInfo.mGlobalCoord.printYourself(); FloatArray dir(matForce); dir.times(1.0/forceNorm); // printf("dir: "); dir.printYourself(); const double cosAngTol = 1.0/sqrt(2.0); if(tipInfo.mTangDir.dotProduct(dir) < cosAngTol) { // Do not allow sharper turns than 45 degrees if( tipInfo.mNormalDir.dotProduct(dir) > 0.0 ) { dir = tipInfo.mTangDir; dir.add(tipInfo.mNormalDir); dir.normalize(); } else { // dir = tipInfo.mNormalDir; // dir.times(-1.0); dir = tipInfo.mTangDir; dir.add(-1.0,tipInfo.mNormalDir); dir.normalize(); } printf("//////////////////////////////////////////// Resticting crack propagation direction.\n"); // printf("tipInfo.mTangDir: "); tipInfo.mTangDir.printYourself(); // printf("dir: "); dir.printYourself(); } // Fill up struct 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 }
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 }
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; }
void HangingNode :: postInitialize() { Node :: postInitialize(); Element *e; FEInterpolation *fei; FloatArray lcoords, masterContribution; #ifdef __OOFEG if ( initialized ) { return; } initialized = true; #endif // First check element and interpolation if ( masterElement == -1 ) { // Then we find it by taking the closest (probably containing element) FloatArray closest; SpatialLocalizer *sp = this->domain->giveSpatialLocalizer(); sp->init(); // Closest point or containing point? It should be contained, but with numerical errors it might be slightly outside // so the closest point is more robust. if ( !( e = sp->giveElementClosestToPoint(lcoords, closest, coordinates, this->masterRegion) ) ) { OOFEM_ERROR("Couldn't find closest element (automatically)."); } this->masterElement = e->giveNumber(); } else if ( !( e = this->giveDomain()->giveElement(this->masterElement) ) ) { OOFEM_ERROR("Requested element %d doesn't exist.", this->masterElement); } if ( !( fei = e->giveInterpolation() ) ) { OOFEM_ERROR("Requested element %d doesn't have a interpolator.", this->masterElement); } if ( lcoords.giveSize() == 0 ) { // we don't need to do this again if the spatial localizer was used. fei->global2local( lcoords, coordinates, FEIElementGeometryWrapper(e) ); } // Initialize slave dofs (inside check of consistency of receiver and master dof) const IntArray &masterNodes = e->giveDofManArray(); for ( Dof *dof: *this ) { SlaveDof *sdof = dynamic_cast< SlaveDof * >(dof); if ( sdof ) { DofIDItem id = sdof->giveDofID(); fei = e->giveInterpolation(id); if ( !fei ) { OOFEM_ERROR("Requested interpolation for dof id %d doesn't exist in element %d.", id, this->masterElement); } #if 0 // This won't work (yet), as it requires some more general FEI classes, or something similar. if ( fei->hasMultiField() ) { FloatMatrix multiContribution; IntArray masterDofIDs, masterNodesDup, dofids; fei->evalMultiN(multiContribution, dofids, lcoords, FEIElementGeometryWrapper(e), 0.0); masterContribution.flatten(multiContribution); masterDofIDs.clear(); for ( int i = 0; i <= multiContribution.giveNumberOfColumns(); ++i ) { masterDofIDs.followedBy(dofids); masterNodesDup.followedBy(masterNodes); } sdof->initialize(masterNodesDup, & masterDofIDs, masterContribution); } else { } #else // Note: There can be more masterNodes than masterContributions, since all the // FEI classes are based on that the first nodes correspond to the simpler/linear interpolation. // If this assumption is changed in FEIElementGeometryWrapper + friends, // masterNode will also need to be modified for each dof accordingly. fei->evalN( masterContribution, lcoords, FEIElementGeometryWrapper(e) ); sdof->initialize(masterNodes, IntArray(), masterContribution); #endif } } }
void PrescribedGradientBCWeak :: assembleGPContrib(SparseMtrx &answer, TimeStep *tStep, CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, TracSegArray &iEl, GaussPoint &iGP) { SpatialLocalizer *localizer = domain->giveSpatialLocalizer(); /////////////// // Gamma_plus FloatMatrix contrib; assembleTangentGPContributionNew(contrib, iEl, iGP, -1.0, iGP.giveGlobalCoordinates()); // Compute vector of traction unknowns FloatArray tracUnknowns; iEl.mFirstNode->giveUnknownVector(tracUnknowns, giveTracDofIDs(), VM_Total, tStep); IntArray trac_rows; iEl.giveTractionLocationArray(trac_rows, type, r_s); FloatArray dispElLocCoord, closestPoint; Element *dispEl = localizer->giveElementClosestToPoint(dispElLocCoord, closestPoint, iGP.giveGlobalCoordinates() ); IntArray disp_cols; dispEl->giveLocationArray(disp_cols, c_s); answer.assemble(trac_rows, disp_cols, contrib); FloatMatrix contribT; contribT.beTranspositionOf(contrib); answer.assemble(disp_cols, trac_rows, contribT); /////////////// // Gamma_minus contrib.clear(); FloatArray xMinus; this->giveMirroredPointOnGammaMinus(xMinus, iGP.giveGlobalCoordinates() ); assembleTangentGPContributionNew(contrib, iEl, iGP, 1.0, xMinus); // Compute vector of traction unknowns tracUnknowns.clear(); iEl.mFirstNode->giveUnknownVector(tracUnknowns, giveTracDofIDs(), VM_Total, tStep); trac_rows.clear(); iEl.giveTractionLocationArray(trac_rows, type, r_s); dispElLocCoord.clear(); closestPoint.clear(); dispEl = localizer->giveElementClosestToPoint(dispElLocCoord, closestPoint, xMinus ); disp_cols.clear(); dispEl->giveLocationArray(disp_cols, c_s); answer.assemble(trac_rows, disp_cols, contrib); contribT.clear(); contribT.beTranspositionOf(contrib); answer.assemble(disp_cols, trac_rows, contribT); // Assemble zeros on diagonal (required by PETSc solver) FloatMatrix KZero(1,1); KZero.zero(); for( int i : trac_rows) { answer.assemble(IntArray({i}), IntArray({i}), KZero); } }