void FE2FluidMaterial :: giveDeviatoricStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { FE2FluidMaterialStatus *ms = static_cast<FE2FluidMaterialStatus*> (this->giveStatus(gp)); ms->computeTangents(tStep); if ( mode == TangentStiffness ) { answer = ms->giveDeviatoricTangent(); #ifdef DEBUG_TANGENT // Numerical ATS for debugging FloatArray tempStrain(3); tempStrain.zero(); FloatArray sig, strain, sig11, sig22, sig12; double epspvol; computeDeviatoricStressVector (sig, epspvol, gp, tempStrain, 0.0, tStep); double h = 0.001; // Linear problem, size of this doesn't matter. strain.resize(3); strain = tempStrain; strain.at(1) += h; computeDeviatoricStressVector (sig11, epspvol, gp, strain, 0.0, tStep); strain = tempStrain; strain.at(2) += h; computeDeviatoricStressVector (sig22, epspvol, gp, strain, 0.0, tStep); strain = tempStrain; strain.at(3) += h; computeDeviatoricStressVector (sig12, epspvol, gp, strain, 0.0, tStep); FloatArray dsig11; dsig11.beDifferenceOf(sig11,sig); dsig11.times(1/h); FloatArray dsig22; dsig22.beDifferenceOf(sig22,sig); dsig22.times(1/h); FloatArray dsig12; dsig12.beDifferenceOf(sig12,sig); dsig12.times(1/h); FloatMatrix numericalATS; numericalATS.resize(3,3); numericalATS.zero(); numericalATS.setColumn(dsig11,1); numericalATS.setColumn(dsig22,2); numericalATS.setColumn(dsig12,3); printf("Analytical deviatoric tangent = "); answer.printYourself(); printf("Numerical deviatoric tangent = "); numericalATS.printYourself(); numericalATS.subtract(answer); double norm = numericalATS.computeFrobeniusNorm(); if (norm > answer.computeFrobeniusNorm()*DEBUG_ERR && norm > 0.0) { OOFEM_ERROR("Error in deviatoric tangent"); } #endif } else { OOFEM_ERROR("Mode not implemented"); } }
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"); } }
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"); } }
void HOMExportModule :: doOutput(TimeStep *tStep, bool forcedOutput) { if ( !( testTimeStepOutput(tStep) || forcedOutput ) ) { return; } Domain *d = emodel->giveDomain(1); int nelem = d->giveNumberOfElements(); double dV, VolTot = 0.; FloatArray vecState, vecFlow, sumFlow(3); FloatArray internalSource, capacity; FloatArray answerArr, answerArr1; FloatMatrix answerMtrx; IntArray Mask; FloatMatrix baseGCS; sumFlow.zero(); domainType domType = d->giveDomainType(); if ( domType == _HeatTransferMode || domType == _HeatMass1Mode ) { #ifdef __TM_MODULE double sumState = 0.; TransportElement *transpElem; for ( int ielem = 1; ielem <= nelem; ielem++ ) { Element *elem = d->giveElement(ielem); if ( this->matnum.giveSize() == 0 || this->matnum.contains( elem->giveMaterial()->giveNumber() ) ) { for ( GaussPoint *gp: *elem->giveDefaultIntegrationRulePtr() ) { dV = elem->computeVolumeAround(gp); VolTot += dV; elem->giveIPValue(vecState, gp, IST_Temperature, tStep); elem->giveIPValue(vecFlow, gp, IST_TemperatureFlow, tStep); sumState += vecState.at(1) * dV; vecFlow.resize(3); vecFlow.times(dV); sumFlow += vecFlow; } } } sumState *= ( 1. / VolTot * this->scale ); fprintf(this->stream, "%e % e ", tStep->giveTargetTime(), sumState); sumFlow.times(1. / VolTot * this->scale); fprintf( this->stream, "% e % e % e ", sumFlow.at(1), sumFlow.at(2), sumFlow.at(3) ); //add total heat for each material - accumulated energy due to material capacity (J for heat) and internal source (J for heat) internalSource.resize( d->giveNumberOfCrossSectionModels() ); capacity.resize( d->giveNumberOfCrossSectionModels() ); for ( int ielem = 1; ielem <= nelem; ielem++ ) { transpElem = static_cast< TransportElement * >( d->giveElement(ielem) ); transpElem->computeInternalSourceRhsVectorAt(answerArr, tStep, VM_Total); internalSource.at( transpElem->giveCrossSection()->giveNumber() ) += answerArr.sum(); transpElem->giveCharacteristicMatrix(answerMtrx, CapacityMatrix, tStep); transpElem->computeVectorOf(VM_Incremental, tStep, answerArr); answerArr1.beProductOf(answerMtrx, answerArr); capacity.at( transpElem->giveCrossSection()->giveNumber() ) -= answerArr1.sum(); } internalSource.times( tStep->giveTimeIncrement() ); internalSourceEnergy.add(internalSource); capacityEnergy.add(capacity); for ( int i = 1; i <= internalSourceEnergy.giveSize(); i++ ) { fprintf( this->stream, "% e ", internalSourceEnergy.at(i) ); } fprintf(this->stream, " "); for ( int i = 1; i <= capacityEnergy.giveSize(); i++ ) { fprintf( this->stream, "% e ", capacityEnergy.at(i) ); } fprintf(this->stream, "\n"); #endif } else { //structural analysis #ifdef __SM_MODULE StructuralElement *structElem; //int nnodes = d->giveNumberOfDofManagers(); FloatArray VecStrain, VecStress, VecEigStrain, VecEigStrainReduced, tempStrain(6), tempStress(6), tempEigStrain(6), SumStrain(6), SumStress(6), SumEigStrain(6), tempFloatAr, damage; double sumDamage = 0.; //stress and strain vectors are always in global c.s. SumStrain.zero(); //xx, yy, zz, yz, zx, xy SumStress.zero(); SumEigStrain.zero(); for ( int ielem = 1; ielem <= nelem; ielem++ ) { Element *elem = d->giveElement(ielem); tempStrain.zero(); tempStress.zero(); tempEigStrain.zero(); if ( this->matnum.giveSize() == 0 || this->matnum.contains( elem->giveMaterial()->giveNumber() ) ) { for ( GaussPoint *gp: *elem->giveDefaultIntegrationRulePtr() ) { structElem = static_cast< StructuralElement * >(elem); // structElem->computeResultingIPEigenstrainAt(VecEigStrain, tStep, gp, VM_Incremental); structElem->computeResultingIPEigenstrainAt(VecEigStrainReduced, tStep, gp, VM_Total); if ( VecEigStrainReduced.giveSize() == 0 ) { VecEigStrain.resize(0); } else { ( ( StructuralMaterial * ) structElem->giveMaterial() )->giveFullSymVectorForm( VecEigStrain, VecEigStrainReduced, gp->giveMaterialMode() ); } dV = elem->computeVolumeAround(gp); elem->giveIPValue(VecStrain, gp, IST_StrainTensor, tStep); elem->giveIPValue(VecStress, gp, IST_StressTensor, tStep); elem->giveIPValue(damage, gp, IST_DamageTensor, tStep); //truss element has strains and stresses in the first array so transform them to global coordinates ///@todo Should this be the job of giveIPValue to ensure that vectors are given in global c.s.? if ( dynamic_cast< Truss3d * >(elem) ) { MaterialMode mmode = _3dMat; tempStress.at(1) = VecStress.at(1); tempStrain.at(1) = VecStrain.at(1); if ( VecEigStrain.giveSize() ) { tempEigStrain.at(1) = VecEigStrain.at(1); } StressVector stressVector1(tempStress, mmode); //convert from array StressVector stressVector2(mmode); StrainVector strainVector1(tempStrain, mmode); //convert from array StrainVector strainVector2(mmode); StrainVector strainEigVector1(tempEigStrain, mmode); //convert from array StrainVector strainEigVector2(mmode); elem->giveLocalCoordinateSystem(baseGCS); stressVector1.transformTo(stressVector2, baseGCS, 0); strainVector1.transformTo(strainVector2, baseGCS, 0); strainEigVector1.transformTo(strainEigVector2, baseGCS, 0); stressVector2.convertToFullForm(VecStress); strainVector2.convertToFullForm(VecStrain); strainEigVector2.convertToFullForm(VecEigStrain); } VolTot += dV; VecStrain.times(dV); VecStress.times(dV); VecEigStrain.times(dV); if ( damage.giveSize() ) { //only for models with damage sumDamage += damage.at(1) * dV; } SumStrain.add(VecStrain); SumEigStrain.add(VecEigStrain); SumStress.add(VecStress); //VecStrain.printYourself(); //VecEigStrain.printYourself(); //SumStrain.printYourself(); } } } //averaging SumStrain.times(1. / VolTot * this->scale); SumEigStrain.times(1. / VolTot * this->scale); SumStress.times(1. / VolTot * this->scale); sumDamage *= ( 1. / VolTot ); //SumStrain.printYourself(); //SumEigStrain.printYourself(); //SumStress.printYourself(); fprintf( this->stream, "%f ", tStep->giveTargetTime() ); for ( double s: SumStrain ) { //strain fprintf( this->stream, "%06.5e ", s ); } fprintf(this->stream, " "); for ( double s: SumStress ) { //stress fprintf( this->stream, "%06.5e ", s ); } fprintf(this->stream, " "); for ( double s: SumEigStrain ) { //eigenstrain fprintf( this->stream, "%06.5e ", s ); } fprintf(this->stream, "Vol %06.5e ", VolTot); fprintf(this->stream, "AvrDamage %06.5e ", sumDamage); fprintf(this->stream, "\n"); #endif } fflush(this->stream); }