bool NodeErrorCheckingRule :: check(Domain *domain, TimeStep *tStep) { // Rule doesn't apply yet. if ( tStep->giveNumber() != tstep ) { return true; } DofManager *dman = domain->giveGlobalDofManager(number); if ( !dman ) { if ( domain->giveEngngModel()->isParallel() ) { return true; } else { OOFEM_WARNING("Dof manager %d not found.", number); return false; } } if ( dman->giveParallelMode() == DofManager_remote || dman->giveParallelMode() == DofManager_null ) { return true; } Dof *dof = dman->giveDofWithID(dofid); double dmanValue = dof->giveUnknown(mode, tStep); bool check = checkValue(dmanValue); if ( !check ) { OOFEM_WARNING("Check failed in: tstep %d, node %d, dof %d, mode %d:\n" "value is %.8e, but should be %.8e ( error is %e but tolerance is %e )", tstep, number, dofid, mode, dmanValue, value, fabs(dmanValue-value), tolerance ); } return check; }
void Tr21Stokes :: giveIntegratedVelocity(FloatMatrix &answer, TimeStep *tStep ) { /* * Integrate velocity over element */ IntegrationRule *iRule = integrationRulesArray [ 0 ]; FloatMatrix v, v_gamma, ThisAnswer, boundaryV, Nmatrix; double detJ; FloatArray *lcoords, N; int i, j, k=0; Dof *d; GaussPoint *gp; v.resize(12,1); v.zero(); boundaryV.resize(2,1); for (i=1; i<=this->giveNumberOfDofManagers(); i++) { for (j=1; j<=this->giveDofManager(i)->giveNumberOfDofs(); j++) { d = this->giveDofManager(i)->giveDof(j); if ((d->giveDofID()==V_u) || (d->giveDofID()==V_v)) { k=k+1; v.at(k,1)=d->giveUnknown(EID_ConservationEquation, VM_Total, tStep); /*} else if (d->giveDofID()==A_x) { boundaryV.at(1,1)=d->giveUnknown(EID_ConservationEquation, VM_Total, tStep); } else if (d->giveDofID()==A_y) { boundaryV.at(2,1)=d->giveUnknown(EID_ConservationEquation, VM_Total, tStep);*/ } } } answer.resize(2,1); answer.zero(); Nmatrix.resize(2,12); for (i=0; i<iRule->getNumberOfIntegrationPoints(); i++) { gp = iRule->getIntegrationPoint(i); lcoords = gp->giveCoordinates(); this->interpolation_quad.evalN(N, *lcoords, FEIElementGeometryWrapper(this)); detJ = this->interpolation_quad.giveTransformationJacobian(*lcoords, FEIElementGeometryWrapper(this)); N.times(detJ*gp->giveWeight()); for (j=1; j<=6;j++) { Nmatrix.at(1,j*2-1)=N.at(j); Nmatrix.at(2,j*2)=N.at(j); } ThisAnswer.beProductOf(Nmatrix,v); answer.add(ThisAnswer); } }
double PrescribedGradientBCPeriodic :: giveUnknown(double val, ValueModeType mode, TimeStep *tStep, ActiveDof *dof) { DofManager *master = this->domain->giveDofManager(this->slavemap[dof->giveDofManager()->giveNumber()]); DofIDItem id = dof->giveDofID(); FloatArray *coords = dof->giveDofManager()->giveCoordinates(); FloatArray *masterCoords = master->giveCoordinates(); FloatArray dx, uM; dx.beDifferenceOf(* coords, * masterCoords ); int ind; if ( id == D_u || id == V_u || id == P_f || id == T_f ) { ind = 1; } else if ( id == D_v || id == V_v ) { ind = 2; } else { /*if ( id == D_w || id == V_w )*/ // 3D only: ind = 3; } FloatMatrix grad(3, 3); for ( int i = 0; i < this->strain_id.giveSize(); ++i ) { Dof *dof = this->strain->giveDofWithID(strain_id[i]); grad(i % 3, i / 3) = dof->giveUnknown(mode, tStep); } uM.beProductOf(grad, dx); // The "jump" part of the unknown ( u^+ = [[u^M]] + u^- ) return val + uM.at(ind); }
void IncrementalLinearStatic :: updateDofUnknownsDictionary(DofManager *inode, TimeStep *tStep) { // update DOF unknowns dictionary, where // unknowns are hold instead of keeping them in global unknowns // vectors in engng instances // this is necessary, because during solution equation numbers for // particular DOFs may changed, and it is necessary to keep them // in DOF level. int ndofs = inode->giveNumberOfDofs(); Dof *iDof; double val; for ( int i = 1; i <= ndofs; i++ ) { iDof = inode->giveDof(i); // skip slave DOFs (only master (primary) DOFs have to be updated). if (!iDof->isPrimaryDof()) continue; val = iDof->giveUnknown(VM_Total, tStep); if ( !iDof->hasBc(tStep) ) { val += this->incrementOfDisplacementVector.at( iDof->__giveEquationNumber() ); } iDof->updateUnknownsDictionary(tStep, VM_Total_Old, val); iDof->updateUnknownsDictionary(tStep, VM_Total, val); } }
void Node2NodeContactL :: computeContactTractionAt(GaussPoint *gp, FloatArray &t, FloatArray &gap, TimeStep *tStep) { // should be replaced with a call to constitutive model // gap should be in a local system if ( gap.at(1) < 0.0 ) { Dof *dof = masterNode->giveDofWithID( this->giveDofIdArray().at(1) ); double lambda = dof->giveUnknown(VM_Total, tStep); t = {lambda, 0.0, 0.0}; //printf("lambda %e \n\n", lambda); } else { t = {0.0, 0.0, 0.0}; } }
void MatlabExportModule :: doOutputData(TimeStep *tStep, FILE *FID) { Domain *domain = emodel->giveDomain(1); std :: vector< int >DofIDList; std :: vector< int > :: iterator it; std :: vector< std :: vector< double > * >valuesList; std :: vector< double > *values; for ( int i = 1; i <= domain->giveNumberOfDofManagers(); i++ ) { for ( int j = 1; j <= domain->giveDofManager(i)->giveNumberOfDofs(); j++ ) { Dof *thisDof; thisDof = domain->giveDofManager(i)->giveDof(j); it = std :: find( DofIDList.begin(), DofIDList.end(), thisDof->giveDofID() ); if ( it == DofIDList.end() ) { DofIDList.push_back( thisDof->giveDofID() ); values = new( std :: vector< double > ); valuesList.push_back(values); } else { int pos = it - DofIDList.begin(); values = valuesList.at(pos); } double value = thisDof->giveUnknown(EID_MomentumBalance, VM_Total, tStep); values->push_back(value); } } fprintf(FID, "\tdata.DofIDs=["); for ( size_t i = 0; i < DofIDList.size(); i++ ) { fprintf( FID, "%u, ", DofIDList.at(i) ); } fprintf(FID, "];\n"); for ( size_t i = 0; i < valuesList.size(); i++ ) { fprintf(FID, "\tdata.a{%lu}=[", static_cast<long unsigned int>(i) + 1); for ( size_t j = 0; j < valuesList.at(i)->size(); j++ ) { fprintf( FID, "%f,", valuesList.at(i)->at(j) ); } fprintf(FID, "];\n"); } }
void CoupledFieldsElement :: computeVectorOfDofIDs(const IntArray &dofIdArray, ValueModeType valueMode, TimeStep *stepN, FloatArray &answer) { // Routine to extract the solution vector for an element given an dofid array. // Size will be numberOfDofs and if a certain dofId does not exist a zero is used as value. answer.resize( numberOfDofMans * dofIdArray.giveSize() ); // equal number of nodes for all fields answer.zero(); int k = 1; for ( int i = 1; i <= numberOfDofMans; i++ ) { DofManager *dMan = this->giveDofManager(i); for (int j = 1; j <= dofIdArray.giveSize(); j++ ) { if ( dMan->hasDofID( (DofIDItem) dofIdArray.at(j) ) ) { Dof *d = dMan->giveDofWithID( dofIdArray.at(j) ); answer.at(k) = d->giveUnknown(valueMode, stepN); } k++; } } }
void LinearConstraintBC :: assembleVector(FloatArray &answer, TimeStep *tStep, EquationID eid, CharType type, ValueModeType mode, const UnknownNumberingScheme &s, FloatArray *eNorms) { IntArray loc, lambdaeq(1); FloatArray vec(1); double factor=1.; if (!this->rhsType.contains((int) type)) return ; if (!this->isImposed(tStep)) return; if (type == InternalForcesVector) { // compute true residual int size = this->weights.giveSize(); Dof *idof; // assemble location array for ( int _i = 1; _i <= size; _i++ ) { factor=1.; if(weightsLtf.giveSize()){ factor = domain->giveLoadTimeFunction(weightsLtf.at(_i))->__at(tStep->giveIntrinsicTime()); } idof = this->domain->giveDofManager( this->dofmans.at(_i) )->giveDof( this->dofs.at(_i) ); answer.at(s.giveDofEquationNumber(idof)) += md->giveDof(1)->giveUnknown(mode, tStep) * this->weights.at(_i)*factor; answer.at(s.giveDofEquationNumber( md->giveDof(1) )) += idof->giveUnknown(mode, tStep) * this->weights.at(_i)*factor; } } else { // use rhs value if(rhsLtf){ factor = domain->giveLoadTimeFunction(rhsLtf)->__at(tStep->giveIntrinsicTime()); } this->giveLocArray(s, loc, lambdaeq.at(1)); vec.at(1) = rhs*factor; answer.assemble(vec, lambdaeq); } }
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 DEIDynamic :: solveYourselfAt(TimeStep *tStep) { // // creates system of governing eq's and solves them at given time step // // this is an explicit problem: we assemble governing equating at time t // and solution is obtained for time t+dt // // first assemble problem at current time step to obtain results in following // time step. // and then print results for this step also. // for first time step we need special start code Domain *domain = this->giveDomain(1); int nelem = domain->giveNumberOfElements(); int nman = domain->giveNumberOfDofManagers(); IntArray loc; Element *element; DofManager *node; Dof *iDof; int nDofs, neq; int i, k, n, j, jj, kk, init = 0; double coeff, maxDt, maxOmi, maxOm = 0., maxOmEl, c1, c2, c3; FloatMatrix charMtrx, charMtrx2; FloatArray previousDisplacementVector; neq = this->giveNumberOfEquations(EID_MomentumBalance); if ( tStep->giveNumber() == giveNumberOfFirstStep() ) { init = 1; #ifdef VERBOSE OOFEM_LOG_INFO("Assembling mass matrix\n"); #endif // // first step assemble mass Matrix // massMatrix.resize(neq); massMatrix.zero(); EModelDefaultEquationNumbering dn; for ( i = 1; i <= nelem; i++ ) { element = domain->giveElement(i); element->giveLocationArray(loc, EID_MomentumBalance, dn); element->giveCharacteristicMatrix(charMtrx, LumpedMassMatrix, tStep); // charMtrx.beLumpedOf(fullCharMtrx); element->giveCharacteristicMatrix(charMtrx2, StiffnessMatrix, tStep); // // assemble it manually // #ifdef DEBUG if ( ( n = loc.giveSize() ) != charMtrx.giveNumberOfRows() ) { _error("solveYourselfAt : dimension mismatch"); } #endif n = loc.giveSize(); maxOmEl = 0.; for ( j = 1; j <= n; j++ ) { if ( charMtrx.at(j, j) > ZERO_MASS ) { maxOmi = charMtrx2.at(j, j) / charMtrx.at(j, j); if ( init ) { maxOmEl = ( maxOmEl > maxOmi ) ? ( maxOmEl ) : ( maxOmi ); } } } maxOm = ( maxOm > maxOmEl ) ? ( maxOm ) : ( maxOmEl ); for ( j = 1; j <= n; j++ ) { jj = loc.at(j); if ( ( jj ) && ( charMtrx.at(j, j) <= ZERO_MASS ) ) { charMtrx.at(j, j) = charMtrx2.at(j, j) / maxOmEl; } } for ( j = 1; j <= n; j++ ) { jj = loc.at(j); if ( jj ) { massMatrix.at(jj) += charMtrx.at(j, j); } } } // if init - try to determine the best deltaT if ( init ) { maxDt = 2 / sqrt(maxOm); if ( deltaT > maxDt ) { OOFEM_LOG_RELEVANT("DEIDynamic: deltaT reduced to %e\n", maxDt); deltaT = maxDt; tStep->setTimeIncrement(deltaT); } } // // special init step - compute displacements at tstep 0 // displacementVector.resize(neq); displacementVector.zero(); nextDisplacementVector.resize(neq); nextDisplacementVector.zero(); velocityVector.resize(neq); velocityVector.zero(); accelerationVector.resize(neq); accelerationVector.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) // now we are setting initial cond. for step -1. iDof = node->giveDof(k); if ( !iDof->isPrimaryDof() ) { continue; } jj = iDof->__giveEquationNumber(); if ( jj ) { nextDisplacementVector.at(jj) = iDof->giveUnknown(EID_MomentumBalance, VM_Total, tStep); // become displacementVector after init velocityVector.at(jj) = iDof->giveUnknown(EID_MomentumBalance, VM_Velocity, tStep); // accelerationVector = iDof->giveUnknown(AccelerartionVector,tStep) ; } } } for ( j = 1; j <= neq; j++ ) { nextDisplacementVector.at(j) -= velocityVector.at(j) * ( deltaT ); } return; } // end of init step #ifdef VERBOSE OOFEM_LOG_INFO("Assembling right hand side\n"); #endif c1 = ( 1. / ( deltaT * deltaT ) ); c2 = ( 1. / ( 2. * deltaT ) ); c3 = ( 2. / ( deltaT * deltaT ) ); previousDisplacementVector = displacementVector; displacementVector = nextDisplacementVector; // // assembling the element part of load vector // loadVector.resize( this->giveNumberOfEquations(EID_MomentumBalance) ); loadVector.zero(); this->assembleVector(loadVector, tStep, EID_MomentumBalance, ExternalForcesVector, VM_Total, EModelDefaultEquationNumbering(), domain); // // assembling additional parts of right hand side // EModelDefaultEquationNumbering dn; for ( i = 1; i <= nelem; i++ ) { element = domain->giveElement(i); element->giveLocationArray(loc, EID_MomentumBalance, dn); element->giveCharacteristicMatrix(charMtrx, StiffnessMatrix, tStep); n = loc.giveSize(); for ( j = 1; j <= n; j++ ) { jj = loc.at(j); if ( jj ) { for ( k = 1; k <= n; k++ ) { kk = loc.at(k); if ( kk ) { loadVector.at(jj) -= charMtrx.at(j, k) * displacementVector.at(kk); } } // // if init step - find minimum period of vibration in order to // determine maximal admissible time step // //maxOmi = charMtrx.at(j,j)/massMatrix.at(jj) ; //if (init) maxOm = (maxOm > maxOmi) ? (maxOm) : (maxOmi) ; } } } for ( j = 1; j <= neq; j++ ) { coeff = massMatrix.at(j); loadVector.at(j) += coeff * c3 * displacementVector.at(j) - coeff * ( c1 - dumpingCoef * c2 ) * previousDisplacementVector.at(j); } // // set-up numerical model // /* it is not necessary to call numerical method * approach used here is not good, but effective enough * inverse of diagonal mass matrix is done here */ // // call numerical model to solve arose problem - done locally here // #ifdef VERBOSE OOFEM_LOG_RELEVANT( "Solving [step number %8d, time %15e]\n", tStep->giveNumber(), tStep->giveTargetTime() ); #endif double prevD; for ( i = 1; i <= neq; i++ ) { prevD = previousDisplacementVector.at(i); nextDisplacementVector.at(i) = loadVector.at(i) / ( massMatrix.at(i) * ( c1 + dumpingCoef * c2 ) ); velocityVector.at(i) = nextDisplacementVector.at(i) - prevD; accelerationVector.at(i) = nextDisplacementVector.at(i) - 2. * displacementVector.at(i) + prevD; } accelerationVector.times(c1); velocityVector.times(c2); }
void NonLinearDynamic :: proceedStep(int di, TimeStep *tStep) { // creates system of governing eq's and solves them at given time step // first assemble problem at current time step int neq = this->giveNumberOfDomainEquations(1, EModelDefaultEquationNumbering()); // Time-stepping constants this->determineConstants(tStep); if ( ( tStep->giveNumber() == giveNumberOfFirstStep() ) && initFlag ) { // Initialization incrementOfDisplacement.resize(neq); incrementOfDisplacement.zero(); totalDisplacement.resize(neq); totalDisplacement.zero(); velocityVector.resize(neq); velocityVector.zero(); accelerationVector.resize(neq); accelerationVector.zero(); internalForces.resize(neq); internalForces.zero(); previousIncrementOfDisplacement.resize(neq); previousIncrementOfDisplacement.zero(); previousTotalDisplacement.resize(neq); previousTotalDisplacement.zero(); previousVelocityVector.resize(neq); previousVelocityVector.zero(); previousAccelerationVector.resize(neq); previousAccelerationVector.zero(); previousInternalForces.resize(neq); previousInternalForces.zero(); TimeStep *stepWhenIcApply = new TimeStep(giveNumberOfTimeStepWhenIcApply(), this, 0, -deltaT, deltaT, 0); int nDofs, j, k, jj; int nman = this->giveDomain(di)->giveNumberOfDofManagers(); DofManager *node; Dof *iDof; // Considering initial conditions. for ( j = 1; j <= nman; j++ ) { node = this->giveDomain(di)->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 ) { totalDisplacement.at(jj) = iDof->giveUnknown(VM_Total, stepWhenIcApply); velocityVector.at(jj) = iDof->giveUnknown(VM_Velocity, stepWhenIcApply); accelerationVector.at(jj) = iDof->giveUnknown(VM_Acceleration, stepWhenIcApply); } } } this->giveInternalForces(internalForces, true, di, tStep); } if ( initFlag ) { // First assemble problem at current time step. // Option to take into account initial conditions. if ( !effectiveStiffnessMatrix ) { effectiveStiffnessMatrix = classFactory.createSparseMtrx(sparseMtrxType); massMatrix = classFactory.createSparseMtrx(sparseMtrxType); } if ( effectiveStiffnessMatrix == NULL || massMatrix == NULL ) { _error("proceedStep: sparse matrix creation failed"); } if ( nonlocalStiffnessFlag ) { if ( !effectiveStiffnessMatrix->isAsymmetric() ) { _error("proceedStep: effectiveStiffnessMatrix does not support asymmetric storage"); } } effectiveStiffnessMatrix->buildInternalStructure( this, di, EID_MomentumBalance, EModelDefaultEquationNumbering() ); massMatrix->buildInternalStructure( this, di, EID_MomentumBalance, EModelDefaultEquationNumbering() ); // Assemble mass matrix this->assemble(massMatrix, tStep, EID_MomentumBalance, MassMatrix, EModelDefaultEquationNumbering(), this->giveDomain(di)); // Initialize vectors help.resize(neq); help.zero(); rhs.resize(neq); rhs.zero(); rhs2.resize(neq); rhs2.zero(); previousIncrementOfDisplacement.resize(neq); previousTotalDisplacement.resize(neq); previousVelocityVector.resize(neq); previousAccelerationVector.resize(neq); previousInternalForces.resize(neq); for ( int i = 1; i <= neq; i++ ) { previousIncrementOfDisplacement.at(i) = incrementOfDisplacement.at(i); previousTotalDisplacement.at(i) = totalDisplacement.at(i); previousVelocityVector.at(i) = velocityVector.at(i); previousAccelerationVector.at(i) = accelerationVector.at(i); previousInternalForces.at(i) = internalForces.at(i); } forcesVector.resize(neq); forcesVector.zero(); totIterations = 0; initFlag = 0; } #ifdef VERBOSE OOFEM_LOG_DEBUG("Assembling load\n"); #endif // Assemble the incremental reference load vector. this->assembleIncrementalReferenceLoadVectors(incrementalLoadVector, incrementalLoadVectorOfPrescribed, refLoadInputMode, this->giveDomain(di), EID_MomentumBalance, tStep); // Assembling the effective load vector for ( int i = 1; i <= neq; i++ ) { help.at(i) = a2 * previousVelocityVector.at(i) + a3 * previousAccelerationVector.at(i) + eta * ( a4 * previousVelocityVector.at(i) + a5 * previousAccelerationVector.at(i) + a6 * previousIncrementOfDisplacement.at(i) ); } massMatrix->times(help, rhs); if ( delta != 0 ) { for ( int i = 1; i <= neq; i++ ) { help.at(i) = delta * ( a4 * previousVelocityVector.at(i) + a5 * previousAccelerationVector.at(i) + a6 * previousIncrementOfDisplacement.at(i) ); } this->timesMtrx(help, rhs2, TangentStiffnessMatrix, this->giveDomain(di), tStep); help.zero(); for ( int i = 1; i <= neq; i++ ) { rhs.at(i) += rhs2.at(i); } } for ( int i = 1; i <= neq; i++ ) { rhs.at(i) += incrementalLoadVector.at(i) - previousInternalForces.at(i); } // // Set-up numerical model. // this->giveNumericalMethod( this->giveCurrentMetaStep() ); // // Call numerical model to solve problem. // double loadLevel = 1.0; if ( totIterations == 0 ) { incrementOfDisplacement.zero(); } if ( initialLoadVector.isNotEmpty() ) { numMetStatus = nMethod->solve(effectiveStiffnessMatrix, & rhs, & initialLoadVector, & totalDisplacement, & incrementOfDisplacement, & forcesVector, internalForcesEBENorm, loadLevel, refLoadInputMode, currentIterations, tStep); } else { numMetStatus = nMethod->solve(effectiveStiffnessMatrix, & rhs, NULL, & totalDisplacement, & incrementOfDisplacement, & forcesVector, internalForcesEBENorm, loadLevel, refLoadInputMode, currentIterations, tStep); } for ( int i = 1; i <= neq; i++ ) { rhs.at(i) = previousVelocityVector.at(i); rhs2.at(i) = previousAccelerationVector.at(i); accelerationVector.at(i) = a0 * incrementOfDisplacement.at(i) - a2 * rhs.at(i) - a3 * rhs2.at(i); velocityVector.at(i) = a1 * incrementOfDisplacement.at(i) - a4 * rhs.at(i) - a5 * rhs2.at(i) - a6 * previousIncrementOfDisplacement.at(i); } totIterations += currentIterations; }
void GnuplotExportModule::outputBoundaryCondition(PrescribedGradientBCWeak &iBC, TimeStep *tStep) { FloatArray stress; iBC.computeField(stress, tStep); printf("Mean stress computed in Gnuplot export module: "); stress.printYourself(); double time = 0.0; TimeStep *ts = emodel->giveCurrentStep(); if ( ts != NULL ) { time = ts->giveTargetTime(); } int bcIndex = iBC.giveNumber(); std :: stringstream strMeanStress; strMeanStress << "PrescribedGradientGnuplotMeanStress" << bcIndex << "Time" << time << ".dat"; std :: string nameMeanStress = strMeanStress.str(); std::vector<double> componentArray, stressArray; for(int i = 1; i <= stress.giveSize(); i++) { componentArray.push_back(i); stressArray.push_back(stress.at(i)); } XFEMDebugTools::WriteArrayToGnuplot(nameMeanStress, componentArray, stressArray); // Homogenized strain FloatArray grad; iBC.giveGradientVoigt(grad); outputGradient(iBC.giveNumber(), *iBC.giveDomain(), grad, tStep); #if 0 FloatArray grad; iBC.giveGradientVoigt(grad); double timeFactor = iBC.giveTimeFunction()->evaluate(ts, VM_Total); printf("timeFactor: %e\n", timeFactor ); grad.times(timeFactor); printf("Mean grad computed in Gnuplot export module: "); grad.printYourself(); std :: stringstream strMeanGrad; strMeanGrad << "PrescribedGradientGnuplotMeanGrad" << bcIndex << "Time" << time << ".dat"; std :: string nameMeanGrad = strMeanGrad.str(); std::vector<double> componentArrayGrad, gradArray; for(int i = 1; i <= grad.giveSize(); i++) { componentArrayGrad.push_back(i); gradArray.push_back(grad.at(i)); } XFEMDebugTools::WriteArrayToGnuplot(nameMeanGrad, componentArrayGrad, gradArray); #endif if(mExportBoundaryConditionsExtra) { // Traction node coordinates std::vector< std::vector<FloatArray> > nodePointArray; size_t numTracEl = iBC.giveNumberOfTractionElements(); for(size_t i = 0; i < numTracEl; i++) { std::vector<FloatArray> points; FloatArray xS, xE; iBC.giveTractionElCoord(i, xS, xE); points.push_back(xS); points.push_back(xE); nodePointArray.push_back(points); } std :: stringstream strTractionNodes; strTractionNodes << "TractionNodesGnuplotTime" << time << ".dat"; std :: string nameTractionNodes = strTractionNodes.str(); WritePointsToGnuplot(nameTractionNodes, nodePointArray); // Traction element normal direction std::vector< std::vector<FloatArray> > nodeNormalArray; for(size_t i = 0; i < numTracEl; i++) { std::vector<FloatArray> points; FloatArray n,t; iBC.giveTractionElNormal(i, n,t); points.push_back(n); points.push_back(n); nodeNormalArray.push_back(points); } std :: stringstream strTractionNodeNormals; strTractionNodeNormals << "TractionNodeNormalsGnuplotTime" << time << ".dat"; std :: string nameTractionNodeNormals = strTractionNodeNormals.str(); WritePointsToGnuplot(nameTractionNodeNormals, nodeNormalArray); // Traction (x,y) std::vector< std::vector<FloatArray> > nodeTractionArray; for(size_t i = 0; i < numTracEl; i++) { std::vector<FloatArray> tractions; FloatArray tS, tE; iBC.giveTraction(i, tS, tE, VM_Total, tStep); tractions.push_back(tS); tractions.push_back(tE); nodeTractionArray.push_back(tractions); } std :: stringstream strTractions; strTractions << "TractionsGnuplotTime" << time << ".dat"; std :: string nameTractions = strTractions.str(); WritePointsToGnuplot(nameTractions, nodeTractionArray); // Arc position along the boundary std::vector< std::vector<FloatArray> > arcPosArray; for(size_t i = 0; i < numTracEl; i++) { std::vector<FloatArray> arcPos; double xiS = 0.0, xiE = 0.0; iBC.giveTractionElArcPos(i, xiS, xiE); arcPos.push_back( FloatArray{xiS} ); arcPos.push_back( FloatArray{xiE} ); arcPosArray.push_back(arcPos); } std :: stringstream strArcPos; strArcPos << "ArcPosGnuplotTime" << time << ".dat"; std :: string nameArcPos = strArcPos.str(); WritePointsToGnuplot(nameArcPos, arcPosArray); // Traction (normal, tangent) std::vector< std::vector<FloatArray> > nodeTractionNTArray; for(size_t i = 0; i < numTracEl; i++) { std::vector<FloatArray> tractions; FloatArray tS, tE; iBC.giveTraction(i, tS, tE, VM_Total, tStep); FloatArray n,t; iBC.giveTractionElNormal(i, n, t); double tSn = tS.dotProduct(n,2); double tSt = tS.dotProduct(t,2); tractions.push_back( {tSn ,tSt} ); double tEn = tE.dotProduct(n,2); double tEt = tE.dotProduct(t,2); tractions.push_back( {tEn, tEt} ); nodeTractionNTArray.push_back(tractions); } std :: stringstream strTractionsNT; strTractionsNT << "TractionsNormalTangentGnuplotTime" << time << ".dat"; std :: string nameTractionsNT = strTractionsNT.str(); WritePointsToGnuplot(nameTractionsNT, nodeTractionNTArray); // Boundary points and displacements IntArray boundaries, bNodes; iBC.giveBoundaries(boundaries); std::vector< std::vector<FloatArray> > bndNodes; for ( int pos = 1; pos <= boundaries.giveSize() / 2; ++pos ) { Element *e = iBC.giveDomain()->giveElement( boundaries.at(pos * 2 - 1) ); int boundary = boundaries.at(pos * 2); e->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); std::vector<FloatArray> bndSegNodes; // Add the start and end nodes of the segment DofManager *startNode = e->giveDofManager( bNodes[0] ); FloatArray xS = *(startNode->giveCoordinates()); Dof *dSu = startNode->giveDofWithID(D_u); double dU = dSu->giveUnknown(VM_Total, tStep); xS.push_back(dU); Dof *dSv = startNode->giveDofWithID(D_v); double dV = dSv->giveUnknown(VM_Total, tStep); xS.push_back(dV); bndSegNodes.push_back(xS); DofManager *endNode = e->giveDofManager( bNodes[1] ); FloatArray xE = *(endNode->giveCoordinates()); Dof *dEu = endNode->giveDofWithID(D_u); dU = dEu->giveUnknown(VM_Total, tStep); xE.push_back(dU); Dof *dEv = endNode->giveDofWithID(D_v); dV = dEv->giveUnknown(VM_Total, tStep); xE.push_back(dV); bndSegNodes.push_back(xE); bndNodes.push_back(bndSegNodes); } std :: stringstream strBndNodes; strBndNodes << "BndNodesGnuplotTime" << time << ".dat"; std :: string nameBndNodes = strBndNodes.str(); WritePointsToGnuplot(nameBndNodes, bndNodes); } }
void NlDEIDynamic :: solveYourselfAt(TimeStep *tStep) { // // Creates system of governing eq's and solves them at given time step. // Domain *domain = this->giveDomain(1); int neq = this->giveNumberOfEquations(EID_MomentumBalance); int nman = domain->giveNumberOfDofManagers(); DofManager *node; Dof *iDof; int nDofs; int i, k, j, jj; double coeff, maxDt, maxOm = 0.; double prevIncrOfDisplacement, incrOfDisplacement; if ( initFlag ) { #ifdef VERBOSE OOFEM_LOG_DEBUG("Assembling mass matrix\n"); #endif // // Assemble mass matrix. // this->computeMassMtrx(massMatrix, maxOm, tStep); if ( drFlag ) { // If dynamic relaxation: Assemble amplitude load vector. loadRefVector.resize(neq); loadRefVector.zero(); this->computeLoadVector(loadRefVector, VM_Total, tStep); #ifdef __PARALLEL_MODE // Compute the processor part of load vector norm pMp this->pMp = 0.0; double my_pMp = 0.0, coeff = 1.0; int eqNum, ndofs, ndofman = domain->giveNumberOfDofManagers(); dofManagerParallelMode dofmanmode; DofManager *dman; Dof *jdof; for ( int dm = 1; dm <= ndofman; dm++ ) { dman = domain->giveDofManager(dm); ndofs = dman->giveNumberOfDofs(); dofmanmode = dman->giveParallelMode(); // Skip all remote and null dofmanagers coeff = 1.0; if ( ( dofmanmode == DofManager_remote ) || ( ( dofmanmode == DofManager_null ) ) ) { continue; } else if ( dofmanmode == DofManager_shared ) { coeff = 1. / dman->givePartitionsConnectivitySize(); } // For shared nodes we add locally an average = 1/givePartitionsConnectivitySize()*contribution, for ( j = 1; j <= ndofs; j++ ) { jdof = dman->giveDof(j); if ( jdof->isPrimaryDof() && ( eqNum = jdof->__giveEquationNumber() ) ) { my_pMp += coeff * loadRefVector.at(eqNum) * loadRefVector.at(eqNum) / massMatrix.at(eqNum); } } } // Sum up the contributions from processors. MPI_Allreduce(& my_pMp, & pMp, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); #else this->pMp = 0.0; for ( i = 1; i <= neq; i++ ) { pMp += loadRefVector.at(i) * loadRefVector.at(i) / massMatrix.at(i); } #endif // Solve for rate of loading process (parameter "c") (undamped system assumed), if ( dumpingCoef < 1.e-3 ) { c = 3.0 * this->pyEstimate / pMp / Tau / Tau; } else { c = this->pyEstimate * Tau * dumpingCoef * dumpingCoef * dumpingCoef / pMp / ( -3.0 / 2.0 + dumpingCoef * Tau + 2.0 * exp(-dumpingCoef * Tau) - 0.5 * exp(-2.0 * dumpingCoef * Tau) ); } } initFlag = 0; } if ( tStep->giveNumber() == giveNumberOfFirstStep() ) { // // Special init step - Compute displacements at tstep 0. // displacementVector.resize(neq); displacementVector.zero(); previousIncrementOfDisplacementVector.resize(neq); previousIncrementOfDisplacementVector.zero(); velocityVector.resize(neq); velocityVector.zero(); accelerationVector.resize(neq); accelerationVector.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) // all dofs are expected to be DisplacementVector type. iDof = node->giveDof(k); if ( !iDof->isPrimaryDof() ) { continue; } jj = iDof->__giveEquationNumber(); if ( jj ) { displacementVector.at(jj) = iDof->giveUnknown(EID_MomentumBalance, VM_Total, tStep); velocityVector.at(jj) = iDof->giveUnknown(EID_MomentumBalance, VM_Velocity, tStep); accelerationVector.at(jj) = iDof->giveUnknown(EID_MomentumBalance, VM_Acceleration, tStep) ; } } } // // Set-up numerical model. // // Try to determine the best deltaT, maxDt = 2.0 / sqrt(maxOm); if ( deltaT > maxDt ) { // Print reduced time step increment and minimum period Tmin OOFEM_LOG_RELEVANT("deltaT reduced to %e, Tmin is %e\n", maxDt, maxDt * M_PI); deltaT = maxDt; tStep->setTimeIncrement(deltaT); } for ( j = 1; j <= neq; j++ ) { previousIncrementOfDisplacementVector.at(j) = velocityVector.at(j) * ( deltaT ); displacementVector.at(j) -= previousIncrementOfDisplacementVector.at(j); } #ifdef VERBOSE OOFEM_LOG_RELEVANT( "\n\nSolving [Step number %8d, Time %15e]\n", tStep->giveNumber(), tStep->giveTargetTime() ); #endif return; } // end of init step #ifdef VERBOSE OOFEM_LOG_DEBUG("Assembling right hand side\n"); #endif for ( i = 1; i <= neq; i++ ) { displacementVector.at(i) += previousIncrementOfDisplacementVector.at(i); } // Update solution state counter tStep->incrementStateCounter(); // Compute internal forces. this->giveInternalForces( internalForces, false, 1, tStep ); if ( !drFlag ) { // // Assembling the element part of load vector. // this->computeLoadVector(loadVector, VM_Total, tStep); // // Assembling additional parts of right hand side. // for ( k = 1; k <= neq; k++ ) { loadVector.at(k) -= internalForces.at(k); } } else { // Dynamic relaxation // compute load factor pt = 0.0; #ifdef __PARALLEL_MODE double my_pt = 0.0, coeff = 1.0; int eqNum, ndofs, ndofman = domain->giveNumberOfDofManagers(); dofManagerParallelMode dofmanmode; DofManager *dman; Dof *jdof; for ( int dm = 1; dm <= ndofman; dm++ ) { dman = domain->giveDofManager(dm); ndofs = dman->giveNumberOfDofs(); dofmanmode = dman->giveParallelMode(); // skip all remote and null dofmanagers coeff = 1.0; if ( ( dofmanmode == DofManager_remote ) || ( dofmanmode == DofManager_null ) ) { continue; } else if ( dofmanmode == DofManager_shared ) { coeff = 1. / dman->givePartitionsConnectivitySize(); } // For shared nodes we add locally an average= 1/givePartitionsConnectivitySize()*contribution. for ( j = 1; j <= ndofs; j++ ) { jdof = dman->giveDof(j); if ( jdof->isPrimaryDof() && ( eqNum = jdof->__giveEquationNumber() ) ) { my_pt += coeff * internalForces.at(eqNum) * loadRefVector.at(eqNum) / massMatrix.at(eqNum); } } } // Sum up the contributions from processors. MPI_Allreduce(& my_pt, & pt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); #else for ( k = 1; k <= neq; k++ ) { pt += internalForces.at(k) * loadRefVector.at(k) / massMatrix.at(k); } #endif pt = pt / pMp; if ( dumpingCoef < 1.e-3 ) { pt += c * ( Tau - tStep->giveTargetTime() ) / Tau; } else { pt += c * ( 1.0 - exp( dumpingCoef * ( tStep->giveTargetTime() - Tau ) ) ) / dumpingCoef / Tau; } loadVector.resize( this->giveNumberOfEquations(EID_MomentumBalance) ); for ( k = 1; k <= neq; k++ ) { loadVector.at(k) = pt * loadRefVector.at(k) - internalForces.at(k); } // Compute relative error. double err = 0.0; #ifdef __PARALLEL_MODE double my_err = 0.0; for ( int dm = 1; dm <= ndofman; dm++ ) { dman = domain->giveDofManager(dm); ndofs = dman->giveNumberOfDofs(); dofmanmode = dman->giveParallelMode(); // Skip all remote and null dofmanagers. coeff = 1.0; if ( ( dofmanmode == DofManager_remote ) || ( dofmanmode == DofManager_null ) ) { continue; } else if ( dofmanmode == DofManager_shared ) { coeff = 1. / dman->givePartitionsConnectivitySize(); } // For shared nodes we add locally an average= 1/givePartitionsConnectivitySize()*contribution. for ( j = 1; j <= ndofs; j++ ) { jdof = dman->giveDof(j); if ( jdof->isPrimaryDof() && ( eqNum = jdof->__giveEquationNumber() ) ) { my_err += coeff * loadVector.at(eqNum) * loadVector.at(eqNum) / massMatrix.at(eqNum); } } } // Sum up the contributions from processors. MPI_Allreduce(& my_err, & err, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); #else for ( k = 1; k <= neq; k++ ) { err = loadVector.at(k) * loadVector.at(k) / massMatrix.at(k); } #endif err = err / ( pMp * pt * pt ); OOFEM_LOG_RELEVANT("Relative error is %e, loadlevel is %e\n", err, pt); } for ( j = 1; j <= neq; j++ ) { coeff = massMatrix.at(j); loadVector.at(j) += coeff * ( ( 1. / ( deltaT * deltaT ) ) - dumpingCoef * 1. / ( 2. * deltaT ) ) * previousIncrementOfDisplacementVector.at(j); } // // Set-up numerical model // /* it is not necesary to call numerical method * approach used here is not good, but effective enough * inverse of diagonal mass matrix is done here */ // // call numerical model to solve arised problem - done localy here // #ifdef VERBOSE OOFEM_LOG_RELEVANT( "\n\nSolving [Step number %8d, Time %15e]\n", tStep->giveNumber(), tStep->giveTargetTime() ); #endif for ( i = 1; i <= neq; i++ ) { prevIncrOfDisplacement = previousIncrementOfDisplacementVector.at(i); incrOfDisplacement = loadVector.at(i) / ( massMatrix.at(i) * ( 1. / ( deltaT * deltaT ) + dumpingCoef / ( 2. * deltaT ) ) ); accelerationVector.at(i) = ( incrOfDisplacement - prevIncrOfDisplacement ) / ( deltaT * deltaT ); velocityVector.at(i) = ( incrOfDisplacement + prevIncrOfDisplacement ) / ( 2. * deltaT ); previousIncrementOfDisplacementVector.at(i) = incrOfDisplacement; } }
void NonLinearDynamic :: proceedStep(int di, TimeStep *tStep) { // creates system of governing eq's and solves them at given time step // first assemble problem at current time step int neq = this->giveNumberOfEquations(EID_MomentumBalance); // Time-stepping constants double dt2 = deltaT * deltaT; if ( tStep->giveTimeDiscretization() == TD_Newmark ) { OOFEM_LOG_DEBUG("Solving using Newmark-beta method\n"); a0 = 1 / ( beta * dt2 ); a1 = gamma / ( beta * deltaT ); a2 = 1 / ( beta * deltaT ); a3 = 1 / ( 2 * beta ) - 1; a4 = ( gamma / beta ) - 1; a5 = deltaT / 2 * ( gamma / beta - 2 ); a6 = 0; } else if ( ( tStep->giveTimeDiscretization() == TD_TwoPointBackward ) || ( tStep->giveNumber() == giveNumberOfFirstStep() ) ) { if ( tStep->giveTimeDiscretization() != TD_ThreePointBackward ) { OOFEM_LOG_DEBUG("Solving using Backward Euler method\n"); } else { OOFEM_LOG_DEBUG("Solving initial step using Three-point Backward Euler method\n"); } a0 = 1 / dt2; a1 = 1 / deltaT; a2 = 1 / deltaT; a3 = 0; a4 = 0; a5 = 0; a6 = 0; } else if ( tStep->giveTimeDiscretization() == TD_ThreePointBackward ) { OOFEM_LOG_DEBUG("Solving using Three-point Backward Euler method\n"); a0 = 2 / dt2; a1 = 3 / ( 2 * deltaT ); a2 = 2 / deltaT; a3 = 0; a4 = 0; a5 = 0; a6 = 1 / ( 2 * deltaT ); } else { _error("NonLinearDynamic: Time-stepping scheme not found!\n") } if ( tStep->giveNumber() == giveNumberOfFirstStep() ) { // Initialization previousIncrementOfDisplacement.resize(neq); previousIncrementOfDisplacement.zero(); previousTotalDisplacement.resize(neq); previousTotalDisplacement.zero(); totalDisplacement.resize(neq); totalDisplacement.zero(); previousInternalForces.resize(neq); previousInternalForces.zero(); incrementOfDisplacement.resize(neq); incrementOfDisplacement.zero(); velocityVector.resize(neq); velocityVector.zero(); accelerationVector.resize(neq); accelerationVector.zero(); TimeStep *stepWhenIcApply = new TimeStep(giveNumberOfTimeStepWhenIcApply(), this, 0, -deltaT, deltaT, 0); int nDofs, j, k, jj; int nman = this->giveDomain(di)->giveNumberOfDofManagers(); DofManager *node; Dof *iDof; // Considering initial conditions. for ( j = 1; j <= nman; j++ ) { node = this->giveDomain(di)->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 ) { incrementOfDisplacement.at(jj) = iDof->giveUnknown(EID_MomentumBalance, VM_Total, stepWhenIcApply); velocityVector.at(jj) = iDof->giveUnknown(EID_MomentumBalance, VM_Velocity, stepWhenIcApply); accelerationVector.at(jj) = iDof->giveUnknown(EID_MomentumBalance, VM_Acceleration, stepWhenIcApply); } } } } else { incrementOfDisplacement.resize(neq); incrementOfDisplacement.zero(); } if ( initFlag ) { // First assemble problem at current time step. // Option to take into account initial conditions. if ( !stiffnessMatrix ) { stiffnessMatrix = CreateUsrDefSparseMtrx(sparseMtrxType); } if ( stiffnessMatrix == NULL ) { _error("proceedStep: sparse matrix creation failed"); } if ( nonlocalStiffnessFlag ) { if ( !stiffnessMatrix->isAsymmetric() ) { _error("proceedStep: stiffnessMatrix does not support asymmetric storage"); } } stiffnessMatrix->buildInternalStructure( this, di, EID_MomentumBalance, EModelDefaultEquationNumbering() ); // Initialize vectors help.resize(neq); rhs.resize(neq); rhs2.resize(neq); internalForces.resize(neq); help.zero(); rhs.zero(); rhs2.zero(); previousTotalDisplacement.resize(neq); for ( int i = 1; i <= neq; i++ ) { previousTotalDisplacement.at(i) = totalDisplacement.at(i); } initFlag = 0; } #ifdef VERBOSE OOFEM_LOG_DEBUG("Assembling load\n"); #endif // Assemble the incremental reference load vector. this->assembleIncrementalReferenceLoadVectors(incrementalLoadVector, incrementalLoadVectorOfPrescribed, refLoadInputMode, this->giveDomain(di), EID_MomentumBalance, tStep); // Assembling the effective load vector for ( int i = 1; i <= neq; i++ ) { help.at(i) = a2 * velocityVector.at(i) + a3 * accelerationVector.at(i) + eta * ( a4 * velocityVector.at(i) + a5 * accelerationVector.at(i) + a6 * previousIncrementOfDisplacement.at(i) ); } this->timesMtrx(help, rhs, MassMatrix, this->giveDomain(di), tStep); if ( delta != 0 ) { for ( int i = 1; i <= neq; i++ ) { help.at(i) = delta * ( a4 * velocityVector.at(i) + a5 * accelerationVector.at(i) + a6 * previousIncrementOfDisplacement.at(i) ); } this->timesMtrx(help, rhs2, StiffnessMatrix, this->giveDomain(di), tStep); help.zero(); for ( int i = 1; i <= neq; i++ ) { rhs.at(i) += rhs2.at(i); } } for ( int i = 1; i <= neq; i++ ) { rhs.at(i) += incrementalLoadVector.at(i) - previousInternalForces.at(i); totalDisplacement.at(i) = previousTotalDisplacement.at(i); } // // Set-up numerical model. // this->giveNumericalMethod( this->giveCurrentMetaStep() ); // // Call numerical model to solve problem. // double loadLevel = 1.0; if ( initialLoadVector.isNotEmpty() ) { numMetStatus = nMethod->solve(stiffnessMatrix, & rhs, & initialLoadVector, & totalDisplacement, & incrementOfDisplacement, & internalForces, internalForcesEBENorm, loadLevel, refLoadInputMode, currentIterations, tStep); } else { numMetStatus = nMethod->solve(stiffnessMatrix, & rhs, NULL, & totalDisplacement, & incrementOfDisplacement, & internalForces, internalForcesEBENorm, loadLevel, refLoadInputMode, currentIterations, tStep); } OOFEM_LOG_INFO("Equilibrium reached in %d iterations\n", currentIterations); }
void IncrementalLinearStatic :: solveYourselfAt(TimeStep *tStep) { // Creates system of governing eq's and solves them at given time step // Initiates the total displacement to zero. if ( tStep->isTheFirstStep() ) { Domain *d = this->giveDomain(1); for ( int i = 1; i <= d->giveNumberOfDofManagers(); i++ ) { DofManager *dofman = d->giveDofManager(i); for ( int j = 1; j <= dofman->giveNumberOfDofs(); j++ ) { dofman->giveDof(j)->updateUnknownsDictionary(tStep, VM_Total_Old, 0.); dofman->giveDof(j)->updateUnknownsDictionary(tStep, VM_Total, 0.); // This is actually redundant now; //dofman->giveDof(j)->updateUnknownsDictionary(tStep, VM_Incremental, 0.); } } int nbc = d->giveNumberOfBoundaryConditions(); for ( int ibc = 1; ibc <= nbc; ++ibc ) { GeneralBoundaryCondition *bc = d->giveBc(ibc); ActiveBoundaryCondition *abc; if ( ( abc = dynamic_cast< ActiveBoundaryCondition * >( bc ) ) ) { int ndman = abc->giveNumberOfInternalDofManagers(); for ( int i = 1; i <= ndman; i++ ) { DofManager *dofman = abc->giveInternalDofManager(i); for ( int j = 1; j <= dofman->giveNumberOfDofs(); j++ ) { dofman->giveDof(j)->updateUnknownsDictionary(tStep, VM_Total_Old, 0.); dofman->giveDof(j)->updateUnknownsDictionary(tStep, VM_Total, 0.); // This is actually redundant now; //dofman->giveDof(j)->updateUnknownsDictionary(tStep, VM_Incremental, 0.); } } } } } // Apply dirichlet b.c's on total values Domain *d = this->giveDomain(1); for ( int i = 1; i <= d->giveNumberOfDofManagers(); i++ ) { DofManager *dofman = d->giveDofManager(i); for ( int j = 1; j <= dofman->giveNumberOfDofs(); j++ ) { Dof *d = dofman->giveDof(j); double tot = d->giveUnknown(VM_Total_Old, tStep); if ( d->hasBc(tStep) ) { tot += d->giveBcValue(VM_Incremental, tStep); } d->updateUnknownsDictionary(tStep, VM_Total, tot); } } #ifdef VERBOSE OOFEM_LOG_RELEVANT( "Solving [step number %8d, time %15e]\n", tStep->giveNumber(), tStep->giveTargetTime() ); #endif int neq = this->giveNumberOfDomainEquations(1, EModelDefaultEquationNumbering()); if (neq == 0) { // Allows for fully prescribed/empty problems. return; } incrementOfDisplacementVector.resize(neq); incrementOfDisplacementVector.zero(); #ifdef VERBOSE OOFEM_LOG_INFO("Assembling load\n"); #endif // Assembling the element part of load vector internalLoadVector.resize(neq); internalLoadVector.zero(); this->assembleVector( internalLoadVector, tStep, EID_MomentumBalance, InternalForcesVector, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); loadVector.resize(neq); loadVector.zero(); this->assembleVector( loadVector, tStep, EID_MomentumBalance, ExternalForcesVector, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); loadVector.subtract(internalLoadVector); #ifdef VERBOSE OOFEM_LOG_INFO("Assembling stiffness matrix\n"); #endif if ( stiffnessMatrix ) { delete stiffnessMatrix; } stiffnessMatrix = classFactory.createSparseMtrx(sparseMtrxType); if ( stiffnessMatrix == NULL ) { _error("solveYourselfAt: sparse matrix creation failed"); } stiffnessMatrix->buildInternalStructure( this, 1, EID_MomentumBalance, EModelDefaultEquationNumbering() ); stiffnessMatrix->zero(); this->assemble( stiffnessMatrix, tStep, EID_MomentumBalance, StiffnessMatrix, EModelDefaultEquationNumbering(), this->giveDomain(1) ); #ifdef VERBOSE OOFEM_LOG_INFO("Solving ...\n"); #endif this->giveNumericalMethod( this->giveCurrentMetaStep() ); NM_Status s = nMethod->solve(stiffnessMatrix, & loadVector, & incrementOfDisplacementVector); if ( !(s & NM_Success) ) { OOFEM_ERROR("IncrementalLinearStatic :: solverYourselfAt - No success in solving system."); } }