void StructuralFE2Material :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { if ( useNumTangent ) { // Numerical tangent StructuralFE2MaterialStatus *status = static_cast<StructuralFE2MaterialStatus*>( this->giveStatus( gp ) ); double h = 1.0e-9; const FloatArray &epsRed = status->giveTempStrainVector(); FloatArray eps; StructuralMaterial::giveFullSymVectorForm(eps, epsRed, gp->giveMaterialMode() ); int dim = eps.giveSize(); answer.resize(dim, dim); answer.zero(); FloatArray sig, sigPert, epsPert; for(int i = 1; i <= dim; i++) { // Add a small perturbation to the strain epsPert = eps; epsPert.at(i) += h; giveRealStressVector_3d(sigPert, gp, epsPert, tStep); answer.setColumn(sigPert, i); } giveRealStressVector_3d(sig, gp, eps, tStep); for(int i = 1; i <= dim; i++) { for(int j = 1; j <= dim; j++) { answer.at(j,i) -= sig.at(j); answer.at(j,i) /= h; } } } else { StructuralFE2MaterialStatus *ms = static_cast< StructuralFE2MaterialStatus * >( this->giveStatus(gp) ); ms->computeTangent(tStep); const FloatMatrix &ans9 = ms->giveTangent(); StructuralMaterial::giveReducedSymMatrixForm(answer, ans9, _3dMat); // const FloatMatrix &ans9 = ms->giveTangent(); // printf("ans9: "); ans9.printYourself(); // // // Compute the (minor) symmetrized tangent: // answer.resize(6, 6); // for ( int i = 0; i < 6; ++i ) { // for ( int j = 0; j < 6; ++j ) { // answer(i, j) = ans9(i, j); // } // } // for ( int i = 0; i < 6; ++i ) { // for ( int j = 6; j < 9; ++j ) { // answer(i, j-3) += ans9(i, j); // answer(j-3, i) += ans9(j, i); // } // } // for ( int i = 6; i < 9; ++i ) { // for ( int j = 6; j < 9; ++j ) { // answer(j-3, i-3) += ans9(j, i); // } // } // for ( int i = 0; i < 6; ++i ) { // for ( int j = 3; j < 6; ++j ) { // answer(j, i) *= 0.5; // answer(i, j) *= 0.5; // } // } #if 0 // Numerical ATS for debugging FloatMatrix numericalATS(6, 6); FloatArray dsig; // Note! We need a copy of the temp strain, since the pertubations might change it. FloatArray tempStrain = ms->giveTempStrainVector(); FloatArray sig, strain, sigPert; giveRealStressVector_3d(sig, gp, tempStrain, tStep); double hh = 1e-6; for ( int k = 1; k <= 6; ++k ) { strain = tempStrain; strain.at(k) += hh; giveRealStressVector_3d(sigPert, gp, strain, tStep); dsig.beDifferenceOf(sigPert, sig); numericalATS.setColumn(dsig, k); } numericalATS.times(1. / hh); giveRealStressVector_3d(sig, gp, tempStrain, tStep); // Reset //answer.printYourself("Analytical deviatoric tangent"); //numericalATS.printYourself("Numerical deviatoric tangent"); numericalATS.subtract(answer); double norm = numericalATS.computeFrobeniusNorm(); if ( norm > answer.computeFrobeniusNorm() * 1e-3 && norm > 0.0 ) { OOFEM_ERROR("Error in deviatoric tangent"); } #endif } }
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"); } }