TimeStep *NonLinearStatic :: giveNextStep() { int istep = giveNumberOfFirstStep(); int mStepNum = 1; double totalTime = 0.0; StateCounterType counter = 1; double deltaTtmp = deltaT; //do not increase deltaT on microproblem if ( pScale == microScale ) { deltaTtmp = 0.; } if ( currentStep ) { totalTime = currentStep->giveTargetTime() + deltaTtmp; istep = currentStep->giveNumber() + 1; counter = currentStep->giveSolutionStateCounter() + 1; mStepNum = currentStep->giveMetaStepNumber(); if ( !this->giveMetaStep(mStepNum)->isStepValid(istep) ) { mStepNum++; if ( mStepNum > nMetaSteps ) { OOFEM_ERROR("no next step available, mStepNum=%d > nMetaSteps=%d", mStepNum, nMetaSteps); } } } previousStep = std :: move(currentStep); currentStep.reset( new TimeStep(istep, this, mStepNum, totalTime, deltaTtmp, counter) ); // dt variable are set eq to 0 for statics - has no meaning // *Wrong* It has meaning for viscoelastic materials. return currentStep.get(); }
TimeStep *EigenValueDynamic :: giveNextStep() { int istep = giveNumberOfFirstStep(); StateCounterType counter = 1; delete previousStep; if ( currentStep != NULL ) { istep = currentStep->giveNumber() + 1; counter = currentStep->giveSolutionStateCounter() + 1; } previousStep = currentStep; currentStep = new TimeStep(istep, this, 1, ( double ) istep, 0., counter); // time and dt variables are set eq to 0 for statics - has no meaning return currentStep; }
TimeStep *DEIDynamic :: giveNextStep() { int istep = giveNumberOfFirstStep(); double totalTime = 0.; StateCounterType counter = 1; delete previousStep; if ( currentStep != NULL ) { totalTime = currentStep->giveTargetTime() + deltaT; istep = currentStep->giveNumber() + 1; counter = currentStep->giveSolutionStateCounter() + 1; } previousStep = currentStep; currentStep = new TimeStep(istep, this, 1, totalTime, deltaT, counter); // time and dt variables are set eq to 0 for staics - has no meaning return currentStep; }
TimeStep *LinearStability :: giveNextStep() { int istep = giveNumberOfFirstStep(); StateCounterType counter = 1; if (previousStep != NULL){ delete previousStep; } if ( currentStep != NULL ) { istep = currentStep->giveNumber() + 1; counter = currentStep->giveSolutionStateCounter() + 1; } previousStep = currentStep; currentStep = new TimeStep(istep, this, 1, 0., 0., counter); // time and dt variables are set eq to 0 for staics - has no meaning return currentStep; }
TimeStep * NonStationaryTransportProblem :: giveSolutionStepWhenIcApply() { if ( stepWhenIcApply == NULL ) { stepWhenIcApply = new TimeStep(giveNumberOfTimeStepWhenIcApply(), this, 0, this->initT-giveDeltaT(giveNumberOfFirstStep()), giveDeltaT(giveNumberOfFirstStep()), 0); //stepWhenIcApply = new TimeStep(giveNumberOfTimeStepWhenIcApply(), this, 0, -deltaT, deltaT, 0); } return stepWhenIcApply; }
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); }
TimeStep * NonStationaryTransportProblem :: giveSolutionStepWhenIcApply(bool force) { if ( master && (!force)) { return master->giveSolutionStepWhenIcApply(); } else { if ( !stepWhenIcApply ) { stepWhenIcApply.reset( new TimeStep(giveNumberOfTimeStepWhenIcApply(), this, 0, this->initT - giveDeltaT ( giveNumberOfFirstStep() ), giveDeltaT ( giveNumberOfFirstStep() ), 0) ); //stepWhenIcApply.reset( new TimeStep(giveNumberOfTimeStepWhenIcApply(), this, 0, -deltaT, deltaT, 0) ); } return stepWhenIcApply.get(); } }
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; } }