void NonStationaryTransportProblem :: updateYourself(TimeStep *tStep) { this->updateInternalState(tStep); EngngModel :: updateYourself(tStep); ///@todo Find a cleaner way to do these cemhyd hacks #ifdef __CEMHYD_MODULE for ( auto &domain: this->domainList ) { for ( int i = 1; i <= domain->giveNumberOfElements(); ++i ) { TransportElement *elem = static_cast< TransportElement * >( domain->giveElement(i) ); //store temperature and associated volume on each GP before performing averaging CemhydMat *cem = dynamic_cast< CemhydMat * >( elem->giveMaterial() ); if ( cem ) { cem->clearWeightTemperatureProductVolume(elem); cem->storeWeightTemperatureProductVolume(elem, tStep); } } //perform averaging on each material instance for ( int i = 1; i <= domain->giveNumberOfMaterialModels(); i++ ) { CemhydMat *cem = dynamic_cast< CemhydMat * >( domain->giveMaterial(i) ); if ( cem ) { cem->averageTemperature(); } } } #ifdef VERBOSE VERBOSE_PRINT0("Updated Materials ", 0) #endif #endif }
// needed for CemhydMat void NonStationaryTransportProblem :: averageOverElements(TimeStep *tStep) { ///@todo Verify this, the function is completely unused. Domain *domain = this->giveDomain(1); int nelem = domain->giveNumberOfElements(); FloatArray vecTemperature; for ( int ielem = 1; ielem <= nelem; ielem++ ) { TransportElement *element = static_cast< TransportElement * >( domain->giveElement(ielem) ); TransportMaterial *mat = static_cast< CemhydMat * >( element->giveMaterial() ); if ( mat ) { for ( GaussPoint *gp: *element->giveDefaultIntegrationRulePtr() ) { element->giveIPValue(vecTemperature, gp, IST_Temperature, tStep); //mat->IP_volume += dV; //mat->average_temp += vecState.at(1) * dV; } } } for ( int i = 1; i <= domain->giveNumberOfMaterialModels(); i++ ) { CemhydMat *mat = static_cast< CemhydMat * >( domain->giveMaterial(i) ); if ( mat ) { //mat->average_temp /= mat->IP_volume; } } }
void NLTransientTransportProblem :: applyIC(TimeStep *stepWhenIcApply) { Domain *domain = this->giveDomain(1); NonStationaryTransportProblem :: applyIC(stepWhenIcApply); // update element state according to given ic for ( auto &elem : domain->giveElements() ) { TransportElement *element = static_cast< TransportElement * >( elem.get() ); element->updateInternalState(stepWhenIcApply); element->updateYourself(stepWhenIcApply); } }
void TransientTransportProblem :: applyIC() { Domain *domain = this->giveDomain(1); OOFEM_LOG_INFO("Applying initial conditions\n"); this->field->applyDefaultInitialCondition(); ///@todo It's rather strange that the models need the initial values. // update element state according to given ic TimeStep *s = this->giveSolutionStepWhenIcApply(); for ( auto &elem : domain->giveElements() ) { TransportElement *element = static_cast< TransportElement * >( elem.get() ); element->updateInternalState(s); element->updateYourself(s); } }
// needed for CemhydMat void NonStationaryTransportProblem :: averageOverElements(TimeStep *tStep) { Domain *domain = this->giveDomain(1); int ielem, i; int nelem = domain->giveNumberOfElements(); double dV; TransportElement *element; IntegrationRule *iRule; GaussPoint *gp; FloatArray vecTemperature; TransportMaterial *mat; for ( ielem = 1; ielem <= nelem; ielem++ ) { element = ( TransportElement * ) domain->giveElement(ielem); mat = ( TransportMaterial * ) element->giveMaterial(); if ( mat->giveClassID() == CemhydMatClass ) { iRule = element->giveDefaultIntegrationRulePtr(); for ( i = 0; i < iRule->getNumberOfIntegrationPoints(); i++ ) { gp = iRule->getIntegrationPoint(i); dV = element->computeVolumeAround(gp); element->giveIPValue(vecTemperature, gp, IST_Temperature, tStep); //mat->IP_volume += dV; //mat->average_temp += vecState.at(1) * dV; } } } for ( i = 1; i <= domain->giveNumberOfMaterialModels(); i++ ) { mat = ( TransportMaterial * ) domain->giveMaterial(i); if ( mat->giveClassID() == CemhydMatClass ) { //mat->average_temp /= mat->IP_volume; } } }
void TransportMaterialStatus :: printOutputAt(FILE *File, TimeStep *tNow) // Print the state variable and the flow vector on the data file. { FloatArray flowVec; TransportElement *transpElem = static_cast< TransportElement * >( gp->giveElement() ); MaterialStatus :: printOutputAt(File, tNow); fprintf(File, " state"); for ( int i = 1; i <= field.giveSize(); i++ ) { fprintf( File, " % .4e", field.at(i) ); } transpElem->computeFlow(flowVec, gp, tNow); fprintf(File, " flow"); for ( int i = 1; i <= flowVec.giveSize(); i++ ) { fprintf( File, " % .4e", flowVec.at(i) ); } fprintf(File, "\n"); }
int TransportMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) // IST_Humidity must be overriden! { TransportMaterialStatus *ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); if ( type == IST_Temperature || type == IST_MassConcentration_1 || type == IST_Humidity ) { FloatArray vec = ms->giveField(); answer = FloatArray{vec.at( ( type == IST_Temperature ) ? 1 : 2 ) }; return 1; } else if ( type == IST_TemperatureFlow ) { TransportElement *transpElem = static_cast< TransportElement * >( gp->giveElement() ); transpElem->computeFlow(answer, gp, tStep); return 1; } else if ( type == IST_Velocity ) { ///@todo Shouldn't be named velocity.. instead, "MassFlow" or something suitable like that. answer = ms->giveFlux(); answer.resizeWithValues(3); return 1; } else if ( type == IST_PressureGradient ) { answer = ms->giveGradient(); answer.resizeWithValues(3); return 1; } else if ( type == IST_Density ) { answer = FloatArray{ this->give('d', gp) }; return 1; } else if ( type == IST_HeatCapacity ) { answer = FloatArray{ this->give('c', gp) }; return 1; } else if ( type == IST_ThermalConductivityIsotropic ) { answer = FloatArray{ this->give('k', gp) }; return 1; } else if ( type == IST_Maturity ) { answer = FloatArray{ ms->giveMaturity() }; return 1; } return Material :: giveIPValue(answer, gp, type, tStep); }
void NonStationaryTransportProblem :: applyIC(TimeStep *stepWhenIcApply) { Domain *domain = this->giveDomain(1); int neq = this->giveNumberOfEquations(EID_ConservationEquation); FloatArray *solutionVector; double val; #ifdef VERBOSE OOFEM_LOG_INFO("Applying initial conditions\n"); #endif int nDofs, j, k, jj; int nman = domain->giveNumberOfDofManagers(); DofManager *node; Dof *iDof; UnknownsField->advanceSolution(stepWhenIcApply); solutionVector = UnknownsField->giveSolutionVector(stepWhenIcApply); solutionVector->resize(neq); solutionVector->zero(); for ( j = 1; j <= nman; j++ ) { node = domain->giveDofManager(j); nDofs = node->giveNumberOfDofs(); for ( k = 1; k <= nDofs; k++ ) { // ask for initial values obtained from // bc (boundary conditions) and ic (initial conditions) iDof = node->giveDof(k); if ( !iDof->isPrimaryDof() ) { continue; } jj = iDof->__giveEquationNumber(); if ( jj ) { val = iDof->giveUnknown(EID_ConservationEquation, VM_Total, stepWhenIcApply); solutionVector->at(jj) = val; //update in dictionary, if the problem is growing/decreasing if ( this->changingProblemSize ) { iDof->updateUnknownsDictionary(stepWhenIcApply, EID_MomentumBalance, VM_Total, val); } } } } int nelem = domain->giveNumberOfElements(); //project initial temperature to integration points // for ( j = 1; j <= nelem; j++ ) { // domain->giveElement(j)->updateInternalState(stepWhenIcApply); // } #ifdef __CEMHYD_MODULE // Not relevant in linear case, but needed for CemhydMat for temperature averaging before solving balance equations // Update element state according to given ic TransportElement *element; CemhydMat *cem; for ( j = 1; j <= nelem; j++ ) { element = ( TransportElement * ) domain->giveElement(j); //assign status to each integration point on each element if ( element->giveMaterial()->giveClassID() == CemhydMatClass ) { element->giveMaterial()->initMaterial(element); //create microstructures and statuses on specific GPs element->updateInternalState(stepWhenIcApply); //store temporary unequilibrated temperature element->updateYourself(stepWhenIcApply); //store equilibrated temperature cem = ( CemhydMat * ) element->giveMaterial(); cem->clearWeightTemperatureProductVolume(element); cem->storeWeightTemperatureProductVolume(element, stepWhenIcApply); } } //perform averaging on each material instance of CemhydMatClass int nmat = domain->giveNumberOfMaterialModels(); for ( j = 1; j <= nmat; j++ ) { if ( domain->giveMaterial(j)->giveClassID() == CemhydMatClass ) { cem = ( CemhydMat * ) domain->giveMaterial(j); cem->averageTemperature(); } } #endif //__CEMHYD_MODULE }
void NonStationaryTransportProblem :: applyIC(TimeStep *stepWhenIcApply) { Domain *domain = this->giveDomain(1); int neq = this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); FloatArray *solutionVector; double val; #ifdef VERBOSE OOFEM_LOG_INFO("Applying initial conditions\n"); #endif UnknownsField->advanceSolution(stepWhenIcApply); solutionVector = UnknownsField->giveSolutionVector(stepWhenIcApply); solutionVector->resize(neq); solutionVector->zero(); for ( auto &node : domain->giveDofManagers() ) { for ( Dof *dof: *node ) { // ask for initial values obtained from // bc (boundary conditions) and ic (initial conditions) if ( !dof->isPrimaryDof() ) { continue; } int jj = dof->__giveEquationNumber(); if ( jj ) { val = dof->giveUnknown(VM_Total, stepWhenIcApply); solutionVector->at(jj) = val; //update in dictionary, if the problem is growing/decreasing if ( this->changingProblemSize ) { dof->updateUnknownsDictionary(stepWhenIcApply, VM_Total, val); } } } } //project initial temperature to integration points // for ( int j = 1; j <= nelem; j++ ) { // domain->giveElement(j)->updateInternalState(stepWhenIcApply); // } #ifdef __CEMHYD_MODULE // Not relevant in linear case, but needed for CemhydMat for temperature averaging before solving balance equations // Update element state according to given ic for ( auto &elem : domain->giveElements() ) { TransportElement *element = static_cast< TransportElement * >( elem.get() ); CemhydMat *cem = dynamic_cast< CemhydMat * >( element->giveMaterial() ); //assign status to each integration point on each element if ( cem ) { cem->initMaterial(element); //create microstructures and statuses on specific GPs element->updateInternalState(stepWhenIcApply); //store temporary unequilibrated temperature element->updateYourself(stepWhenIcApply); //store equilibrated temperature cem->clearWeightTemperatureProductVolume(element); cem->storeWeightTemperatureProductVolume(element, stepWhenIcApply); } } //perform averaging on each material instance of CemhydMatClass for ( auto &mat : domain->giveMaterials() ) { CemhydMat *cem = dynamic_cast< CemhydMat * >( mat.get() ); if ( cem ) { cem->averageTemperature(); } } #endif //__CEMHYD_MODULE }
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); }