void FE2FluidMaterial :: giveDeviatoricPressureStiffness(FloatArray &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { FE2FluidMaterialStatus *ms = static_cast<FE2FluidMaterialStatus*> (this->giveStatus(gp)); ms->computeTangents(tStep); if ( mode == TangentStiffness ) { answer = ms->giveDeviatoricPressureTangent(); #ifdef DEBUG_TANGENT // Numerical ATS for debugging FloatArray strain(3); strain.zero(); FloatArray sig, sigh; double epspvol, pressure = 0.0; double h = 1.00; // Linear problem, size of this doesn't matter. computeDeviatoricStressVector (sig, epspvol, gp, strain, pressure, tStep); computeDeviatoricStressVector (sigh, epspvol, gp, strain, pressure+h, tStep); FloatArray dsigh; dsigh.beDifferenceOf(sigh,sig); dsigh.times(1/h); printf("Analytical deviatoric pressure tangent = "); answer.printYourself(); printf("Numerical deviatoric pressure tangent = "); dsigh.printYourself(); dsigh.subtract(answer); double norm = dsigh.computeNorm(); if (norm > answer.computeNorm()*DEBUG_ERR && norm > 0.0) { OOFEM_ERROR("Error in deviatoric pressure tangent"); } #endif } else { OOFEM_ERROR("Mode not implemented"); } }
void LIBeam3dNL :: computeRotMtrx(FloatMatrix &answer, FloatArray &psi) { FloatMatrix S(3, 3), SS(3, 3); double psiSize; if ( psi.giveSize() != 3 ) { _error("computeSMtrx: psi param size mismatch"); } answer.resize(3, 3); answer.zero(); psiSize = psi.computeNorm(); answer.at(1, 1) = answer.at(2, 2) = answer.at(3, 3) = 1.; if ( psiSize <= 1.e-40 ) { return; } this->computeSMtrx(S, psi); SS.beProductOf(S, S); S.times(sin(psiSize) / psiSize); SS.times( ( 1. - cos(psiSize) ) / ( psiSize * psiSize ) ); answer.add(S); answer.add(SS); }
double ScalarErrorIndicator :: giveElementError(EE_ErrorType type, Element *elem, TimeStep *tStep) { FloatArray val; int result = 1; double sval, maxVal = 0.0; if ( type != indicatorET ) { return 0.0; } if ( this->skipRegion( elem->giveRegionNumber() ) ) { return 0.0; } for ( GaussPoint *gp: *elem->giveDefaultIntegrationRulePtr() ) { result = elem->giveIPValue(val, gp, varType, tStep); if ( result ) { sval = val.computeNorm(); if ( gp->giveNumber() == 1 ) { maxVal = sval; } else { maxVal = max(maxVal, sval); } } } return maxVal; }
void IntMatCoulombContact :: computeEngTraction(double &normalStress, FloatArray &shearStress, FloatArray &tempShearStressShift, double normalJump, const FloatArray &shearJump ) { double maxShearStress = 0.0; double shift = -this->kn * this->stiffCoeff * normalClearance; if ( normalJump + normalClearance <= 0. ) { normalStress = this->kn * ( normalJump + normalClearance ) + shift; //in compression and after the clearance gap closed maxShearStress = fabs( normalStress ) * this->frictCoeff; } else { normalStress = this->kn * this->stiffCoeff * ( normalJump + normalClearance ) + shift; maxShearStress = 0.; } if ( shearJump.giveSize() != 0 ) { shearStress = this->kn * shearJump - tempShearStressShift; double dp = shearStress.computeNorm(); double eps = 1.0e-15; // small number if ( dp > maxShearStress ) { shearStress.times( maxShearStress / ( dp + eps ) ); } tempShearStressShift = this->kn * shearJump - shearStress; } else { // 1d -> no shear stresses return; } }
double Line :: computeTangentialDistanceToEnd(FloatArray *point) { FloatArray projection; this->computeProjection(projection); FloatArray tmp; tmp.beDifferenceOf(* point, mVertices [ 1 ]); return tmp.dotProduct(projection) / projection.computeNorm(); }
double LineSurfaceTension :: SpatialLocalizerI_giveDistanceFromParametricCenter(const FloatArray &coords) { FloatArray c; c = *this->giveNode(1)->giveCoordinates(); c.add(*this->giveNode(2)->giveCoordinates()); c.times(0.5); c.subtract(coords); return c.computeNorm(); }
double FEI3dTrQuad :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { FloatArray G1, G2; // local curvilinear base vectors this->surfaceEvalBaseVectorsAt(G1, G2, lcoords, cellgeo); answer.beVectorProductOf(G1, G2); double J = answer.computeNorm(); answer.times(1 / J); return J; }
void NonlinearMassTransferMaterial :: giveFluxVector(FloatArray &answer, GaussPoint *gp, const FloatArray &grad, const FloatArray &field, TimeStep *tStep) { TransportMaterialStatus *ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); double gradPNorm = grad.computeNorm(); answer.beScaled( -(1. + C * pow(gradPNorm, alpha)), grad); ms->setTempGradient(grad); ms->setTempField(field); ms->setTempFlux(answer); }
void Line :: transformIntoPolar(FloatArray *point, FloatArray &answer) { FloatArray xp; FloatMatrix Qt; FloatArray help; this->computeTransformationMatrix(Qt); help.beDifferenceOf(* point, mVertices [ 1 ]); xp.beProductOf(Qt, help); answer.resize(2); answer.at(1) = xp.computeNorm(); answer.at(2) = atan2( xp.at(2), xp.at(1) ); }
void NonlinearMassTransferMaterial :: giveFluxVector(FloatArray &answer, GaussPoint *gp, const FloatArray &eps, TimeStep *tStep) { AnisotropicMassTransferMaterialStatus *thisMaterialStatus; thisMaterialStatus = ( ( AnisotropicMassTransferMaterialStatus * ) this->giveStatus(gp) ); thisMaterialStatus->setPressureGradient(eps); double gradPNorm = eps.computeNorm(); answer = eps; answer.times( 1 + C * pow(gradPNorm, alpha) ); answer.negated(); thisMaterialStatus->setSeepageValocity(answer); }
double ParallelContext :: localNorm(const FloatArray &src) { #ifdef __PARALLEL_MODE if ( emodel->isParallel() ) { double norm2 = 0.0, norm2_tot; int size = src.giveSize(); Natural2LocalOrdering *n2l = this->giveN2Lmap(); for ( int i = 0; i < size; i++ ) { if ( n2l->giveNewEq(i + 1) ) { norm2 += src(i) * src(i); } } MPI_Allreduce( & norm2, & norm2_tot, 1, MPI_DOUBLE, MPI_SUM, this->emodel->giveParallelComm() ); return sqrt(norm2_tot); } #endif return src.computeNorm(); }
void NonlinearMassTransferMaterial :: giveCharacteristicMatrix(FloatMatrix &answer, MatResponseForm form, MatResponseMode mode, GaussPoint *gp, TimeStep *atTime) { MaterialMode mMode = gp->giveMaterialMode(); AnisotropicMassTransferMaterialStatus *status = ( ( AnisotropicMassTransferMaterialStatus * ) this->giveStatus(gp) ); FloatArray eps = status->giveGradP(); double gradPNorm; FloatMatrix t1, t2; gradPNorm = eps.computeNorm(); t1.beDyadicProductOf(eps, eps); if ( gradPNorm != 0.0 ) { t1.times( C * alpha * pow(gradPNorm, alpha - 2) ); } switch ( mMode ) { case _1dHeat: t2.resize(1, 1); t2.at(1, 1) = 1; break; case _2dHeat: t2.resize(2, 2); t2.at(1, 1) = t2.at(2, 2) = 1; break; case _3dHeat: t2.resize(3, 3); t2.at(1, 1) = t2.at(2, 2) = t2.at(3, 3) = 1; break; default: _error2( "giveCharacteristicMatrix : unknown mode (%s)", __MaterialModeToString(mMode) ); } answer.beEmptyMtrx(); answer.add(t1); answer.add(1 + C * pow(gradPNorm, alpha), t2); }
void FE2FluidMaterial :: giveVolumetricDeviatoricStiffness(FloatArray &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { FE2FluidMaterialStatus *ms = static_cast<FE2FluidMaterialStatus*> (this->giveStatus(gp)); ms->computeTangents(tStep); if ( mode == TangentStiffness ) { answer = ms->giveVolumetricDeviatoricTangent(); #ifdef DEBUG_TANGENT // Numerical ATS for debugging FloatArray tempStrain(3); tempStrain.zero(); FloatArray sig, strain; double epspvol, epspvol11, epspvol22, epspvol12, pressure = 0.0; double h = 1.0; // Linear problem, size of this doesn't matter. computeDeviatoricStressVector (sig, epspvol, gp, tempStrain, pressure, tStep); strain = tempStrain; strain.at(1) += h; computeDeviatoricStressVector(sig, epspvol11, gp, strain, pressure, tStep); strain = tempStrain; strain.at(2) += h; computeDeviatoricStressVector(sig, epspvol22, gp, strain, pressure, tStep); strain = tempStrain; strain.at(3) += h; computeDeviatoricStressVector(sig, epspvol12, gp, strain, pressure, tStep); FloatArray dvol(3); dvol.at(1) = (epspvol11 - epspvol)/h; dvol.at(2) = (epspvol22 - epspvol)/h; dvol.at(3) = (epspvol12 - epspvol)/h; dvol.at(1) += 1.0; dvol.at(2) += 1.0; printf("Analytical volumetric deviatoric tangent = "); answer.printYourself(); printf("Numerical volumetric deviatoric tangent = "); dvol.printYourself(); dvol.subtract(answer); double norm = dvol.computeNorm(); if (norm > answer.computeNorm()*DEBUG_ERR && norm > 0.0) { OOFEM_ERROR("Error in volumetric deviatoric tangent"); } #endif } else { OOFEM_ERROR("Mode not implemented"); } }
double FEI3dTetQuad :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { IntArray snodes(3); FloatArray a,b; this->computeLocalSurfaceMapping(snodes, isurf); double l1, l2, l3; l1 = lcoords.at(1); l2 = lcoords.at(2); l3 = 1.0 - l1 - l2; FloatArray dNdxi(6), dNdeta(6); dNdxi(0) = 4.0 * l1 - 1.0; dNdxi(1) = 0.0; dNdxi(2) = -1.0 * ( 4.0 * l3 - 1.0 ); dNdxi(3) = 4.0 * l2; dNdxi(4) = -4.0 * l2; dNdxi(5) = 4.0 * l3 - 4.0 * l1; dNdeta(0) = 0.0; dNdeta(1) = 4.0 * l2 - 1.0; dNdeta(2) = -1.0 * ( 4.0 * l3 - 1.0 ); dNdeta(3) = 4.0 * l1; dNdeta(4) = 4.0 * l3 - 4.0 * l2; dNdeta(5) = -4.0 * l1; for (int i = 0; i < 6; ++i) { a.add(dNdxi(i), *cellgeo.giveVertexCoordinates(snodes(i))); b.add(dNdeta(i), *cellgeo.giveVertexCoordinates(snodes(i))); } answer.beVectorProductOf(a, b); double J = answer.computeNorm(); answer.times(1/J); return J; }
void NLTransientTransportProblem :: solveYourselfAt(TimeStep *tStep) { // creates system of governing eq's and solves them at given time step // first assemble problem at current time step // Right hand side FloatArray rhs; double solutionErr, incrementErr; int neq = this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); #ifdef VERBOSE OOFEM_LOG_RELEVANT( "Solving [step number %8d, time %15e]\n", tStep->giveNumber(), tStep->giveTargetTime() ); #endif //Delete lhs matrix and create a new one. This is necessary due to growing/decreasing number of equations. if ( tStep->isTheFirstStep() || this->changingProblemSize ) { if ( conductivityMatrix ) { delete conductivityMatrix; } conductivityMatrix = classFactory.createSparseMtrx(sparseMtrxType); if ( conductivityMatrix == NULL ) { OOFEM_ERROR("sparse matrix creation failed"); } conductivityMatrix->buildInternalStructure( this, 1, EModelDefaultEquationNumbering() ); #ifdef VERBOSE OOFEM_LOG_INFO("Assembling conductivity and capacity matrices\n"); #endif } //create previous solution from IC or from previous tStep if ( tStep->isTheFirstStep() ) { if ( !stepWhenIcApply ) { stepWhenIcApply.reset( new TimeStep( *tStep->givePreviousStep() ) ); } this->applyIC(stepWhenIcApply.get()); //insert solution to hash=1(previous), if changes in equation numbering } double dTTau = tStep->giveTimeIncrement(); double Tau = tStep->giveTargetTime() - ( 1. - alpha ) * tStep->giveTimeIncrement(); //Time step in which material laws are taken into account TimeStep TauStep(tStep->giveNumber(), this, tStep->giveMetaStepNumber(), Tau, dTTau, tStep->giveSolutionStateCounter() + 1); //Predictor FloatArray *solutionVector; UnknownsField->advanceSolution(tStep); solutionVector = UnknownsField->giveSolutionVector(tStep); //Initialize and give solutionVector from previous solution if ( changingProblemSize ) { if ( !tStep->isTheFirstStep() ) { //copy recent solution to previous position, copy from hash=0 to hash=1(previous) copyUnknownsInDictionary( VM_Total, tStep, tStep->givePreviousStep() ); } UnknownsField->initialize( VM_Total, tStep->givePreviousStep(), *solutionVector, EModelDefaultEquationNumbering() ); } else { //copy previous solution vector to actual *solutionVector = *UnknownsField->giveSolutionVector( tStep->givePreviousStep() ); } this->updateInternalState(& TauStep); //insert to hash=0(current), if changes in equation numbering FloatArray solutionVectorIncrement(neq); int nite = 0; OOFEM_LOG_INFO("Time Iter ResidNorm IncrNorm\n__________________________________________________________\n"); do { nite++; // Corrector #ifdef VERBOSE // printf("\nAssembling conductivity and capacity matrices"); #endif if ( ( nite == 1 ) || ( NR_Mode == nrsolverFullNRM ) || ( ( NR_Mode == nrsolverAccelNRM ) && ( nite % MANRMSteps == 0 ) ) ) { conductivityMatrix->zero(); //Assembling left hand side - start with conductivity matrix this->assemble( *conductivityMatrix, & TauStep, IntSourceLHSMatrix, EModelDefaultEquationNumbering(), this->giveDomain(1) ); conductivityMatrix->times(alpha); //Add capacity matrix this->assemble( *conductivityMatrix, & TauStep, NSTP_MidpointLhs, EModelDefaultEquationNumbering(), this->giveDomain(1) ); } rhs.resize(neq); rhs.zero(); //edge or surface load on element this->assembleVectorFromElements( rhs, & TauStep, ElementBCTransportVector, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); //add internal source vector on elements this->assembleVectorFromElements( rhs, & TauStep, ElementInternalSourceVector, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); //add nodal load this->assembleVectorFromDofManagers( rhs, & TauStep, ExternalForcesVector, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); // subtract the rhs part depending on previous solution assembleAlgorithmicPartOfRhs(rhs, EModelDefaultEquationNumbering(), & TauStep); // set-up numerical model this->giveNumericalMethod( this->giveCurrentMetaStep() ); // call numerical model to solve arised problem #ifdef VERBOSE //OOFEM_LOG_INFO("Solving ...\n"); #endif // compute norm of residuals from balance equations solutionErr = rhs.computeNorm(); linSolver->solve(*conductivityMatrix, rhs, solutionVectorIncrement); solutionVector->add(solutionVectorIncrement); this->updateInternalState(& TauStep); //insert to hash=0(current), if changes in equation numbering // compute error in the solutionvector increment incrementErr = solutionVectorIncrement.computeNorm(); // update solution state counter TauStep.incrementStateCounter(); tStep->incrementStateCounter(); OOFEM_LOG_INFO("%-15e %-10d %-15e %-15e\n", tStep->giveTargetTime(), nite, solutionErr, incrementErr); if ( nite >= nsmax ) { OOFEM_ERROR("convergence not reached after %d iterations", nsmax); } } while ( ( fabs(solutionErr) > rtol ) || ( fabs(incrementErr) > rtol ) ); }
void XFEMStatic :: terminate(TimeStep *tStep) { this->doStepOutput(tStep); this->printReactionForces(tStep, 1); // update load vectors before storing context fflush( this->giveOutputStream() ); this->updateLoadVectors(tStep); this->saveStepContext(tStep); // Propagate fronts for ( auto &domain: domainList ) { XfemManager *xMan = domain->giveXfemManager(); xMan->propagateFronts(); } // Update element subdivisions if necessary // (e.g. if a crack has moved and cut a new element) for ( int domInd = 1; domInd <= this->giveNumberOfDomains(); domInd++ ) { Domain *domain = this->giveDomain(domInd); // create a new set containing all elements Set elemSet(0, domain); elemSet.addAllElements(); if ( domain->giveXfemManager()->hasPropagatingFronts() || mForceRemap ) { // If domain cloning is performed, there is no need to // set values from the dof map. mSetValsFromDofMap = false; // Take copy of the domain to allow mapping of state variables // to the new Gauss points. Domain *dNew = domain->Clone(); bool deallocateOld = false; setDomain(1, dNew, deallocateOld); forceEquationNumbering(); // Map primary variables LSPrimaryVariableMapper primMapper; FloatArray u; primMapper.mapPrimaryVariables(u, * domain, * dNew, VM_Total, * tStep); if ( totalDisplacement.giveSize() == u.giveSize() ) { FloatArray diff; diff.beDifferenceOf(totalDisplacement, u); printf( "diff norm: %e\n", diff.computeNorm() ); } totalDisplacement = u; primMapper.mapPrimaryVariables(incrementOfDisplacement, * domain, * dNew, VM_Incremental, * tStep); int numEl = dNew->giveNumberOfElements(); for ( int i = 1; i <= numEl; i++ ) { //////////////////////////////////////////////////////// // Map state variables for regular Gauss points StructuralElement *el = dynamic_cast< StructuralElement * >( dNew->giveElement(i) ); el->createMaterialStatus(); el->mapStateVariables(* domain, * tStep); //////////////////////////////////////////////////////// // Map state variables for cohesive zone if applicable XfemStructuralElementInterface *xFemEl = dynamic_cast< XfemStructuralElementInterface * >(el); if ( xFemEl != NULL ) { if ( xFemEl->mpCZMat != NULL ) { size_t numCzRules = xFemEl->mpCZIntegrationRules.size(); for ( size_t czIndex = 0; czIndex < numCzRules; czIndex++ ) { if ( xFemEl->mpCZIntegrationRules [ czIndex ] != NULL ) { for ( GaussPoint *gp: *xFemEl->mpCZIntegrationRules [ czIndex ] ) { MaterialStatus *ms = xFemEl->mpCZMat->giveStatus(gp); if ( ms == NULL ) { OOFEM_ERROR("Failed to fetch material status."); } MaterialStatusMapperInterface *interface = dynamic_cast< MaterialStatusMapperInterface * > ( xFemEl->mpCZMat->giveStatus(gp) ); if ( interface == NULL ) { OOFEM_ERROR("Failed to fetch MaterialStatusMapperInterface."); } MaterialStatus *matStat = dynamic_cast< MaterialStatus * >( xFemEl->mpCZMat->giveStatus(gp) ); StructuralInterfaceMaterialStatus *siMatStat = dynamic_cast< StructuralInterfaceMaterialStatus * >(matStat); if ( siMatStat == NULL ) { OOFEM_ERROR("Failed to cast to StructuralInterfaceMaterialStatus."); } interface->MSMI_map_cz(* gp, * domain, elemSet, * tStep, * siMatStat); } } } } } } delete domain; domain = this->giveDomain(1); // Set domain pointer to various components ... this->nMethod->setDomain(domain); int numExpModules = this->exportModuleManager->giveNumberOfModules(); for ( int i = 1; i <= numExpModules; i++ ) { // ... by diving deep into the hierarchies ... :-/ VTKXMLExportModule *vtkxmlMod = dynamic_cast< VTKXMLExportModule * >( this->exportModuleManager->giveModule(i) ); if ( vtkxmlMod != NULL ) { vtkxmlMod->giveSmoother()->setDomain(domain); vtkxmlMod->givePrimVarSmoother()->setDomain(domain); } } this->setUpdateStructureFlag(true); } // if( domain->giveXfemManager()->hasPropagatingFronts() ) //#endif } // Fracture/failure mechanics evaluation for ( auto &domain: domainList ) { if ( domain->hasFractureManager() ) { // Will most likely fail if numDom > 1 FractureManager *fracMan = domain->giveFractureManager(); fracMan->evaluateYourself(tStep); fracMan->updateXFEM(tStep); // Update XFEM structure based on the fracture manager this->setUpdateStructureFlag( fracMan->giveUpdateFlag() ); // if the internal structure need to be updated } } }
void Quad10_2D_SUPG :: updateStabilizationCoeffs(TimeStep *tStep) { double Re, norm_un, mu, mu_min, nu, norm_N, norm_N_d, norm_M_d, norm_LSIC, norm_G_c, norm_M_c, norm_N_c, t_p1, t_p2, t_p3, t_s1, t_s2, t_s3, rho; FloatMatrix N, N_d, M_d, LSIC, G_c, M_c, N_c; FloatArray u; mu_min = 1; rho = this->giveMaterial()->give( 'd', integrationRulesArray [ 0 ]->getIntegrationPoint(0) ); for ( GaussPoint *gp: *integrationRulesArray [ 1 ] ) { mu = static_cast< FluidDynamicMaterial * >( this->giveMaterial() )->giveEffectiveViscosity(gp, tStep); if ( mu_min > mu ) { mu_min = mu; } } nu = mu_min / rho; //this->computeVectorOfVelocities(VM_Total, tStep->givePreviousStep(), un); this->computeVectorOfVelocities(VM_Total, tStep, u); norm_un = u.computeNorm(); this->computeAdvectionTerm(N, tStep); this->computeAdvectionDeltaTerm(N_d, tStep); this->computeMassDeltaTerm(M_d, tStep); this->computeLSICTerm(LSIC, tStep); this->computeLinearAdvectionTerm_MC(G_c, tStep); this->computeMassEpsilonTerm(M_c, tStep); this->computeAdvectionEpsilonTerm(N_c, tStep); norm_N = N.computeFrobeniusNorm(); norm_N_d = N_d.computeFrobeniusNorm(); norm_M_d = M_d.computeFrobeniusNorm(); norm_LSIC = LSIC.computeFrobeniusNorm(); norm_G_c = G_c.computeFrobeniusNorm(); norm_M_c = M_c.computeFrobeniusNorm(); norm_N_c = N_c.computeFrobeniusNorm(); if ( ( norm_N == 0 ) || ( norm_N_d == 0 ) || ( norm_M_d == 0 ) ) { t_supg = 0; } else { Re = ( norm_un / nu ) * ( norm_N / norm_N_d ); t_s1 = norm_N / norm_N_d; t_s2 = tStep->giveTimeIncrement() * ( norm_N / norm_M_d ) * 0.5; t_s3 = t_s1 * Re; t_supg = 1. / sqrt( 1. / ( t_s1 * t_s1 ) + 1. / ( t_s2 * t_s2 ) + 1. / ( t_s3 * t_s3 ) ); // t_supg = 0; } if ( norm_LSIC == 0 ) { t_lsic = 0; } else { t_lsic = norm_N / norm_LSIC; // t_lsic = 0; } if ( ( norm_G_c == 0 ) || ( norm_N_c == 0 ) || ( norm_M_c == 0 ) ) { t_pspg = 0; } else { Re = ( norm_un / nu ) * ( norm_N / norm_N_d ); t_p1 = norm_G_c / norm_N_c; t_p2 = tStep->giveTimeIncrement() * ( norm_G_c / norm_M_c ) * 0.5; t_p3 = t_p1 * Re; t_pspg = 1. / sqrt( 1. / ( t_p1 * t_p1 ) + 1. / ( t_p2 * t_p2 ) + 1. / ( t_p3 * t_p3 ) ); // t_pspg = 0; } //t_pspg = 0; }
void FE2FluidMaterial :: giveStiffnessMatrices(FloatMatrix &dsdd, FloatArray &dsdp, FloatArray &dedd, double &dedp, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { FE2FluidMaterialStatus *ms = static_cast< FE2FluidMaterialStatus * >( this->giveStatus(gp) ); ms->computeTangents(tStep); if ( mode == TangentStiffness ) { dsdd = ms->giveDeviatoricTangent(); dsdp = ms->giveDeviatoricPressureTangent(); dedd = ms->giveVolumetricDeviatoricTangent(); dedp = ms->giveVolumetricPressureTangent(); #if 0 // Numerical ATS for debugging FloatMatrix numericalATS(6, 6); FloatArray dsig; FloatArray tempStrain(6); tempStrain.zero(); FloatArray sig, strain, sigPert; double epspvol; computeDeviatoricStressVector(sig, epspvol, gp, tempStrain, 0., tStep); double h = 0.001; // Linear problem, size of this doesn't matter. for ( int k = 1; k <= 6; ++k ) { strain = tempStrain; strain.at(k) += h; double tmp = strain.at(1) + strain.at(2) + strain.at(3); strain.at(1) -= tmp/3.0; strain.at(2) -= tmp/3.0; strain.at(3) -= tmp/3.0; strain.printYourself(); computeDeviatoricStressVector(sigPert, epspvol, gp, strain, 0., tStep); sigPert.printYourself(); dsig.beDifferenceOf(sigPert, sig); numericalATS.setColumn(dsig, k); } numericalATS.times(1. / h); printf("Analytical deviatoric tangent = "); dsdd.printYourself(); printf("Numerical deviatoric tangent = "); numericalATS.printYourself(); numericalATS.subtract(dsdd); double norm = numericalATS.computeFrobeniusNorm(); if ( norm > dsdd.computeFrobeniusNorm() * DEBUG_ERR && norm > 0.0 ) { OOFEM_ERROR("Error in deviatoric tangent"); } #endif #if 0 // Numerical ATS for debugging FloatArray strain(3); strain.zero(); FloatArray sig, sigh; double epspvol, pressure = 0.0; double h = 1.00; // Linear problem, size of this doesn't matter. computeDeviatoricStressVector(sig, epspvol, gp, strain, pressure, tStep); computeDeviatoricStressVector(sigh, epspvol, gp, strain, pressure + h, tStep); FloatArray dsigh; dsigh.beDifferenceOf(sigh, sig); dsigh.times(1 / h); printf("Analytical deviatoric pressure tangent = "); dsdp.printYourself(); printf("Numerical deviatoric pressure tangent = "); dsigh.printYourself(); dsigh.subtract(dsdp); double norm = dsigh.computeNorm(); if ( norm > dsdp.computeNorm() * DEBUG_ERR && norm > 0.0 ) { OOFEM_ERROR("Error in deviatoric pressure tangent"); } #endif #if 0 // Numerical ATS for debugging FloatArray tempStrain(3); tempStrain.zero(); FloatArray sig, strain; double epspvol, epspvol11, epspvol22, epspvol12, pressure = 0.0; double h = 1.0; // Linear problem, size of this doesn't matter. computeDeviatoricStressVector(sig, epspvol, gp, tempStrain, pressure, tStep); strain = tempStrain; strain.at(1) += h; computeDeviatoricStressVector(sig, epspvol11, gp, strain, pressure, tStep); strain = tempStrain; strain.at(2) += h; computeDeviatoricStressVector(sig, epspvol22, gp, strain, pressure, tStep); strain = tempStrain; strain.at(3) += h; computeDeviatoricStressVector(sig, epspvol12, gp, strain, pressure, tStep); FloatArray dvol(3); dvol.at(1) = ( epspvol11 - epspvol ) / h; dvol.at(2) = ( epspvol22 - epspvol ) / h; dvol.at(3) = ( epspvol12 - epspvol ) / h; dvol.at(1) += 1.0; dvol.at(2) += 1.0; printf("Analytical volumetric deviatoric tangent = "); dedd.printYourself(); printf("Numerical volumetric deviatoric tangent = "); dvol.printYourself(); dvol.subtract(dedd); double norm = dvol.computeNorm(); if ( norm > dedd.computeNorm() * DEBUG_ERR && norm > 0.0 ) { OOFEM_ERROR("Error in volumetric deviatoric tangent"); } #endif #if 0 // Numerical ATS for debugging FloatArray strain(3); strain.zero(); FloatArray sig; double epspvol, epspvolh, pressure = 0.0; double h = 1.0; // Linear problem, size of this doesn't matter. computeDeviatoricStressVector(sig, epspvol, gp, strain, pressure, tStep); computeDeviatoricStressVector(sig, epspvolh, gp, strain, pressure + h, tStep); double dvol = -( epspvolh - epspvol ) / h; printf("Analytical volumetric pressure tangent = %e\n", dedp); printf("Numerical volumetric pressure tangent = %e\n", dvol); double norm = fabs(dvol - dedp); if ( norm > fabs(dedp) * DEBUG_ERR && norm > 0.0 ) { OOFEM_ERROR("Error in volumetric pressure tangent"); } #endif } else { OOFEM_ERROR("Mode not implemented"); } }
double BasicGeometry :: computeLineDistance(const FloatArray &iP1, const FloatArray &iP2, const FloatArray &iQ1, const FloatArray &iQ2) { FloatArray u; u.beDifferenceOf(iP2, iP1); const double LengthP = u.computeNorm(); FloatArray v; v.beDifferenceOf(iQ2, iQ1); const double LengthQ = v.computeNorm(); // Regularization coefficients (to make it possible to solve when lines are parallel) const double c1 = (1.0e-14)*LengthP*LengthP; const double c2 = (1.0e-14)*LengthQ*LengthQ; const size_t minIter = 2; const size_t maxIter = 5; const double absTol = 1.0e-12; double xi = 0.0, eta = 0.0; FloatArray d; d = iP1; d.add(xi,u); d.add(-1.0, iQ1); d.add(-eta, v); FloatMatrix K(2,2), KInv; FloatArray dXi; bool lockXi = false, lockEta = false; for(size_t iter = 0; iter < maxIter; iter++) { if(xi < 0.0) { xi = 0.0; lockXi = true; } if(xi > 1.0) { xi = 1.0; lockXi = true; } if(eta < 0.0) { eta = 0.0; lockEta = true; } if(eta > 1.0) { eta = 1.0; lockEta = true; } FloatArray R = { d.dotProduct(u) + c1*xi, -d.dotProduct(v) + c2*eta}; if(lockXi) { R[0] = 0.0; } if(lockEta) { R[1] = 0.0; } const double res = R.computeNorm(); // printf("iter: %lu res: %e\n", iter, res); if(res < absTol && iter >= minIter) { // printf("xi: %e eta: %e\n", xi, eta); break; } K(0,0) = -u.dotProduct(u)-c1; K(0,1) = u.dotProduct(v); K(1,0) = u.dotProduct(v); K(1,1) = -v.dotProduct(v)-c2; if(lockXi) { K(0,0) = -1.0; K(0,1) = K(1,0) = 0.0; } if(lockEta) { K(0,1) = K(1,0) = 0.0; K(1,1) = -1.0; } KInv.beInverseOf(K); dXi.beProductOf(KInv, R); xi += dXi[0]; eta += dXi[1]; d = iP1; d.add(xi,u); d.add(-1.0, iQ1); d.add(-eta, v); } if(xi < 0.0) { xi = 0.0; } if(xi > 1.0) { xi = 1.0; } if(eta < 0.0) { eta = 0.0; } if(eta > 1.0) { eta = 1.0; } d = iP1; d.add(xi,u); d.add(-1.0, iQ1); d.add(-eta, v); const double dist = d.computeNorm(); return dist; }
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 }
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; }