void BoundaryLoad :: computeValueAt(FloatArray &answer, TimeStep *tStep, FloatArray &coords, ValueModeType mode) { // Evaluates the value at specific integration point int i, j, nSize; double value, factor; FloatArray N; if ( ( mode != VM_Total ) && ( mode != VM_Incremental ) ) { OOFEM_ERROR("unknown mode"); } answer.resize(this->nDofs); this->computeNArray(N, coords); nSize = N.giveSize(); if ( ( this->componentArray.giveSize() / nSize ) != nDofs ) { OOFEM_ERROR("componentArray size mismatch"); } for ( i = 1; i <= nDofs; i++ ) { for ( value = 0., j = 1; j <= nSize; j++ ) { value += N.at(j) * this->componentArray.at(i + ( j - 1 ) * nDofs); } answer.at(i) = value; } // time distribution /* * factor = this -> giveTimeFunction() -> at(tStep->giveTime()) ; * if ((mode==VM_Incremental) && (!tStep->isTheFirstStep())) * //factor -= this->giveTimeFunction()->at(tStep->givePreviousStep()->giveTime()) ; * factor -= this->giveTimeFunction()->at(tStep->giveTime()-tStep->giveTimeIncrement()); */ factor = this->giveTimeFunction()->evaluate(tStep, mode); answer.times(factor); }
void Quad1Mindlin :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *stepN, ValueModeType mode) { // Only gravity load double dV, load; GaussPoint *gp; FloatArray force, gravity, n; if ( ( forLoad->giveBCGeoType() != BodyLoadBGT ) || ( forLoad->giveBCValType() != ForceLoadBVT ) ) { _error("computeBodyLoadVectorAt: unknown load type"); } // note: force is assumed to be in global coordinate system. forLoad->computeComponentArrayAt(gravity, stepN, mode); force.resize(0); if ( gravity.giveSize() ) { IntegrationRule *ir = integrationRulesArray [ 0 ]; ///@todo Other/higher integration for lumped mass matrices perhaps? for ( int i = 0; i < ir->getNumberOfIntegrationPoints(); ++i) { gp = ir->getIntegrationPoint(i); this->interp_lin.evalN(n, *gp->giveCoordinates(), FEIElementGeometryWrapper(this)); dV = this->computeVolumeAround(gp) * this->giveCrossSection()->give(CS_Thickness); load = this->giveMaterial()->give('d', gp) * gravity.at(3) * dV; force.add(load, n); } answer.resize(12); answer.zero(); answer.at(1) = force.at(1); answer.at(4) = force.at(2); answer.at(7) = force.at(3); answer.at(10) = force.at(4); } else { answer.resize(0); } }
double HeMoTKMaterial :: computeCapacityCoeff(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { if ( mode == Capacity_ww ) { return 1.0 * rho; } else if ( mode == Capacity_wh ) { return 0.0; } else if ( mode == Capacity_hw ) { TransportMaterialStatus *status = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); FloatArray s; double w, t; s = status->giveTempField(); if ( s.isEmpty() ) { OOFEM_ERROR("undefined state vector"); } w = s.at(2); t = s.at(1); return get_b(w, t) * get_latent(w, t); } else if ( mode == Capacity_hh ) { TransportMaterialStatus *status = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); FloatArray s; double w, t; s = status->giveTempField(); if ( s.isEmpty() ) { OOFEM_ERROR("undefined state vector"); } w = s.at(2); t = s.at(1); return get_ceff(w, t); } else { OOFEM_ERROR("Unknown MatResponseMode"); } return 0.0; // to make compiler happy }
double HeMoTKMaterial :: computeCapacityCoeff(MatResponseMode mode, GaussPoint *gp, TimeStep *atTime) { if ( mode == Capacity_ww ) { return 1.0 * rho; } else if ( mode == Capacity_wh ) { return 0.0; } else if ( mode == Capacity_hw ) { TransportMaterialStatus *status = ( TransportMaterialStatus * ) this->giveStatus(gp); FloatArray s; double w, t; s = status->giveTempStateVector(); if ( s.isEmpty() ) { _error("computeCapacityCoeff: undefined state vector"); } w = s.at(2); t = s.at(1); return get_b(w, t) * get_latent(w, t); } else if ( mode == Capacity_hh ) { TransportMaterialStatus *status = ( TransportMaterialStatus * ) this->giveStatus(gp); FloatArray s; double w, t; s = status->giveTempStateVector(); if ( s.isEmpty() ) { _error("computeCapacityCoeff: undefined state vector"); } w = s.at(2); t = s.at(1); return get_ceff(w, t); } else { _error("Unknown MatResponseMode"); } return 0.0; // to make compiler happy }
void LEPlic :: giveMaterialMixtureAt(FloatArray &answer, FloatArray &position) { answer.resize(2); Element *elem = domain->giveSpatialLocalizer()->giveElementContainingPoint(position); LEPlicElementInterface *interface = ( LEPlicElementInterface * ) elem->giveInterface(LEPlicElementInterfaceType); if ( interface ) { Polygon pg; FloatArray n; interface->giveTempInterfaceNormal(n); interface->formVolumeInterfacePoly(pg, this, n, interface->giveTempLineConstant(), false); if ( pg.testPoint( position.at(1), position.at(2) ) ) { answer.at(1) = 1.0; answer.at(2) = 0.0; } else { answer.at(1) = 0.0; answer.at(2) = 1.0; } } else { answer.at(1) = 1.0; answer.at(2) = 0.0; } }
void LIBeam2dNL :: computeStrainVectorInLayer(FloatArray &answer, GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep) // // returns full 3d strain vector of given layer (whose z-coordinate from center-line is // stored in slaveGp) for given tStep // { FloatArray masterGpStrain; double layerZeta, layerZCoord, top, bottom; this->computeStrainVector(masterGpStrain, masterGp, tStep); top = masterGp->giveElement()->giveCrossSection()->give(CS_TopZCoord); bottom = masterGp->giveElement()->giveCrossSection()->give(CS_BottomZCoord); layerZeta = slaveGp->giveCoordinate(3); layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top ); answer.resize(6); // {Exx,Eyy,Ezz,GMyz,GMzx,GMxy} answer.zero(); answer.at(1) = masterGpStrain.at(1) + masterGpStrain.at(2) * layerZCoord; answer.at(5) = masterGpStrain.at(3); }
void Quad1Mindlin :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) { // Only gravity load double dV, load; FloatArray force, gravity, n; if ( ( forLoad->giveBCGeoType() != BodyLoadBGT ) || ( forLoad->giveBCValType() != ForceLoadBVT ) ) { OOFEM_ERROR("unknown load type"); } // note: force is assumed to be in global coordinate system. forLoad->computeComponentArrayAt(gravity, tStep, mode); force.clear(); if ( gravity.giveSize() ) { ///@todo Other/higher integration for lumped mass matrices perhaps? for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { this->interp_lin.evalN( n, * gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); dV = this->computeVolumeAround(gp) * this->giveCrossSection()->give(CS_Thickness, gp); load = this->giveStructuralCrossSection()->give('d', gp) * gravity.at(3) * dV; force.add(load, n); } answer.resize(12); answer.zero(); answer.at(1) = force.at(1); answer.at(4) = force.at(2); answer.at(7) = force.at(3); answer.at(10) = force.at(4); } else { answer.clear(); } }
void CohesiveInterfaceMaterial :: giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) { StructuralInterfaceMaterialStatus *status = static_cast< StructuralInterfaceMaterialStatus * >( this->giveStatus(gp) ); answer.resize(3); double x = jump.at(1) + transitionOpening; if (stiffCoeffKn == 1.){//tension stiffness = compression stiffness answer.at(1) = kn*x; } else { //composed function from two atan's to have smooth intersection between tension and compression answer.at(1) = (M_PI/2. + atan(smoothMag*x))/M_PI*kn*stiffCoeffKn*x + (M_PI/2.-atan(smoothMag*x))/M_PI*kn*x; } // shear part of elastic stress-strain law answer.at(2) = ks * jump.at(2); answer.at(3) = ks * jump.at(3); // update gp status->letTempJumpBe(jump); status->letTempTractionBe(answer); }
void J2MPlasticMaterial :: computeStressSpaceHardeningVars(FloatArray &answer, GaussPoint *gp, const FloatArray &strainSpaceHardeningVariables) { // in full stress strain space int count = 0, size = this->giveSizeOfFullHardeningVarsVector(), isize, rSize; IntArray mask; if ( !hasHardening() ) { answer.clear(); return; } answer.resize(size); StructuralMaterial :: giveVoigtSymVectorMask( mask, gp->giveMaterialMode() ); isize = mask.giveSize(); rSize = this->giveSizeOfReducedHardeningVarsVector(gp); /* kinematic hardening variables are first */ if ( this->kinematicHardeningFlag ) { for ( int i = 1; i <= isize; i++ ) { // to be consistent with equivalent plastic strain formulation // we multiply by (sqrt(2.)*2./3.) answer.at( mask.at(i) ) = ( sqrt(2.) * 2. / 3. ) * this->kinematicModuli * strainSpaceHardeningVariables.at(i); } count = 6; } if ( this->isotropicHardeningFlag ) { answer.at(count + 1) = this->isotropicModuli * strainSpaceHardeningVariables.at(rSize); } answer.negated(); }
void IntMatCoulombContact :: giveEngTraction_3d( FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) { IntMatCoulombContactStatus *status = static_cast< IntMatCoulombContactStatus * >( this->giveStatus( gp ) ); double normalJump = jump.at( 3 ); FloatArray shearJump = { jump.at(1), jump.at(2) }; double normalStress = 0.0; FloatArray shearStress, tempShearStressShift = status->giveShearStressShift(); this->computeEngTraction( normalStress, shearStress, tempShearStressShift, normalJump, shearJump ); // Set stress components in the traction vector answer.resize( 3 ); answer.at( 1 ) = shearStress.at( 1 ); answer.at( 2 ) = shearStress.at( 2 ); answer.at( 3 ) = normalStress; // Update gp status->setTempShearStressShift( tempShearStressShift ); status->letTempJumpBe( jump ); status->letTempTractionBe( answer ); }
void LEPlic :: findCellLineConstant(double &p, FloatArray &fvgrad, int ie, bool coord_upd, bool temp_vof_flag) { /* The line constatnt p is solved from the general non-linear function * F(p) = V(p)-V = 0, * where V(p) is the truncated volume resulting from the intersection between * assumed line segment and the reference cell * V is the given Volume of Fluid ratio * To find zero of this function, Brent's method is been used. */ Element *elem = domain->giveElement(ie); LEPlicElementInterface *interface = ( LEPlicElementInterface * ) elem->giveInterface(LEPlicElementInterfaceType); int ivert, nelemnodes = elem->giveNumberOfNodes(); double ivof, fvi; double ivx, ivy, pp, target_vof; if ( temp_vof_flag ) { target_vof = interface->giveTempVolumeFraction(); } else { target_vof = interface->giveVolumeFraction(); } computeLEPLICVolumeFractionWrapper wrapper(interface, this, fvgrad, target_vof, coord_upd); /* * Initial part: find lower and uper bounds for Brent algorithm * Here lines with given interface normal are passed through each vertex * and corresponding volume fractions are computed. The two lines forming * truncation volumes that bound the actual material in the cell provide * upper and lower bounds for line constant */ double upper_vof = 10.0, lower_vof = -10.0; double upper_p = 0.0, lower_p = 0.0; if ( temp_vof_flag ) { fvi = interface->giveTempVolumeFraction(); } else { fvi = interface->giveVolumeFraction(); } if ( ( fvi > LEPLIC_ZERO_VOF ) && ( fvi < 1.0 ) ) { // boundary cell for ( ivert = 1; ivert <= nelemnodes; ivert++ ) { if ( coord_upd ) { ivx = giveUpdatedXCoordinate( elem->giveNode(ivert)->giveNumber() ); ivy = giveUpdatedYCoordinate( elem->giveNode(ivert)->giveNumber() ); } else { ivx = elem->giveNode(ivert)->giveCoordinate(1); ivy = elem->giveNode(ivert)->giveCoordinate(2); } // determine line constant for vertex ivert pp = -( fvgrad.at(1) * ivx + fvgrad.at(2) * ivy ); ivof = interface->computeLEPLICVolumeFraction(fvgrad, pp, this, coord_upd); if ( ( ( ivof - target_vof ) >= 0. ) && ( ivof < upper_vof ) ) { upper_vof = ivof; upper_p = pp; } else if ( ( ( target_vof - ivof ) >= 0. ) && ( ivof > lower_vof ) ) { lower_vof = ivof; lower_p = pp; } } if ( ( lower_vof >= 0. ) && ( upper_vof <= 1.00000000001 ) ) { // now use brent's method to find minima of V(p)-V function brent(lower_p, 0.5 * ( lower_p + upper_p ), upper_p, mem_fun< computeLEPLICVolumeFractionWrapper >(& wrapper, & computeLEPLICVolumeFractionWrapper :: eval), LEPLIC_BRENT_EPS, p); //interface->setTempLineConstant (p); #ifdef __OOFEG /* * Polygon grp, cell; * // check here * //Polygon testvolpoly; * //interface->formMaterialVolumePoly(testvolpoly, this, fvgrad, p, true); * //double debug_vof = interface->truncateMatVolume(testvolpoly); * * //printf ("Cell %d-> target_vof is %e, debug val is %e\n", ie, target_vof, debug_vof); * interface->formMyVolumePoly (cell, this, true); * GraphicObj *goc = cell.draw(::gc[0], false); * EASValsSetLayer(OOFEG_DEBUG_LAYER); * EASValsSetColor(::gc[0].getBcIcColor()); * EGWithMaskChangeAttributes(COLOR_MASK | LAYER_MASK, goc); * EMDrawGraphics (ESIModel(), goc); * * interface->formVolumeInterfacePoly (grp, this, fvgrad, p, true); * GraphicObj *go = grp.draw(::gc[0], true); * EASValsSetColor(::gc[0].getActiveCrackColor()); * EGWithMaskChangeAttributes(COLOR_MASK | LAYER_MASK, go); * EMDrawGraphics (ESIModel(), go); * //ESIEventLoop (YES, "findCellLineConstant -> Press Ctrl-p to continue"); */ #endif } else { OOFEM_ERROR("LEPlic::findCellLineConstant: finding lower and uper bounds of line constant value failed"); } } }
void RCSDMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &totalStrain, TimeStep *tStep) // // returns real stress vector in 3d stress space of receiver according to // previous level of stress and current // strain increment, the only way, how to correctly update gp records // { FloatMatrix Ds0; double equivStrain; FloatArray princStress, reducedAnswer; FloatArray reducedStrainVector, strainVector, principalStrain; FloatArray reducedSpaceStressVector; FloatMatrix tempCrackDirs; RCSDMaterialStatus *status = static_cast< RCSDMaterialStatus * >( this->giveStatus(gp) ); this->initTempStatus(gp); //this->initGpForNewStep(gp); // subtract stress independent part // note: eigenStrains (temperature) is not contained in mechanical strain stored in gp // therefore it is necessary to subtract always the total eigen strain value this->giveStressDependentPartOfStrainVector(reducedStrainVector, gp, totalStrain, tStep, VM_Total); StructuralMaterial :: giveFullSymVectorForm( strainVector, reducedStrainVector, gp->giveMaterialMode() ); tempCrackDirs = status->giveTempCrackDirs(); this->computePrincipalValDir(principalStrain, tempCrackDirs, strainVector, principal_strain); if ( status->giveTempMode() == RCSDMaterialStatus :: rcMode ) { // rotating crack mode this->giveRealPrincipalStressVector3d(princStress, gp, principalStrain, tempCrackDirs, tStep); princStress.resize(6); tempCrackDirs = status->giveTempCrackDirs(); this->transformStressVectorTo(answer, tempCrackDirs, princStress, 1); StructuralMaterial :: giveReducedSymVectorForm( reducedSpaceStressVector, answer, gp->giveMaterialMode() ); status->letTempStressVectorBe(reducedSpaceStressVector); this->updateCrackStatus(gp, status->giveCrackStrainVector()); StructuralMaterial :: giveReducedSymVectorForm( reducedAnswer, answer, gp->giveMaterialMode() ); answer = reducedAnswer; // test if transition to scalar damage mode take place double minSofteningPrincStress = this->Ft, dCoeff, CurrFt, E, ep, ef, damage; int ipos = 0; for ( int i = 1; i <= 3; i++ ) { if ( status->giveTempCrackStatus(i) == pscm_SOFTENING ) { if ( princStress.at(i) < minSofteningPrincStress ) { minSofteningPrincStress = princStress.at(i); ipos = i; } } } CurrFt = this->computeStrength( gp, status->giveCharLength(ipos) ); if ( minSofteningPrincStress <= this->SDTransitionCoeff * CurrFt ) { // sd transition takes place E = linearElasticMaterial->give(Ex, gp); ep = CurrFt / E; ef = this->giveMinCrackStrainsForFullyOpenCrack(gp, ipos); dCoeff = ( E / ( princStress.at(ipos) / principalStrain.at(ipos) ) ); this->giveMaterialStiffnessMatrix(Ds0, SecantStiffness, gp, tStep); // compute reached equivalent strain equivStrain = this->computeCurrEquivStrain(gp, reducedStrainVector, E, tStep); damage = this->computeDamageCoeff(equivStrain, dCoeff, ep, ef); status->setDamageEpsfCoeff(ef); status->setDamageEpspCoeff(ep); status->setDamageStiffCoeff(dCoeff); status->setDs0Matrix(Ds0); status->setTempMaxEquivStrain(equivStrain); status->setTempDamageCoeff(damage); status->setTempMode(RCSDMaterialStatus :: sdMode); } } else { // scalar damage mode double ep, ef, E, dCoeff; double damage; //int ipos; E = linearElasticMaterial->give(Ex, gp); equivStrain = this->computeCurrEquivStrain(gp, reducedStrainVector, E, tStep); equivStrain = max( equivStrain, status->giveTempMaxEquivStrain() ); reducedSpaceStressVector.beProductOf(* status->giveDs0Matrix(), reducedStrainVector); dCoeff = status->giveDamageStiffCoeff(); ef = status->giveDamageEpsfCoeff(); ep = status->giveDamageEpspCoeff(); damage = this->computeDamageCoeff(equivStrain, dCoeff, ep, ef); reducedSpaceStressVector.times(1.0 - damage); answer = reducedSpaceStressVector; status->letTempStressVectorBe(reducedSpaceStressVector); status->setTempMaxEquivStrain(equivStrain); status->setTempDamageCoeff(damage); } status->letTempStrainVectorBe(totalStrain); }
void LEPlic :: doCellDLS(FloatArray &fvgrad, int ie, bool coord_upd, bool vof_temp_flag) { int i, ineighbr, nneighbr; double fvi, fvk, wk, dx, dy; bool isBoundaryCell = false; LEPlicElementInterface *interface, *ineghbrInterface; FloatMatrix lhs(2, 2); FloatArray rhs(2), xi(2), xk(2); IntArray currCell(1), neighborList; ConnectivityTable *contable = domain->giveConnectivityTable(); if ( ( interface = ( LEPlicElementInterface * ) ( domain->giveElement(ie)->giveInterface(LEPlicElementInterfaceType) ) ) ) { if ( vof_temp_flag ) { fvi = interface->giveTempVolumeFraction(); } else { fvi = interface->giveVolumeFraction(); } if ( ( fvi > 0. ) && ( fvi <= 1.0 ) ) { // potentially boundary cell if ( ( fvi > 0. ) && ( fvi < 1.0 ) ) { isBoundaryCell = true; } /* DLS (Differential least square reconstruction) * * In the DLS method, volume fraction Taylor series expansion of vf (volume fraction) * is formed from each reference cell volume fraction vf at element center x(i) to each * cell neighbor at point x(k). The sum (vf(i)-vf(k))^2 over all immediate neighbors * is then minimized inthe least square sense. */ // get list of neighbours to current cell including current cell currCell.at(1) = ie; contable->giveElementNeighbourList(neighborList, currCell); // loop over neighbors to assemble normal equations nneighbr = neighborList.giveSize(); interface->giveElementCenter(this, xi, coord_upd); lhs.zero(); rhs.zero(); for ( i = 1; i <= nneighbr; i++ ) { ineighbr = neighborList.at(i); if ( ineighbr == ie ) { continue; // skip itself } if ( ( ineghbrInterface = ( LEPlicElementInterface * ) ( domain->giveElement(ineighbr)->giveInterface(LEPlicElementInterfaceType) ) ) ) { if ( vof_temp_flag ) { fvk = ineghbrInterface->giveTempVolumeFraction(); } else { fvk = ineghbrInterface->giveVolumeFraction(); } if ( fvk < 1.0 ) { isBoundaryCell = true; } ineghbrInterface->giveElementCenter(this, xk, coord_upd); wk = xk.distance(xi); dx = ( xk.at(1) - xi.at(1) ) / wk; dy = ( xk.at(2) - xi.at(2) ) / wk; lhs.at(1, 1) += dx * dx; lhs.at(1, 2) += dx * dy; lhs.at(2, 2) += dy * dy; rhs.at(1) += ( fvi - fvk ) * dx / wk; rhs.at(2) += ( fvi - fvk ) * dy / wk; } } if ( isBoundaryCell ) { // symmetry lhs.at(2, 1) = lhs.at(1, 2); // solve normal equation for volume fraction gradient lhs.solveForRhs(rhs, fvgrad); // compute unit normal fvgrad.normalize(); fvgrad.negated(); #ifdef __OOFEG /* * EASValsSetLayer(OOFEG_DEBUG_LAYER); * WCRec p[2]; * double tx = -fvgrad.at(2), ty=fvgrad.at(1); * p[0].x=xi.at(1)-tx*0.1; * p[0].y=xi.at(2)-ty*0.1; * p[1].x=xi.at(1)+tx*0.1; * p[1].y=xi.at(2)+ty*0.1; * p[0].z = p[1].z = 0.0; * GraphicObj *go = CreateLine3D(p); * EGWithMaskChangeAttributes(LAYER_MASK, go); * EMAddGraphicsToModel(ESIModel(), go); * ESIEventLoop (YES, "Cell DLS finished; Press Ctrl-p to continue"); */ #endif } else { fvgrad.zero(); } } } }
void B3SolidMaterial :: computeCharCoefficients(FloatArray &answer, double tStep) { /* * If EmoduliMode == 0 then analysis of continuous retardation spectrum is used for * computing characteristic coefficients (moduli) of Kelvin chain * Else least-squares method is used */ if ( this->EmoduliMode == 0 ) { int mu; double tau0, tauMu; // constant "n" is assumed to be equal to 0.1 (typical value) // modulus of elasticity of the first unit of Kelvin chain. // (aging elastic spring with retardation time = 0) double lambda0ToPowN = pow(lambda0, 0.1); tau0 = pow(2 * this->giveCharTime(1) / sqrt(10.0), 0.1); EspringVal = 1.e6 / ( q2 * log(1.0 + tau0 / lambda0ToPowN) - q2 * tau0 / ( 10.0 * lambda0ToPowN + 10.0 * tau0 ) ); // evaluation of moduli of elasticity for the remaining units // (Solidifying kelvin units with retardation times tauMu) answer.resize(nUnits); answer.zero(); for ( mu = 1; mu <= this->nUnits; mu++ ) { tauMu = pow(2 * this->giveCharTime(mu), 0.1); answer.at(mu) = 10.e6 * pow(1 + tauMu / lambda0ToPowN, 2) / ( log(10.0) * q2 * ( tauMu / lambda0ToPowN ) * ( 0.9 + tauMu / lambda0ToPowN ) ); this->charTimes.at(mu) *= 1.35; } answer.at(nUnits) /= 1.2; // modulus of the last unit is reduced } else { // moduli computed using the least-squares method int rSize; double taui, tauj, tti, ttj; FloatArray rhs(this->nUnits); FloatMatrix A(this->nUnits, this->nUnits); const FloatArray &rTimes = this->giveDiscreteTimes(); rSize = rTimes.giveSize(); FloatArray discreteComplianceFunctionVal(rSize); // compute values of the compliance function at specified times rTimes // (can be done directly, since the compliance function is available) for ( int i = 1; i <= rSize; i++ ) { discreteComplianceFunctionVal.at(i) = this->computeCreepFunction( rTimes.at(i), 0. ); } // assemble the matrix of the set of linear equations // for computing the optimal compliances // !!! chartime exponents are assumed to be equal to 1 !!! for ( int i = 1; i <= this->nUnits; i++ ) { taui = this->giveCharTime(i); for ( int j = 1; j <= this->nUnits; j++ ) { tauj = this->giveCharTime(j); double sum = 0.; for ( int r = 1; r <= rSize; r++ ) { tti = rTimes.at(r) / taui; ttj = rTimes.at(r) / tauj; sum += ( 1. - exp(-tti) ) * ( 1. - exp(-ttj) ); } A.at(i, j) = sum; } // assemble rhs // !!! chartime exponents are assumed to be equal to 1 !!! double sumRhs = 0.; for ( int r = 1; r <= rSize; r++ ) { tti = rTimes.at(r) / taui; sumRhs += ( 1. - exp(-tti) ) * discreteComplianceFunctionVal.at(r); } rhs.at(i) = sumRhs; } // solve the linear system A.solveForRhs(rhs, answer); // convert compliances into moduli for ( int i = 1; i <= this->nUnits; i++ ) { answer.at(i) = 1.e6 / answer.at(i); } } }
NM_Status SubspaceIteration :: solve(SparseMtrx &a, SparseMtrx &b, FloatArray &_eigv, FloatMatrix &_r, double rtol, int nroot) // // this function solve the generalized eigenproblem using the Generalized // jacobi iteration // { if ( a.giveNumberOfColumns() != b.giveNumberOfColumns() ) { OOFEM_ERROR("matrices size mismatch"); } FloatArray temp, w, d, tt, f, rtolv, eigv; FloatMatrix r; int nn, nc1, ij = 0, is; double rt, art, brt, eigvt; FloatMatrix ar, br, vec; std :: unique_ptr< SparseLinearSystemNM > solver( GiveClassFactory().createSparseLinSolver(ST_Direct, domain, engngModel) ); GJacobi mtd(domain, engngModel); int nc = min(2 * nroot, nroot + 8); nn = a.giveNumberOfColumns(); if ( nc > nn ) { nc = nn; } ar.resize(nc, nc); ar.zero(); br.resize(nc, nc); br.zero(); // // creation of initial iteration vectors // nc1 = nc - 1; w.resize(nn); w.zero(); d.resize(nc); d.zero(); tt.resize(nn); tt.zero(); rtolv.resize(nc); rtolv.zero(); vec.resize(nc, nc); vec.zero(); // eigen vectors of reduced problem // // create work arrays // r.resize(nn, nc); r.zero(); eigv.resize(nc); eigv.zero(); FloatArray h(nn); for ( int i = 1; i <= nn; i++ ) { h.at(i) = 1.0; w.at(i) = b.at(i, i) / a.at(i, i); } b.times(h, tt); r.setColumn(tt, 1); for ( int j = 2; j <= nc; j++ ) { rt = 0.0; for ( int i = 1; i <= nn; i++ ) { if ( fabs( w.at(i) ) >= rt ) { rt = fabs( w.at(i) ); ij = i; } } tt.at(j) = ij; w.at(ij) = 0.; for ( int i = 1; i <= nn; i++ ) { if ( i == ij ) { h.at(i) = 1.0; } else { h.at(i) = 0.0; } } b.times(h, tt); r.setColumn(tt, j); } // (r = z) # ifdef DETAILED_REPORT OOFEM_LOG_INFO("SubspaceIteration :: solveYourselfAt: Degrees of freedom invoked by initial vectors :\n"); tt.printYourself(); OOFEM_LOG_INFO("SubspaceIteration :: solveYourselfAt: initial vectors for iteration:\n"); r.printYourself(); # endif //ish = 0; a.factorized(); // // start of iteration loop // for ( int nite = 0; ; ++nite ) { // label 100 # ifdef DETAILED_REPORT printf("SubspaceIteration :: solveYourselfAt: Iteration loop no. %d\n", nite); # endif // // compute projection ar and br of matrices a , b // for ( int j = 1; j <= nc; j++ ) { f.beColumnOf(r, j); solver->solve(a, f, tt); for ( int i = j; i <= nc; i++ ) { art = 0.; for ( int k = 1; k <= nn; k++ ) { art += r.at(k, i) * tt.at(k); } ar.at(j, i) = art; } r.setColumn(tt, j); // (r = xbar) } ar.symmetrized(); // label 110 #ifdef DETAILED_REPORT OOFEM_LOG_INFO("SubspaceIteration :: solveYourselfAt: Printing projection matrix ar\n"); ar.printYourself(); #endif // for ( int j = 1; j <= nc; j++ ) { tt.beColumnOf(r, j); b.times(tt, temp); for ( int i = j; i <= nc; i++ ) { brt = 0.; for ( int k = 1; k <= nn; k++ ) { brt += r.at(k, i) * temp.at(k); } br.at(j, i) = brt; } // label 180 r.setColumn(temp, j); // (r=zbar) } // label 160 br.symmetrized(); #ifdef DETAILED_REPORT OOFEM_LOG_INFO("SubspaceIteration :: solveYourselfAt: Printing projection matrix br\n"); br.printYourself(); #endif // // solution of reduced eigenvalue problem // mtd.solve(ar, br, eigv, vec); // START EXPERIMENTAL #if 0 // solve the reduced problem by Inverse iteration { FloatMatrix x(nc,nc), z(nc,nc), zz(nc,nc), arinv; FloatArray w(nc), ww(nc), tt(nc), t(nc); double c; // initial setting for ( int i = 1;i <= nc; i++ ) { ww.at(i)=1.0; } for ( int i = 1;i <= nc; i++ ) for ( int j = 1; j <= nc;j++ ) z.at(i,j)=1.0; arinv.beInverseOf (ar); for ( int i = 0;i < nitem; i++ ) { // copy zz=z zz = z; // solve matrix equation K.X = M.X x.beProductOf(arinv, z); // evaluation of Rayleigh quotients for ( int j = 1;j <= nc; j++ ) { w.at(j) = 0.0; for (k = 1; k<= nc; k++) w.at(j) += zz.at(k,j) * x.at(k,j); } z.beProductOf (br, x); for ( int j = 1;j <= nc; j++ ) { c = 0; for ( int k = 1; k<= nc; k++ ) c += z.at(k,j) * x.at(k,j); w.at(j) /= c; } // check convergence int ac = 0; for ( int j = 1;j <= nc; j++ ) { if (fabs((ww.at(j)-w.at(j))/w.at(j))< rtol) ac++; ww.at(j) = w.at(j); } //printf ("\n iterace cislo %d %d",i,ac); //w.printYourself(); // Gramm-Schmidt ortogonalization for ( int j = 1;j <= nc;j++ ) { for ( int k = 1; k<= nc; k++ ) tt.at(k) = x.at(k,j); t.beProductOf(br,tt) ; for ( int ii = 1;ii < j; ii++ ) { c = 0.0; for ( int k = 1; k<= nc; k++ ) c += x.at(k,ii) * t.at(k); for ( int k = 1; k<= nc; k++ ) x.at(k,j) -= x.at(k,ii) * c; } for ( int k = 1; k<= nc; k++) tt.at(k) = x.at(k,j); t.beProductOf(br, tt); c = 0.0; for ( int k = 1; k<= nc; k++) c += x.at(k,j)*t.at(k); for ( int k = 1; k<= nc; k++) x.at(k,j) /= sqrt(c); } if ( ac > nroot ) { break; } // compute new approximation of Z z.beProductOf(br,x); } eigv = w; vec = x; } #endif // // sorting eigenvalues according to their values // do { is = 0; // label 350 for ( int i = 1; i <= nc1; i++ ) { if ( fabs( eigv.at(i + 1) ) < fabs( eigv.at(i) ) ) { is++; eigvt = eigv.at(i + 1); eigv.at(i + 1) = eigv.at(i); eigv.at(i) = eigvt; for ( int k = 1; k <= nc; k++ ) { rt = vec.at(k, i + 1); vec.at(k, i + 1) = vec.at(k, i); vec.at(k, i) = rt; } } } // label 360 } while ( is != 0 ); # ifdef DETAILED_REPORT OOFEM_LOG_INFO("SubspaceIteration :: solveYourselfAt: current eigen values of reduced problem \n"); eigv.printYourself(); OOFEM_LOG_INFO("SubspaceIteration :: solveYourselfAt: current eigen vectors of reduced problem \n"); vec.printYourself(); # endif // // compute eigenvectors // for ( int i = 1; i <= nn; i++ ) { // label 375 for ( int j = 1; j <= nc; j++ ) { tt.at(j) = r.at(i, j); } for ( int k = 1; k <= nc; k++ ) { rt = 0.; for ( int j = 1; j <= nc; j++ ) { rt += tt.at(j) * vec.at(j, k); } r.at(i, k) = rt; } } // label 420 (r = z) // // convergency check // for ( int i = 1; i <= nc; i++ ) { double dif = ( eigv.at(i) - d.at(i) ); rtolv.at(i) = fabs( dif / eigv.at(i) ); } # ifdef DETAILED_REPORT OOFEM_LOG_INFO("SubspaceIteration :: solveYourselfAt: Reached precision of eigenvalues:\n"); rtolv.printYourself(); # endif for ( int i = 1; i <= nroot; i++ ) { if ( rtolv.at(i) > rtol ) { goto label400; } } OOFEM_LOG_INFO("SubspaceIteration :: solveYourselfAt: Convergence reached for RTOL=%20.15f\n", rtol); break; label400: if ( nite >= nitem ) { OOFEM_WARNING("SubspaceIteration :: solveYourselfAt: Convergence not reached in %d iteration - using current values", nitem); break; } d = eigv; // label 410 and 440 continue; } // compute eigenvectors for ( int j = 1; j <= nc; j++ ) { tt.beColumnOf(r, j); a.backSubstitutionWith(tt); r.setColumn(tt, j); // r = xbar } // one cad add a normalization of eigen-vectors here // initialize original index locations _r.resize(nn, nroot); _eigv.resize(nroot); for ( int i = 1; i <= nroot; i++ ) { _eigv.at(i) = eigv.at(i); for ( int j = 1; j <= nn; j++ ) { _r.at(j, i) = r.at(j, i); } } return NM_Success; }
int Quad1MindlinShell3D :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { answer.resize(9); if ( ( type == IST_ShellForceTensor ) || ( type == IST_ShellMomentumTensor ) ) { const FloatArray &help = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector(); if ( type == IST_ShellForceTensor ) { answer.at(1) = help.at(1); // nx answer.at(2) = help.at(3); // vxy answer.at(3) = help.at(7); // vxz answer.at(4) = help.at(3); // vxy answer.at(5) = help.at(2); // ny answer.at(6) = help.at(8); // vyz answer.at(7) = help.at(7); // vxy answer.at(8) = help.at(8); // ny answer.at(9) = 0.0; } else { answer.at(1) = help.at(4); // mx answer.at(2) = help.at(6); // mxy answer.at(3) = 0.0; // mxz answer.at(4) = help.at(6); // mxy answer.at(5) = help.at(5); // my answer.at(6) = 0.0; // myz answer.at(7) = 0.0; // mzx answer.at(8) = 0.0; // mzy answer.at(9) = 0.0; // mz } return 1; } else if ( ( type == IST_ShellStrainTensor ) || ( type == IST_ShellCurvatureTensor ) ) { const FloatArray &help = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStrainVector(); if ( type == IST_ShellForceTensor ) { answer.at(1) = help.at(1); // nx answer.at(2) = help.at(3); // vxy answer.at(3) = help.at(7); // vxz answer.at(4) = help.at(3); // vxy answer.at(5) = help.at(2); // ny answer.at(6) = help.at(8); // vyz answer.at(7) = help.at(7); // vxy answer.at(8) = help.at(8); // ny answer.at(9) = 0.0; } else { answer.at(1) = help.at(4); // mx answer.at(2) = help.at(6); // mxy answer.at(3) = 0.0; // mxz answer.at(4) = help.at(6); // mxy answer.at(5) = help.at(5); // my answer.at(6) = 0.0; // myz answer.at(7) = 0.0; // mzx answer.at(8) = 0.0; // mzy answer.at(9) = 0.0; // mz } return 1; } else { return NLStructuralElement :: giveIPValue(answer, gp, type, tStep); } }
void VectorAssembler :: vectorFromNodeLoad(FloatArray& vec, DofManager& dman, NodalLoad* load, TimeStep* tStep, ValueModeType mode) const { vec.clear(); }
void SimpleInterfaceMaterial :: giveStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) // // Returns characteristic material stiffness matrix of the receiver // { MaterialMode mMode = gp->giveElement()->giveMaterialMode(); FloatArray strainVector; StructuralElement *el = static_cast< StructuralElement * >( gp->giveElement() ); double normalStrain; el->computeStrainVector(strainVector, gp, tStep); normalStrain = strainVector.at(1); answer.zero(); switch ( mMode ) { case _1dInterface: answer.resize(1, 1); if ( rMode == SecantStiffness || rMode == TangentStiffness ) { if ( normalStrain + normalClearance <= 0 ) { answer.at(1, 1) = this->kn; //in compression and after the clearance gap closed } else { answer.at(1, 1) = this->kn * this->stiffCoeff; } } else { if ( rMode == ElasticStiffness ) { answer.at(1, 1) = this->kn; } else { OOFEM_ERROR("unknown MatResponseMode (%s)", __MatResponseModeToString(rMode) ); } } return; case _2dInterface: answer.resize(2, 2); if ( rMode == SecantStiffness || rMode == TangentStiffness ) { if ( normalStrain + normalClearance <= 0. ) { answer.at(1, 1) = answer.at(2, 2) = this->kn; //in compression and after the clearance gap closed } else { answer.at(1, 1) = answer.at(2, 2) = this->kn * this->stiffCoeff; } } else { if ( rMode == ElasticStiffness ) { answer.at(1, 1) = answer.at(2, 2) = this->kn; } else { OOFEM_ERROR("unknown MatResponseMode (%s)", __MatResponseModeToString(rMode) ); } } return; case _3dInterface: answer.resize(3, 3); if ( rMode == SecantStiffness || rMode == TangentStiffness ) { if ( normalStrain + normalClearance <= 0. ) { answer.at(1, 1) = answer.at(2, 2) = answer.at(3, 3) = this->kn; //in compression and after the clearance gap closed } else { answer.at(1, 1) = answer.at(2, 2) = answer.at(3, 3) = this->kn * this->stiffCoeff; } } else { if ( rMode == ElasticStiffness ) { answer.at(1, 1) = answer.at(2, 2) = answer.at(3, 3) = this->kn; } else { OOFEM_ERROR("unknown MatResponseMode (%s)", __MatResponseModeToString(rMode) ); } } return; default: StructuralMaterial :: giveStiffnessMatrix(answer, rMode, gp, tStep); } }
void SimpleInterfaceMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, //const FloatArray &totalStrain,// @todo temporary -should not be here /JB const FloatArray &strainVector, TimeStep *tStep) // // returns real stress vector in 3d stress space of receiver according to // previous level of stress and current // strain increment, the only way, how to correctly update gp records // { SimpleInterfaceMaterialStatus *status = static_cast< SimpleInterfaceMaterialStatus * >( this->giveStatus(gp) ); //this->initGpForNewStep(gp); this->initTempStatus(gp); FloatArray shearStrain(2), shearStress; //, strainVector; StructuralElement *el = static_cast< StructuralElement * >( gp->giveElement() ); //el->computeStrainVector(strainVector, gp, tStep); FloatArray tempShearStressShift = status->giveTempShearStressShift(); const double normalStrain = strainVector.at(1); double normalStress, maxShearStress, dp; double shift = -this->kn * this->stiffCoeff * normalClearance; MaterialMode mMode = el->giveMaterialMode(); //answer.resize(giveSizeOfReducedStressStrainVector(mMode)); answer.zero(); if ( normalStrain + normalClearance <= 0. ) { normalStress = this->kn * ( normalStrain + normalClearance ) + shift; //in compression and after the clearance gap closed maxShearStress = fabs(normalStress) * this->frictCoeff; } else { normalStress = this->kn * this->stiffCoeff * ( normalStrain + normalClearance ) + shift; maxShearStress = 0.; } switch ( mMode ) { case _1dInterface: answer.resize(1); break; case _2dInterface: answer.resize(2); shearStrain.at(1) = strainVector.at(2); shearStress.beScaled(this->kn, shearStrain); shearStress.subtract(tempShearStressShift); dp = shearStress.dotProduct(shearStress, 1); if ( dp > maxShearStress * maxShearStress ) { shearStress.times( maxShearStress / sqrt(dp) ); } tempShearStressShift.beScaled(this->kn, shearStrain); tempShearStressShift.subtract(shearStress); answer.at(2) = shearStress.at(1); break; case _3dInterface: case _3dMat: //JB answer.resize(3); shearStrain.at(1) = strainVector.at(2); shearStrain.at(2) = strainVector.at(3); shearStress.beScaled(this->kn, shearStrain); shearStress.subtract(tempShearStressShift); dp = shearStress.dotProduct(shearStress, 2); if ( dp > maxShearStress * maxShearStress ) { shearStress.times( maxShearStress / sqrt(dp) ); } tempShearStressShift.beScaled(this->kn, shearStrain); tempShearStressShift.subtract(shearStress); answer.at(2) = shearStress.at(1); answer.at(3) = shearStress.at(2); break; default: OOFEM_ERROR("Unsupported interface mode"); } double lim = 1.e+50; answer.at(1) = min(normalStress, lim); //threshold on maximum answer.at(1) = max(answer.at(1), -lim); //threshold on minimum //answer.at(1) = normalStress > lim ? lim : normalStress < -lim ? -lim : normalStress; // update gp status->setTempShearStressShift(tempShearStressShift); status->letTempStrainVectorBe(strainVector); status->letTempStressVectorBe(answer); }
void VectorAssembler :: vectorFromSurfaceLoad(FloatArray& vec, Element& element, SurfaceLoad* load, int boundary, TimeStep* tStep, ValueModeType mode) const { vec.clear(); }
void TR_SHELL02 :: ZZErrorEstimatorI_computeLocalStress(FloatArray &answer, FloatArray &sig) { // sig is global ShellForceMomentumTensor FloatMatrix globTensor(3, 3); const FloatMatrix *GtoLRotationMatrix = plate->computeGtoLRotationMatrix(); FloatMatrix LtoGRotationMatrix; answer.resize(8); // reduced, local form LtoGRotationMatrix.beTranspositionOf(* GtoLRotationMatrix); // Forces globTensor.at(1, 1) = sig.at(1); //sxForce globTensor.at(1, 2) = sig.at(6); //qxyForce globTensor.at(1, 3) = sig.at(5); //qxzForce globTensor.at(2, 1) = sig.at(6); //qxyForce globTensor.at(2, 2) = sig.at(2); //syForce globTensor.at(2, 3) = sig.at(4); //syzForce globTensor.at(3, 1) = sig.at(5); //qxzForce globTensor.at(3, 2) = sig.at(4); //syzForce globTensor.at(3, 3) = sig.at(3); //szForce globTensor.rotatedWith(LtoGRotationMatrix); // Forces: now globTensoris transformed into local c.s // answer should be in reduced, local form answer.at(1) = globTensor.at(1, 1); //sxForce answer.at(2) = globTensor.at(2, 2); //syForce answer.at(3) = globTensor.at(1, 2); //qxyForce answer.at(7) = globTensor.at(2, 3); //syzForce answer.at(8) = globTensor.at(1, 3); //qxzForce // Moments: globTensor.at(1, 1) = sig.at(7); //mxForce globTensor.at(1, 2) = sig.at(12); //mxyForce globTensor.at(1, 3) = sig.at(11); //mxzForce globTensor.at(2, 1) = sig.at(12); //mxyForce globTensor.at(2, 2) = sig.at(8); //myForce globTensor.at(2, 3) = sig.at(10); //myzForce globTensor.at(3, 1) = sig.at(11); //mxzForce globTensor.at(3, 2) = sig.at(10); //myzForce globTensor.at(3, 3) = sig.at(9); //mzForce globTensor.rotatedWith(LtoGRotationMatrix); // now globTensoris transformed into local c.s answer.at(4) = globTensor.at(1, 1); //mxForce answer.at(5) = globTensor.at(2, 2); //myForce answer.at(6) = globTensor.at(1, 2); //mxyForce }
void NonStationaryTransportProblem :: solveYourselfAt(TimeStep *tStep) { // Creates system of governing eq's and solves them at given tStep // The solution is stored in UnknownsField. If the problem is growing/decreasing, the UnknownsField is projected on DoFs when needed. // If equations are not renumbered, the algorithm is efficient without projecting unknowns to DoFs (nodes). //Right hand side FloatArray rhs; int neq = this->giveNumberOfEquations(EID_ConservationEquation); #ifdef VERBOSE OOFEM_LOG_RELEVANT( "Solving [step number %8d, time %15e]\n", tStep->giveNumber(), tStep->giveTargetTime() ); #endif //Solution at the first time step needs history. Therefore, return back one time increment and create it. if ( tStep->isTheFirstStep() ) { this->giveSolutionStepWhenIcApply(); bcRhs.resize(neq); //rhs vector from solution step i-1 bcRhs.zero(); this->applyIC(stepWhenIcApply); //project initial conditions to have temorary temperature in integration points //edge or surface load on elements this->assembleVectorFromElements( bcRhs, stepWhenIcApply, EID_ConservationEquation, ElementBCTransportVector, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); //add prescribed value, such as temperature, on nodes this->assembleDirichletBcRhsVector( bcRhs, stepWhenIcApply, EID_ConservationEquation, VM_Total, NSTP_MidpointLhs, EModelDefaultEquationNumbering(), this->giveDomain(1) ); //add internal source vector on elements this->assembleVectorFromElements( bcRhs, stepWhenIcApply, EID_ConservationEquation, ElementInternalSourceVector, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); //add nodal load this->assembleVectorFromDofManagers( bcRhs, stepWhenIcApply, EID_ConservationEquation, ExternalForcesVector, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); } //Create a new lhs matrix if necessary if ( tStep->isTheFirstStep() || this->changingProblemSize ) { if ( conductivityMatrix ) { delete conductivityMatrix; } conductivityMatrix = CreateUsrDefSparseMtrx(sparseMtrxType); if ( conductivityMatrix == NULL ) { _error("solveYourselfAt: sparse matrix creation failed"); } conductivityMatrix->buildInternalStructure( this, 1, EID_ConservationEquation, EModelDefaultEquationNumbering() ); #ifdef VERBOSE OOFEM_LOG_INFO("Assembling conductivity and capacity matrices\n"); #endif this->assemble( conductivityMatrix, stepWhenIcApply, EID_ConservationEquation, LHSBCMatrix, EModelDefaultEquationNumbering(), this->giveDomain(1) ); conductivityMatrix->times(alpha); this->assemble( conductivityMatrix, stepWhenIcApply, EID_ConservationEquation, NSTP_MidpointLhs, EModelDefaultEquationNumbering(), this->giveDomain(1) ); } //obtain the last Rhs vector from DoFs directly if ( !tStep->isTheFirstStep() && this->changingProblemSize ) { UnknownsField->initialize(VM_RhsTotal, tStep, bcRhs); } //prepare position in UnknownsField to store the results UnknownsField->advanceSolution(tStep); FloatArray *solutionVector = UnknownsField->giveSolutionVector(tStep); solutionVector->resize(neq); solutionVector->zero(); #ifdef VERBOSE OOFEM_LOG_INFO("Assembling rhs\n"); #endif // assembling load from elements rhs = bcRhs; rhs.times(1. - alpha); bcRhs.zero(); this->assembleVectorFromElements( bcRhs, tStep, EID_ConservationEquation, ElementBCTransportVector, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); this->assembleDirichletBcRhsVector( bcRhs, tStep, EID_ConservationEquation, VM_Total, NSTP_MidpointLhs, EModelDefaultEquationNumbering(), this->giveDomain(1) ); this->assembleVectorFromElements( bcRhs, tStep, EID_ConservationEquation, ElementInternalSourceVector, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); // assembling load from nodes this->assembleVectorFromDofManagers( bcRhs, tStep, EID_ConservationEquation, InternalForcesVector, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); for ( int i = 1; i <= neq; i++ ) { rhs.at(i) += bcRhs.at(i) * alpha; } // add the rhs part depending on previous solution assembleAlgorithmicPartOfRhs( rhs, EID_ConservationEquation, EModelDefaultEquationNumbering(), tStep->givePreviousStep() ); // set-up numerical model this->giveNumericalMethod( this->giveCurrentMetaStep() ); // // call numerical model to solve arised problem // #ifdef VERBOSE OOFEM_LOG_INFO("Solving ...\n"); #endif UnknownsField->giveSolutionVector(tStep)->resize(neq); nMethod->solve( conductivityMatrix, & rhs, UnknownsField->giveSolutionVector(tStep) ); // update solution state counter tStep->incrementStateCounter(); }
void CohesiveSurface3d :: drawScalar(oofegGraphicContext &gc, TimeStep *tStep) { if ( !gc.testElementGraphicActivity(this) ) { return; } FloatArray val; GaussPoint *gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0); if ( !giveIPValue(val, gp, gc.giveIntVarType(), tStep) ) { return; } int indx = gc.giveIntVarIndx(); double s [ 8 ]; for ( int i = 0; i < 8; i++ ) { s [ i ] = val.at(indx); } gc.updateFringeTableMinMax(s, 1); WCRec p [ 8 ]; Particle *nodeA = ( Particle * ) giveNode(1); Particle *nodeB = ( Particle * ) giveNode(2); if ( gc.getInternalVarsDefGeoFlag() ) { // use deformed geometry double defScale = gc.getDefScale(); p [ 0 ].x = nodeA->giveUpdatedCoordinate(1, tStep, defScale); p [ 0 ].y = nodeA->giveUpdatedCoordinate(2, tStep, defScale); p [ 0 ].z = nodeA->giveUpdatedCoordinate(3, tStep, defScale); p [ 2 ].x = nodeB->giveUpdatedCoordinate(1, tStep, defScale); p [ 2 ].y = nodeB->giveUpdatedCoordinate(2, tStep, defScale); p [ 2 ].z = nodeB->giveUpdatedCoordinate(3, tStep, defScale); // handle special elements crossing the boundary of the periodic cell if ( giveNumberOfNodes() == 3 ) { Node *nodeC = ( Particle * ) giveNode(3); p [ 2 ].x += kxa + kxa * defScale * ( nodeC->giveDofWithID(D_u)->giveUnknown(VM_Total, tStep) ) + kyb * defScale * ( nodeC->giveDofWithID(R_u)->giveUnknown(VM_Total, tStep) ); p [ 2 ].y += kyb + kyb * defScale * ( nodeC->giveDofWithID(D_v)->giveUnknown(VM_Total, tStep) ) + kzc * defScale * ( nodeC->giveDofWithID(R_v)->giveUnknown(VM_Total, tStep) ); p [ 2 ].z += kzc + kzc * defScale * ( nodeC->giveDofWithID(D_w)->giveUnknown(VM_Total, tStep) ) + kxa * defScale * ( nodeC->giveDofWithID(R_w)->giveUnknown(VM_Total, tStep) ); } } else { // use initial geometry p [ 0 ].x = nodeA->giveCoordinate(1); p [ 0 ].y = nodeA->giveCoordinate(2); p [ 0 ].z = nodeA->giveCoordinate(3); p [ 2 ].x = nodeB->giveCoordinate(1); p [ 2 ].y = nodeB->giveCoordinate(2); p [ 2 ].z = nodeB->giveCoordinate(3); // handle special elements crossing the boundary of the periodic cell if ( giveNumberOfNodes() == 3 ) { p [ 2 ].x += kxa; p [ 2 ].y += kyb; p [ 2 ].z += kzc; } } double r1 = nodeA->giveRadius(); double r2 = nodeB->giveRadius(); double d = 0.1 * ( r1 + r2 ); p [ 1 ].x = 0.5 * ( p [ 0 ].x + p [ 2 ].x - d * lcs.at(2, 1) - d * lcs.at(3, 1) ); p [ 1 ].y = 0.5 * ( p [ 0 ].y + p [ 2 ].y - d * lcs.at(2, 2) - d * lcs.at(3, 2) ); p [ 1 ].z = 0.5 * ( p [ 0 ].z + p [ 2 ].z - d * lcs.at(2, 3) - d * lcs.at(3, 3) ); p [ 3 ].x = p [ 1 ].x + d *lcs.at(2, 1); p [ 3 ].y = p [ 1 ].y + d *lcs.at(2, 2); p [ 3 ].z = p [ 1 ].z + d *lcs.at(2, 3); for ( int i = 5; i < 8; i += 2 ) { p [ i ].x = p [ i - 4 ].x + d *lcs.at(3, 1); p [ i ].y = p [ i - 4 ].y + d *lcs.at(3, 2); p [ i ].z = p [ i - 4 ].z + d *lcs.at(3, 3); } p [ 4 ] = p [ 0 ]; p [ 6 ] = p [ 2 ]; GraphicObj *go = CreateHexahedronWD(p, s); EASValsSetLayer(OOFEG_VARPLOT_PATTERN_LAYER); EASValsSetLineWidth(2 * OOFEG_DEFORMED_GEOMETRY_WIDTH); EASValsSetFillStyle(FILL_SOLID); //EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); EGWithMaskChangeAttributes(WIDTH_MASK | FILL_MASK | LAYER_MASK, go); EMAddGraphicsToModel(ESIModel(), go); }
void MatrixProductAssembler :: vectorFromLoad(FloatArray& vec, Element& element, BodyLoad* load, TimeStep* tStep, ValueModeType mode) const { FloatMatrix mat; this->mAssem.matrixFromLoad(mat, element, load, tStep); vec.beProductOf(mat, this->vec); }
void VectorAssembler :: vectorFromElement(FloatArray& vec, Element& element, TimeStep* tStep, ValueModeType mode) const { vec.clear(); }
void SurfaceTensionBoundaryCondition :: computeTangentFromElement(FloatMatrix &answer, Element *e, int side, TimeStep *tStep) { FEInterpolation *fei = e->giveInterpolation(); if ( !fei ) { OOFEM_ERROR("No interpolation available for element."); } std :: unique_ptr< IntegrationRule > iRule( fei->giveBoundaryIntegrationRule(fei->giveInterpolationOrder()-1, side) ); int nsd = e->giveDomain()->giveNumberOfSpatialDimensions(); int nodes = e->giveNumberOfNodes(); if ( side == -1 ) { side = 1; } answer.clear(); if ( nsd == 2 ) { FEInterpolation2d *fei2d = static_cast< FEInterpolation2d * >(fei); ///@todo More of this grunt work should be moved to the interpolation classes FloatMatrix xy(2, nodes); Node *node; for ( int i = 1; i <= nodes; i++ ) { node = e->giveNode(i); xy.at(1, i) = node->giveCoordinate(1); xy.at(2, i) = node->giveCoordinate(2); } FloatArray tmpA(2 *nodes); FloatArray es; // Tangent vector to curve FloatArray dNds; FloatMatrix B(2, 2 *nodes); B.zero(); if ( e->giveDomain()->isAxisymmetric() ) { FloatArray N; FloatArray gcoords; FloatArray tmpB(2 *nodes); for ( GaussPoint *gp: *iRule ) { fei2d->edgeEvaldNds( dNds, side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); fei->boundaryEvalN( N, side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); double J = fei->boundaryGiveTransformationJacobian( side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); fei->boundaryLocal2Global( gcoords, side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); double r = gcoords(0); // First coordinate is the radial coord. es.beProductOf(xy, dNds); // Construct the different matrices in the integrand; for ( int i = 0; i < nodes; i++ ) { tmpA(i * 2 + 0) = dNds(i) * es(0); tmpA(i * 2 + 1) = dNds(i) * es(1); tmpB(i * 2 + 0) = N(i); tmpB(i * 2 + 1) = 0; B(i * 2, 0) = B(i * 2 + 1, 1) = dNds(i); } double dV = 2 *M_PI *gamma *J *gp->giveWeight(); answer.plusDyadUnsym(tmpA, tmpB, dV); answer.plusDyadUnsym(tmpB, tmpA, dV); answer.plusProductSymmUpper(B, B, r * dV); answer.plusDyadUnsym(tmpA, tmpA, -r * dV); } } else { for ( GaussPoint *gp: *iRule ) { double t = e->giveCrossSection()->give(CS_Thickness, gp); ///@todo The thickness is not often relevant or used in FM. fei2d->edgeEvaldNds( dNds, side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); double J = fei->boundaryGiveTransformationJacobian( side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); es.beProductOf(xy, dNds); // Construct the different matrices in the integrand; for ( int i = 0; i < nodes; i++ ) { tmpA(i * 2 + 0) = dNds(i) * es(0); tmpA(i * 2 + 1) = dNds(i) * es(1); B(i * 2, 0) = B(i * 2 + 1, 1) = dNds(i); } double dV = t * gamma * J * gp->giveWeight(); answer.plusProductSymmUpper(B, B, dV); answer.plusDyadSymmUpper(tmpA, -dV); } } answer.symmetrized(); } else if ( nsd == 3 ) { FEInterpolation3d *fei3d = static_cast< FEInterpolation3d * >(fei); OOFEM_ERROR("3D tangents not implemented yet."); //FloatMatrix tmp(3 *nodes, 3 *nodes); FloatMatrix dNdx; FloatArray n; for ( GaussPoint *gp: *iRule ) { fei3d->surfaceEvaldNdx( dNdx, side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); /*double J = */ fei->boundaryEvalNormal( n, side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); //double dV = gamma * J * gp->giveWeight(); for ( int i = 0; i < nodes; i++ ) { //tmp(3*i+0) = dNdx(i,0) - (dNdx(i,0)*n(0)* + dNdx(i,1)*n(1) + dNdx(i,2)*n(2))*n(0); //tmp(3*i+1) = dNdx(i,1) - (dNdx(i,0)*n(0)* + dNdx(i,1)*n(1) + dNdx(i,2)*n(2))*n(1); //tmp(3*i+2) = dNdx(i,2) - (dNdx(i,0)*n(0)* + dNdx(i,1)*n(1) + dNdx(i,2)*n(2))*n(2); } //answer.plusProductSymmUpper(A,B, dV); ///@todo Derive expressions for this. } } else { OOFEM_WARNING("Only 2D or 3D is possible!"); } }
void Quad1MindlinShell3D :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) { // Only gravity load double dV, density; FloatArray forceX, forceY, forceZ, glob_gravity, gravity, n; if ( ( forLoad->giveBCGeoType() != BodyLoadBGT ) || ( forLoad->giveBCValType() != ForceLoadBVT ) ) { OOFEM_ERROR("unknown load type"); } // note: force is assumed to be in global coordinate system. forLoad->computeComponentArrayAt(glob_gravity, tStep, mode); // Transform the load into the local c.s. gravity.beProductOf(this->lcsMatrix, glob_gravity); ///@todo Check potential transpose here. if ( gravity.giveSize() ) { for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { this->interp.evalN( n, * gp->giveNaturalCoordinates(), FEIVoidCellGeometry() ); dV = this->computeVolumeAround(gp) * this->giveCrossSection()->give(CS_Thickness, gp); density = this->giveStructuralCrossSection()->give('d', gp); forceX.add(density * gravity.at(1) * dV, n); forceY.add(density * gravity.at(2) * dV, n); forceZ.add(density * gravity.at(3) * dV, n); } answer.resize(24); answer.zero(); answer.at(1) = forceX.at(1); answer.at(2) = forceY.at(1); answer.at(3) = forceZ.at(1); answer.at(7) = forceX.at(2); answer.at(8) = forceY.at(2); answer.at(9) = forceZ.at(2); answer.at(13) = forceX.at(3); answer.at(14) = forceY.at(3); answer.at(15) = forceZ.at(3); answer.at(19) = forceX.at(4); answer.at(20) = forceY.at(4); answer.at(21) = forceZ.at(4); } else { answer.clear(); } }
void SurfaceTensionBoundaryCondition :: computeLoadVectorFromElement(FloatArray &answer, Element *e, int side, TimeStep *tStep) { FEInterpolation *fei = e->giveInterpolation(); if ( !fei ) { OOFEM_ERROR("No interpolation or default integration available for element."); } std :: unique_ptr< IntegrationRule > iRule( fei->giveBoundaryIntegrationRule(fei->giveInterpolationOrder()-1, side) ); int nsd = e->giveDomain()->giveNumberOfSpatialDimensions(); if ( side == -1 ) { side = 1; } answer.clear(); if ( nsd == 2 ) { FEInterpolation2d *fei2d = static_cast< FEInterpolation2d * >(fei); ///@todo More of this grunt work should be moved to the interpolation classes IntArray bnodes; fei2d->boundaryGiveNodes(bnodes, side); int nodes = bnodes.giveSize(); FloatMatrix xy(2, nodes); for ( int i = 1; i <= nodes; i++ ) { Node *node = e->giveNode(bnodes.at(i)); ///@todo This should rely on the xindex and yindex in the interpolator.. xy.at(1, i) = node->giveCoordinate(1); xy.at(2, i) = node->giveCoordinate(2); } FloatArray tmp; // Integrand FloatArray es; // Tangent vector to curve FloatArray dNds; if ( e->giveDomain()->isAxisymmetric() ) { FloatArray N; FloatArray gcoords; for ( GaussPoint *gp: *iRule ) { fei2d->edgeEvaldNds( dNds, side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); fei->boundaryEvalN( N, side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); double J = fei->boundaryGiveTransformationJacobian( side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); fei->boundaryLocal2Global( gcoords, side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); double r = gcoords(0); // First coordinate is the radial coord. es.beProductOf(xy, dNds); tmp.resize( 2 * nodes); for ( int i = 0; i < nodes; i++ ) { tmp(2 * i) = dNds(i) * es(0) * r + N(i); tmp(2 * i + 1) = dNds(i) * es(1) * r; } answer.add(- 2 * M_PI * gamma * J * gp->giveWeight(), tmp); } } else { for ( GaussPoint *gp: *iRule ) { double t = e->giveCrossSection()->give(CS_Thickness, gp); fei2d->edgeEvaldNds( dNds, side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); double J = fei->boundaryGiveTransformationJacobian( side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); es.beProductOf(xy, dNds); tmp.resize( 2 * nodes); for ( int i = 0; i < nodes; i++ ) { tmp(2 * i) = dNds(i) * es(0); tmp(2 * i + 1) = dNds(i) * es(1); //B.at(1, 1+i*2) = B.at(2, 2+i*2) = dNds(i); } //tmp.beTProductOf(B, es); answer.add(- t * gamma * J * gp->giveWeight(), tmp); } } } else if ( nsd == 3 ) { FEInterpolation3d *fei3d = static_cast< FEInterpolation3d * >(fei); FloatArray n, surfProj; FloatMatrix dNdx, B; for ( GaussPoint *gp: *iRule ) { fei3d->surfaceEvaldNdx( dNdx, side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); double J = fei->boundaryEvalNormal( n, side, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e) ); // [I - n(x)n] in voigt form: surfProj = {1. - n(0)*n(0), 1. - n(1)*n(1), 1. - n(2)*n(2), - n(1)*n(2), - n(0)*n(2), - n(0)*n(1), }; // Construct B matrix of the surface nodes B.resize(6, 3 * dNdx.giveNumberOfRows()); for ( int i = 1; i <= dNdx.giveNumberOfRows(); i++ ) { B.at(1, 3 * i - 2) = dNdx.at(i, 1); B.at(2, 3 * i - 1) = dNdx.at(i, 2); B.at(3, 3 * i - 0) = dNdx.at(i, 3); B.at(5, 3 * i - 2) = B.at(4, 3 * i - 1) = dNdx.at(i, 3); B.at(6, 3 * i - 2) = B.at(4, 3 * i - 0) = dNdx.at(i, 2); B.at(6, 3 * i - 1) = B.at(5, 3 * i - 0) = dNdx.at(i, 1); } answer.plusProduct(B, surfProj, -gamma * J * gp->giveWeight() ); } } }
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 VectorAssembler :: vectorFromEdgeLoad(FloatArray& vec, Element& element, EdgeLoad* load, int edge, TimeStep* tStep, ValueModeType mode) const { vec.clear(); }