void LoadBalancer :: printStatistics() const { EngngModel *emodel = domain->giveEngngModel(); int nelem, nnode; int lelem = 0, lnode = 0; int myrank = emodel->giveRank(); int i; nelem = domain->giveNumberOfElements(); nnode = domain->giveNumberOfDofManagers(); for ( i = 1; i <= nnode; i++ ) { if ( domain->giveDofManager(i)->giveParallelMode() == DofManager_local ) { lnode++; } } for ( i = 1; i <= nelem; i++ ) { if ( domain->giveElement(i)->giveParallelMode() == Element_local ) { lelem++; } } double mySolutionWTime = emodel->giveTimer()->getWtime(EngngModelTimer :: EMTT_AnalysisTimer); double mySolutionUTime = emodel->giveTimer()->getUtime(EngngModelTimer :: EMTT_AnalysisTimer); OOFEM_LOG_RELEVANT("[%d] LB Statistics: wt=%.1f ut=%.1f nelem=%d nnode=%d\n", myrank, mySolutionWTime, mySolutionUTime, lelem, lnode); }
double RCSDMaterial :: computeStrength(GaussPoint *gp, double charLength) // // computes strength for given gp, // which may be reduced according to length of "fracture process zone" // to be energetically correct // { double Ee, Gf, Ft; Ee = this->give(pscm_Ee, gp); Gf = this->give(pscm_Gf, gp); Ft = this->give(pscm_Ft, gp); if ( !this->checkSizeLimit(gp, charLength) ) { // we reduce Ft and there is no softening but sudden drop Ft = sqrt(2. * Ee * Gf / charLength); // OOFEM_LOG_RELEVANT("Reducing Ft to %f in element %d, gp %d, Le %f\n", Ft, gp->giveElement()->giveNumber(), gp->giveNumber(), charLength); } return Ft; }
void NLTransientTransportProblem :: solveYourselfAt(TimeStep *tStep) { // creates system of governing eq's and solves them at given time step // first assemble problem at current time step // Right hand side FloatArray rhs; double solutionErr, incrementErr; int neq = this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); #ifdef VERBOSE OOFEM_LOG_RELEVANT( "Solving [step number %8d, time %15e]\n", tStep->giveNumber(), tStep->giveTargetTime() ); #endif //Delete lhs matrix and create a new one. This is necessary due to growing/decreasing number of equations. if ( tStep->isTheFirstStep() || this->changingProblemSize ) { if ( conductivityMatrix ) { delete conductivityMatrix; } conductivityMatrix = classFactory.createSparseMtrx(sparseMtrxType); if ( conductivityMatrix == NULL ) { OOFEM_ERROR("sparse matrix creation failed"); } conductivityMatrix->buildInternalStructure( this, 1, EModelDefaultEquationNumbering() ); #ifdef VERBOSE OOFEM_LOG_INFO("Assembling conductivity and capacity matrices\n"); #endif } //create previous solution from IC or from previous tStep if ( tStep->isTheFirstStep() ) { if ( !stepWhenIcApply ) { stepWhenIcApply.reset( new TimeStep( *tStep->givePreviousStep() ) ); } this->applyIC(stepWhenIcApply.get()); //insert solution to hash=1(previous), if changes in equation numbering } double dTTau = tStep->giveTimeIncrement(); double Tau = tStep->giveTargetTime() - ( 1. - alpha ) * tStep->giveTimeIncrement(); //Time step in which material laws are taken into account TimeStep TauStep(tStep->giveNumber(), this, tStep->giveMetaStepNumber(), Tau, dTTau, tStep->giveSolutionStateCounter() + 1); //Predictor FloatArray *solutionVector; UnknownsField->advanceSolution(tStep); solutionVector = UnknownsField->giveSolutionVector(tStep); //Initialize and give solutionVector from previous solution if ( changingProblemSize ) { if ( !tStep->isTheFirstStep() ) { //copy recent solution to previous position, copy from hash=0 to hash=1(previous) copyUnknownsInDictionary( VM_Total, tStep, tStep->givePreviousStep() ); } UnknownsField->initialize( VM_Total, tStep->givePreviousStep(), *solutionVector, EModelDefaultEquationNumbering() ); } else { //copy previous solution vector to actual *solutionVector = *UnknownsField->giveSolutionVector( tStep->givePreviousStep() ); } this->updateInternalState(& TauStep); //insert to hash=0(current), if changes in equation numbering FloatArray solutionVectorIncrement(neq); int nite = 0; OOFEM_LOG_INFO("Time Iter ResidNorm IncrNorm\n__________________________________________________________\n"); do { nite++; // Corrector #ifdef VERBOSE // printf("\nAssembling conductivity and capacity matrices"); #endif if ( ( nite == 1 ) || ( NR_Mode == nrsolverFullNRM ) || ( ( NR_Mode == nrsolverAccelNRM ) && ( nite % MANRMSteps == 0 ) ) ) { conductivityMatrix->zero(); //Assembling left hand side - start with conductivity matrix this->assemble( *conductivityMatrix, & TauStep, IntSourceLHSMatrix, EModelDefaultEquationNumbering(), this->giveDomain(1) ); conductivityMatrix->times(alpha); //Add capacity matrix this->assemble( *conductivityMatrix, & TauStep, NSTP_MidpointLhs, EModelDefaultEquationNumbering(), this->giveDomain(1) ); } rhs.resize(neq); rhs.zero(); //edge or surface load on element this->assembleVectorFromElements( rhs, & TauStep, ElementBCTransportVector, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); //add internal source vector on elements this->assembleVectorFromElements( rhs, & TauStep, ElementInternalSourceVector, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); //add nodal load this->assembleVectorFromDofManagers( rhs, & TauStep, ExternalForcesVector, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); // subtract the rhs part depending on previous solution assembleAlgorithmicPartOfRhs(rhs, EModelDefaultEquationNumbering(), & TauStep); // set-up numerical model this->giveNumericalMethod( this->giveCurrentMetaStep() ); // call numerical model to solve arised problem #ifdef VERBOSE //OOFEM_LOG_INFO("Solving ...\n"); #endif // compute norm of residuals from balance equations solutionErr = rhs.computeNorm(); linSolver->solve(*conductivityMatrix, rhs, solutionVectorIncrement); solutionVector->add(solutionVectorIncrement); this->updateInternalState(& TauStep); //insert to hash=0(current), if changes in equation numbering // compute error in the solutionvector increment incrementErr = solutionVectorIncrement.computeNorm(); // update solution state counter TauStep.incrementStateCounter(); tStep->incrementStateCounter(); OOFEM_LOG_INFO("%-15e %-10d %-15e %-15e\n", tStep->giveTargetTime(), nite, solutionErr, incrementErr); if ( nite >= nsmax ) { OOFEM_ERROR("convergence not reached after %d iterations", nsmax); } } while ( ( fabs(solutionErr) > rtol ) || ( fabs(incrementErr) > rtol ) ); }
int ZZErrorEstimator :: estimateError(EE_ErrorMode mode, TimeStep *tStep) { int nelems = this->domain->giveNumberOfElements(); ZZErrorEstimatorInterface *interface; double sNorm; InternalStateType type = IStype; if ( mode == temporaryEM ) { type = IST_StressTensorTemp; // OOFEM_ERROR("temporaryEM mode not supported"); } if ( this->stateCounter == tStep->giveSolutionStateCounter() ) { return 1; } NodalRecoveryModel *oldSmoother, *rm = NULL; if ( this->nodalRecoveryType == ZZRecovery ) { rm = new ZZNodalRecoveryModel(this->domain); } else if ( this->nodalRecoveryType == SPRRecovery ) { rm = new SPRNodalRecoveryModel(this->domain); } else { OOFEM_ERROR("unknown nodal recovery type"); } // first set the domain Smoother to suitable one, keep old one to be recovered oldSmoother = this->domain->giveSmoother(); this->domain->setSmoother(rm, 0); // do not delete old one // create a new set containing all elements Set elemSet(0, this->domain); elemSet.addAllElements(); // recover nodal values on entire elemSet (domain) rm->recoverValues(elemSet, type, tStep); #ifdef ZZErrorEstimator_ElementResultCashed this->eNorms.resize(nelems); #ifdef EXPERIMENT sNorms.resize(nelems); #endif #else double eNorm; #endif this->globalENorm = this->globalSNorm = 0.0; // loop over domain's elements for ( int ielem = 1; ielem <= nelems; ielem++ ) { if ( this->skipRegion( this->domain->giveElement(ielem)->giveRegionNumber() ) ) { continue; } interface = static_cast< ZZErrorEstimatorInterface * >( this->domain->giveElement(ielem)->giveInterface(ZZErrorEstimatorInterfaceType) ); if ( interface == NULL ) { OOFEM_ERROR("Element has no ZZ error estimator interface defined"); } #ifdef ZZErrorEstimator_ElementResultCashed interface->ZZErrorEstimatorI_computeElementContributions(eNorms.at(ielem), sNorm, this->normType, type, tStep); this->globalENorm += eNorms.at(ielem) * eNorms.at(ielem); #ifdef EXPERIMENT sNorms.at(ielem) = sNorm; #endif #else interface->ZZErrorEstimatorI_computeElementContributions(eNorm, sNorm, this->normType, type, tStep); this->globalENorm += eNorm * eNorm; #endif this->globalSNorm += sNorm * sNorm; } FloatArray gnorms; ParallelContext *parallel_context = this->domain->giveEngngModel()->giveParallelContext(this->domain->giveNumber()); parallel_context->accumulate({this->globalENorm, this->globalSNorm}, gnorms); this->globalENorm = gnorms [ 0 ]; this->globalSNorm = gnorms [ 1 ]; // recover the stored smoother this->domain->setSmoother(oldSmoother); //delete old one (the rm) // report the error estimate double pe = sqrt( this->globalENorm / ( this->globalENorm + this->globalSNorm ) ); OOFEM_LOG_RELEVANT("Relative stress error estimate: %5.2f%%\n", pe * 100.0); this->globalENorm = sqrt(this->globalENorm); this->globalSNorm = sqrt(this->globalSNorm); this->globalErrorEstimate = pe; this->stateCounter = tStep->giveSolutionStateCounter(); return 1; }
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->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); int nman = domain->giveNumberOfDofManagers(); DofManager *node; 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, ndofman = domain->giveNumberOfDofManagers(); dofManagerParallelMode dofmanmode; DofManager *dman; for ( int dm = 1; dm <= ndofman; dm++ ) { dman = domain->giveDofManager(dm); 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 ( Dof *dof: *dman ) { if ( dof->isPrimaryDof() && ( eqNum = dof->__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->isTheFirstStep() ) { // // 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); for ( Dof *dof: *node ) { // Ask for initial values obtained from // bc (boundary conditions) and ic (initial conditions) // all dofs are expected to be DisplacementVector type. if ( !dof->isPrimaryDof() ) { continue; } jj = dof->__giveEquationNumber(); if ( jj ) { displacementVector.at(jj) = dof->giveUnknown(VM_Total, tStep); velocityVector.at(jj) = dof->giveUnknown(VM_Velocity, tStep); accelerationVector.at(jj) = dof->giveUnknown(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 displacementVector.add(previousIncrementOfDisplacementVector); // 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. // loadVector.subtract(internalForces); } else { // Dynamic relaxation // compute load factor pt = 0.0; #ifdef __PARALLEL_MODE double my_pt = 0.0, coeff = 1.0; int eqNum, ndofman = domain->giveNumberOfDofManagers(); dofManagerParallelMode dofmanmode; DofManager *dman; for ( int dm = 1; dm <= ndofman; dm++ ) { dman = domain->giveDofManager(dm); 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 ( Dof *dof: *dman ) { if ( dof->isPrimaryDof() && ( eqNum = dof->__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->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ) ); 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); 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 ( Dof *dof: *dman ) { if ( dof->isPrimaryDof() && ( eqNum = dof->__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 // NM_Status s = nMethod->solve(*massMatrix, loadVector, displacementVector); // if ( !(s & NM_Success) ) { // OOFEM_ERROR("No success in solving system. Ma=f"); // } 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 IncrementalLinearStatic :: solveYourselfAt(TimeStep *tStep) { Domain *d = this->giveDomain(1); // Creates system of governing eq's and solves them at given time step // >>> beginning PH // The following piece of code updates assignment of boundary conditions to dofs // (this allows to have multiple boundary conditions assigned to one dof // which can be arbitrarily turned on and off in time) // Almost the entire section has been copied from domain.C std :: vector< std :: map< int, int > > dof_bc( d->giveNumberOfDofManagers() ); for ( int i = 1; i <= d->giveNumberOfBoundaryConditions(); ++i ) { GeneralBoundaryCondition *gbc = d->giveBc(i); if ( gbc->isImposed(tStep) ) { if ( gbc->giveSetNumber() > 0 ) { ///@todo This will eventually not be optional. // Loop over nodes in set and store the bc number in each dof. Set *set = d->giveSet( gbc->giveSetNumber() ); ActiveBoundaryCondition *active_bc = dynamic_cast< ActiveBoundaryCondition * >(gbc); BoundaryCondition *bc = dynamic_cast< BoundaryCondition * >(gbc); if ( bc || ( active_bc && active_bc->requiresActiveDofs() ) ) { const IntArray &appliedDofs = gbc->giveDofIDs(); const IntArray &nodes = set->giveNodeList(); for ( int inode = 1; inode <= nodes.giveSize(); ++inode ) { for ( int idof = 1; idof <= appliedDofs.giveSize(); ++idof ) { if ( dof_bc [ nodes.at(inode) - 1 ].find( appliedDofs.at(idof) ) == dof_bc [ nodes.at(inode) - 1 ].end() ) { // is empty dof_bc [ nodes.at(inode) - 1 ] [ appliedDofs.at(idof) ] = i; DofManager * dofman = d->giveDofManager( nodes.at(inode) ); Dof * dof = dofman->giveDofWithID( appliedDofs.at(idof) ); dof->setBcId(i); } else { // another bc has been already prescribed at this time step to this dof OOFEM_WARNING("More than one boundary condition assigned at time %f to node %d dof %d. Considering boundary condition %d", tStep->giveTargetTime(), nodes.at(inode), appliedDofs.at(idof), dof_bc [ nodes.at(inode) - 1 ] [appliedDofs.at(idof)] ); } } } } } } } // to get proper number of equations this->forceEquationNumbering(); // <<< end PH // Initiates the total displacement to zero. if ( tStep->isTheFirstStep() ) { for ( auto &dofman : d->giveDofManagers() ) { for ( Dof *dof: *dofman ) { dof->updateUnknownsDictionary(tStep->givePreviousStep(), VM_Total, 0.); dof->updateUnknownsDictionary(tStep, VM_Total, 0.); } } for ( auto &bc : d->giveBcs() ) { ActiveBoundaryCondition *abc; if ( ( abc = dynamic_cast< ActiveBoundaryCondition * >(bc.get()) ) ) { int ndman = abc->giveNumberOfInternalDofManagers(); for ( int i = 1; i <= ndman; i++ ) { DofManager *dofman = abc->giveInternalDofManager(i); for ( Dof *dof: *dofman ) { dof->updateUnknownsDictionary(tStep->givePreviousStep(), VM_Total, 0.); dof->updateUnknownsDictionary(tStep, VM_Total, 0.); } } } } } // Apply dirichlet b.c's on total values for ( auto &dofman : d->giveDofManagers() ) { for ( Dof *dof: *dofman ) { double tot = dof->giveUnknown( VM_Total, tStep->givePreviousStep() ); if ( dof->hasBc(tStep) ) { tot += dof->giveBcValue(VM_Incremental, tStep); } dof->updateUnknownsDictionary(tStep, VM_Total, tot); } } int neq = this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); #ifdef VERBOSE OOFEM_LOG_RELEVANT("Solving [step number %8d, time %15e, equations %d]\n", tStep->giveNumber(), tStep->giveTargetTime(), neq); #endif 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, InternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); loadVector.resize(neq); loadVector.zero(); this->assembleVector( loadVector, tStep, ExternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); loadVector.subtract(internalLoadVector); this->updateSharedDofManagers(loadVector, EModelDefaultEquationNumbering(), ReactionExchangeTag); #ifdef VERBOSE OOFEM_LOG_INFO("Assembling stiffness matrix\n"); #endif stiffnessMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); if ( !stiffnessMatrix ) { OOFEM_ERROR("sparse matrix creation failed"); } stiffnessMatrix->buildInternalStructure( this, 1, EModelDefaultEquationNumbering() ); stiffnessMatrix->zero(); this->assemble( *stiffnessMatrix, tStep, TangentAssembler(TangentStiffness), 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("No success in solving system."); } }
int NodalAveragingRecoveryModel :: recoverValues(Set elementSet, InternalStateType type, TimeStep *tStep) { int nnodes = domain->giveNumberOfDofManagers(); IntArray regionNodalNumbers(nnodes); IntArray regionDofMansConnectivity; FloatArray lhs, val; if ( ( this->valType == type ) && ( this->stateCounter == tStep->giveSolutionStateCounter() ) ) { return 1; } #ifdef __PARALLEL_MODE bool parallel = this->domain->giveEngngModel()->isParallel(); if ( parallel ) { this->initCommMaps(); } #endif // clear nodal table this->clear(); int regionValSize = 0; int regionDofMans; // loop over elements and determine local region node numbering and determine and check nodal values size if ( this->initRegionNodeNumbering(regionNodalNumbers, regionDofMans, elementSet) == 0 ) { return 0; } regionDofMansConnectivity.resize(regionDofMans); regionDofMansConnectivity.zero(); IntArray elements = elementSet.giveElementList(); // assemble element contributions for ( int i = 1; i <= elements.giveSize(); i++ ) { int ielem = elements.at(i); NodalAveragingRecoveryModelInterface *interface; Element *element = domain->giveElement(ielem); if ( element->giveParallelMode() != Element_local ) { continue; } // If an element doesn't implement the interface, it is ignored. if ( ( interface = static_cast< NodalAveragingRecoveryModelInterface * > ( element->giveInterface(NodalAveragingRecoveryModelInterfaceType) ) ) == NULL ) { //abort(); continue; } int elemNodes = element->giveNumberOfDofManagers(); // ask element contributions for ( int elementNode = 1; elementNode <= elemNodes; elementNode++ ) { int node = element->giveDofManager(elementNode)->giveNumber(); interface->NodalAveragingRecoveryMI_computeNodalValue(val, elementNode, type, tStep); // if the element cannot evaluate this variable, it is ignored if ( val.giveSize() == 0 ) { continue; } else if ( regionValSize == 0 ) { regionValSize = val.giveSize(); lhs.resize(regionDofMans * regionValSize); lhs.zero(); } else if ( val.giveSize() != regionValSize ) { OOFEM_LOG_RELEVANT("NodalAveragingRecoveryModel :: size mismatch for InternalStateType %s, ignoring all elements that doesn't use the size %d\n", __InternalStateTypeToString(type), regionValSize); continue; } int eq = ( regionNodalNumbers.at(node) - 1 ) * regionValSize; for ( int j = 1; j <= regionValSize; j++ ) { lhs.at(eq + j) += val.at(j); } regionDofMansConnectivity.at( regionNodalNumbers.at(node) )++; } } // end assemble element contributions #ifdef __PARALLEL_MODE if ( parallel ) { this->exchangeDofManValues(lhs, regionDofMansConnectivity, regionNodalNumbers, regionValSize); } #endif // solve for recovered values of active region for ( int inode = 1; inode <= nnodes; inode++ ) { if ( regionNodalNumbers.at(inode) ) { int eq = ( regionNodalNumbers.at(inode) - 1 ) * regionValSize; for ( int i = 1; i <= regionValSize; i++ ) { if ( regionDofMansConnectivity.at( regionNodalNumbers.at(inode) ) > 0 ) { lhs.at(eq + i) /= regionDofMansConnectivity.at( regionNodalNumbers.at(inode) ); } else { OOFEM_WARNING("values of dofmanager %d undetermined", inode); lhs.at(eq + i) = 0.0; } } } } // update recovered values this->updateRegionRecoveredValues(regionNodalNumbers, regionValSize, lhs); this->valType = type; this->stateCounter = tStep->giveSolutionStateCounter(); return 1; }
int AdaptiveNonLinearStatic :: adaptiveRemap(Domain *dNew) { int ielem, nelem, result = 1; this->initStepIncrements(); this->ndomains = 2; this->domainNeqs.resize(2); this->domainPrescribedNeqs.resize(2); this->domainNeqs.at(2) = 0; this->domainPrescribedNeqs.at(2) = 0; this->domainList->put(2, dNew); #ifdef __PARALLEL_MODE ParallelContext *pcNew = new ParallelContext(this); this->parallelContextList->put(2, pcNew); #endif // init equation numbering //this->forceEquationNumbering(2); this->forceEquationNumbering(); // measure time consumed by mapping Timer timer; double mc1, mc2, mc3; timer.startTimer(); // map primary unknowns EIPrimaryUnknownMapper mapper; d2_totalDisplacement.resize( this->giveNumberOfDomainEquations( 2, EModelDefaultEquationNumbering() ) ); d2_incrementOfDisplacement.resize( this->giveNumberOfDomainEquations( 2, EModelDefaultEquationNumbering() ) ); d2_totalDisplacement.zero(); d2_incrementOfDisplacement.zero(); result &= mapper.mapAndUpdate( d2_totalDisplacement, VM_Total, this->giveDomain(1), this->giveDomain(2), this->giveCurrentStep() ); result &= mapper.mapAndUpdate( d2_incrementOfDisplacement, VM_Incremental, this->giveDomain(1), this->giveDomain(2), this->giveCurrentStep() ); timer.stopTimer(); mc1 = timer.getUtime(); timer.startTimer(); // map internal ip state nelem = this->giveDomain(2)->giveNumberOfElements(); for ( ielem = 1; ielem <= nelem; ielem++ ) { /* HUHU CHEATING */ #ifdef __PARALLEL_MODE if ( this->giveDomain(2)->giveElement(ielem)->giveParallelMode() == Element_remote ) { continue; } #endif result &= this->giveDomain(2)->giveElement(ielem)->adaptiveMap( this->giveDomain(1), this->giveCurrentStep() ); } /* replace domains */ OOFEM_LOG_DEBUG("deleting old domain\n"); //delete domainList->at(1); //domainList->put(1, dNew); //dNew->setNumber(1); //domainList->put(2, NULL); domainList->put( 1, domainList->unlink(2) ); domainList->at(1)->setNumber(1); #ifdef __PARALLEL_MODE parallelContextList->put( 1, parallelContextList->unlink(2) ); parallelContextList->growTo(1); #endif // keep equation numbering of new domain this->numberOfEquations = this->domainNeqs.at(1) = this->domainNeqs.at(2); this->numberOfPrescribedEquations = this->domainPrescribedNeqs.at(1) = this->domainPrescribedNeqs.at(2); this->equationNumberingCompleted = 1; // update solution totalDisplacement = d2_totalDisplacement; incrementOfDisplacement = d2_incrementOfDisplacement; this->ndomains = 1; // init equation numbering // this->forceEquationNumbering(); this->updateDomainLinks(); #ifdef __PARALLEL_MODE if ( isParallel() ) { // set up communication patterns this->initializeCommMaps(true); this->exchangeRemoteElementData(RemoteElementExchangeTag); } #endif timer.stopTimer(); mc2 = timer.getUtime(); timer.startTimer(); // computes the stresses and calls updateYourself to mapped state for ( ielem = 1; ielem <= nelem; ielem++ ) { /* HUHU CHEATING */ #ifdef __PARALLEL_MODE if ( this->giveDomain(1)->giveElement(ielem)->giveParallelMode() == Element_remote ) { continue; } #endif result &= this->giveDomain(1)->giveElement(ielem)->adaptiveUpdate( this->giveCurrentStep() ); } // finish mapping process for ( ielem = 1; ielem <= nelem; ielem++ ) { /* HUHU CHEATING */ #ifdef __PARALLEL_MODE if ( this->giveDomain(1)->giveElement(ielem)->giveParallelMode() == Element_remote ) { continue; } #endif result &= this->giveDomain(1)->giveElement(ielem)->adaptiveFinish( this->giveCurrentStep() ); } nMethod->reinitialize(); // increment time step if mapped state will be considered as new solution stepL // this->giveNextStep(); if ( equilibrateMappedConfigurationFlag ) { // we need to assemble the load vector in same time as the restarted step, // so new time step is generated with same intrincic time as has the // previous step if equilibrateMappedConfigurationFlag is set. // this allows to equlibrate the previously reached state TimeStep *cts = this->giveCurrentStep(); // increment version of solution step cts->incrementVersion(); //cts->setTime(cts->giveTime()-cts->giveTimeIncrement()); //cts = this->givePreviousStep(); //cts->setTime(cts->giveTime()-cts->giveTimeIncrement()); } if ( this->giveCurrentStep()->giveNumber() == this->giveCurrentMetaStep()->giveFirstStepNumber() ) { this->updateAttributes( this->giveCurrentMetaStep() ); } // increment solution state counter - not needed, IPs are updated by adaptiveUpdate previously called // and there is no change in primary vars. // this->giveCurrentStep()->incrementStateCounter(); // assemble new initial load for new discretization this->assembleInitialLoadVector( initialLoadVector, initialLoadVectorOfPrescribed, this, 1, this->giveCurrentStep() ); this->assembleIncrementalReferenceLoadVectors( incrementalLoadVector, incrementalLoadVectorOfPrescribed, refLoadInputMode, this->giveDomain(1), EID_MomentumBalance, this->giveCurrentStep() ); // assemble new total load for new discretization // this->assembleCurrentTotalLoadVector (totalLoadVector, totalLoadVectorOfPrescribed, this->giveCurrentStep()); // set bcloadVector to zero (no increment within same step) timer.stopTimer(); mc3 = timer.getUtime(); // compute processor time used by the program OOFEM_LOG_INFO("user time consumed by primary mapping: %.2fs\n", mc1); OOFEM_LOG_INFO("user time consumed by ip mapping: %.2fs\n", mc2); OOFEM_LOG_INFO("user time consumed by ip update: %.2fs\n", mc3); OOFEM_LOG_INFO("user time consumed by mapping: %.2fs\n", mc1 + mc2 + mc3); // /******** * #if 0 * { * * // evaluate the force error of mapped configuration * this->updateComponent (this->giveCurrentStep(), InternalRhs); * FloatArray rhs; * * loadVector.resize (this->numberOfEquations); * loadVector.zero(); * this->assemble (loadVector, this->giveCurrentStep(), ExternalForcesVector_Total, this->giveDomain(1)) ; * this->assemble (loadVector, this->giveCurrentStep(), ExternalForcesVector_Total, this->giveDomain(1)); * * rhs = loadVector; * rhs.times(loadLevel); * if (initialLoadVector.isNotEmpty()) rhs.add(initialLoadVector); * rhs.subtract(internalForces); * * // * // compute forceError * // * // err is relative error of unbalanced forces * double RR, RR0, forceErr = dotProduct (rhs.givePointer(),rhs.givePointer(),rhs.giveSize()); * if (initialLoadVector.isNotEmpty()) * RR0 = dotProduct (initialLoadVector.givePointer(), initialLoadVector.givePointer(), initialLoadVector.giveSize()); * else * RR0 = 0.0; * RR = dotProduct(loadVector.givePointer(),loadVector.givePointer(),loadVector.giveSize()); * // we compute a relative error norm * if ((RR0 + RR * loadLevel * loadLevel) < calm_SMALL_NUM) forceErr = 0.; * else forceErr = sqrt (forceErr / (RR0+RR * loadLevel * loadLevel)); * * printf ("Relative Force Error of Mapped Configuration is %-15e\n", forceErr); * * } **#endif *************/ #ifdef __OOFEG ESIEventLoop( YES, const_cast< char * >("AdaptiveRemap: Press Ctrl-p to continue") ); #endif // // bring mapped configuration into equilibrium // if ( equilibrateMappedConfigurationFlag ) { // use secant stiffness to resrore equilibrium NonLinearStatic_stiffnessMode oldStiffMode = this->stiffMode; stiffMode = nls_secantStiffness; if ( initFlag ) { if ( !stiffnessMatrix ) { stiffnessMatrix = classFactory.createSparseMtrx(sparseMtrxType); if ( stiffnessMatrix == NULL ) { OOFEM_ERROR("sparse matrix creation failed"); } } if ( nonlocalStiffnessFlag ) { if ( !stiffnessMatrix->isAsymmetric() ) { OOFEM_ERROR("stiffnessMatrix does not support asymmetric storage"); } } stiffnessMatrix->buildInternalStructure( this, 1, EID_MomentumBalance, EModelDefaultEquationNumbering() ); stiffnessMatrix->zero(); // zero stiffness matrix this->assemble( stiffnessMatrix, this->giveCurrentStep(), EID_MomentumBalance, SecantStiffnessMatrix, EModelDefaultEquationNumbering(), this->giveDomain(1) ); initFlag = 0; } // updateYourself() not necessary - the adaptiveUpdate previously called does the job //this->updateYourself(this->giveCurrentStep()); #ifdef VERBOSE OOFEM_LOG_INFO( "Equilibrating mapped configuration [step number %5d.%d]\n", this->giveCurrentStep()->giveNumber(), this->giveCurrentStep()->giveVersion() ); #endif //double deltaL = nMethod->giveUnknownComponent (StepLength, 0); double deltaL = nMethod->giveCurrentStepLength(); // // call numerical model to solve arised problem // #ifdef VERBOSE OOFEM_LOG_RELEVANT( "Solving [step number %5d.%d]\n", this->giveCurrentStep()->giveNumber(), this->giveCurrentStep()->giveVersion() ); #endif //nMethod -> solveYourselfAt(this->giveCurrentStep()) ; nMethod->setStepLength(deltaL / 5.0); if ( initialLoadVector.isNotEmpty() ) { numMetStatus = nMethod->solve( stiffnessMatrix, & incrementalLoadVector, & initialLoadVector, & totalDisplacement, & incrementOfDisplacement, & internalForces, internalForcesEBENorm, loadLevel, refLoadInputMode, currentIterations, this->giveCurrentStep() ); } else { numMetStatus = nMethod->solve( stiffnessMatrix, & incrementalLoadVector, NULL, & totalDisplacement, & incrementOfDisplacement, & internalForces, internalForcesEBENorm, loadLevel, refLoadInputMode, currentIterations, this->giveCurrentStep() ); } loadVector.zero(); this->updateYourself( this->giveCurrentStep() ); this->terminate( this->giveCurrentStep() ); // this->updateLoadVectors (this->giveCurrentStep()); // already in terminate // restore old step length nMethod->setStepLength(deltaL); stiffMode = oldStiffMode; } else { // comment this, if output for mapped configuration (not equilibrated) not wanted this->printOutputAt( this->giveOutputStream(), this->giveCurrentStep() ); } return result; }
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 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; TimeStep *icStep = this->giveSolutionStepWhenIcApply(); int neq = this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); #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() ) { bcRhs.resize(neq); //rhs vector from solution step i-1 bcRhs.zero(); this->applyIC(icStep); //project initial conditions to have temporary temperature in integration points //edge or surface load on elements //add internal source vector on elements this->assembleVectorFromElements( bcRhs, icStep, TransportExternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); //add prescribed value, such as temperature, on nodes this->assembleDirichletBcRhsVector( bcRhs, icStep, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); //add nodal load this->assembleVectorFromDofManagers( bcRhs, icStep, ExternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); } //Create a new lhs matrix if necessary if ( tStep->isTheFirstStep() || this->changingProblemSize ) { conductivityMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); if ( !conductivityMatrix ) { OOFEM_ERROR("sparse matrix creation failed"); } conductivityMatrix->buildInternalStructure( this, 1, EModelDefaultEquationNumbering() ); #ifdef VERBOSE OOFEM_LOG_INFO("Assembling conductivity and capacity matrices\n"); #endif //Add contribution of alpha*K+C/dt (where K has contributions from conductivity and neumann b.c.s) this->assemble( *conductivityMatrix, icStep, MidpointLhsAssembler(lumpedCapacityStab, alpha), EModelDefaultEquationNumbering(), this->giveDomain(1) ); } //get the previous Rhs vector if ( !tStep->isTheFirstStep() && this->changingProblemSize ) { UnknownsField->initialize( VM_RhsTotal, tStep, bcRhs, EModelDefaultEquationNumbering() ); } //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(); //boundary conditions evaluated at targetTime this->assembleVectorFromElements( bcRhs, tStep, TransportExternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); this->assembleDirichletBcRhsVector( bcRhs, tStep, VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); // assembling load from nodes this->assembleVectorFromDofManagers( bcRhs, tStep, InternalForceAssembler(), 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, 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); linSolver->solve(*conductivityMatrix, rhs, *UnknownsField->giveSolutionVector(tStep) ); // update solution state counter tStep->incrementStateCounter(); }
void LoadBalancer :: migrateLoad(Domain *d) { // domain->migrateLoad(this); int i; int nproc = d->giveEngngModel()->giveNumberOfProcesses(); int myrank = d->giveEngngModel()->giveRank(); OOFEM_LOG_RELEVANT("[%d] LoadBalancer: migrateLoad: migrating load\n", myrank); // initialize work transfer plugins before any transfer for ( i = 1; i <= wtpList.giveSize(); i++ ) { wtpList.at(i)->init(d); } CommunicatorBuff cb(nproc, CBT_dynamic); Communicator com(d->giveEngngModel(), &cb, myrank, nproc, CommMode_Dynamic); // move existing dofmans and elements, that will be local on current partition, // into local map com.packAllData(this, d, & LoadBalancer :: packMigratingData); com.initExchange(MIGRATE_LOAD_TAG); // do something in between d->initGlobalDofManMap(); d->initGlobalElementMap(); this->deleteRemoteDofManagers(d); this->deleteRemoteElements(d); // receive remote data com.unpackAllData(this, d, & LoadBalancer :: unpackMigratingData); com.finishExchange(); d->commitTransactions( d->giveTransactionManager() ); #if LoadBalancer_debug_print // debug print int j, nnodes = d->giveNumberOfDofManagers(), nelems = d->giveNumberOfElements(); fprintf(stderr, "\n[%d] Nodal Table\n", myrank); for ( i = 1; i <= nnodes; i++ ) { if ( d->giveDofManager(i)->giveParallelMode() == DofManager_local ) { fprintf( stderr, "[%d]: %5d[%d] local\n", myrank, i, d->giveDofManager(i)->giveGlobalNumber() ); } else if ( d->giveDofManager(i)->giveParallelMode() == DofManager_shared ) { fprintf( stderr, "[%d]: %5d[%d] shared ", myrank, i, d->giveDofManager(i)->giveGlobalNumber() ); for ( j = 1; j <= d->giveDofManager(i)->givePartitionList()->giveSize(); j++ ) { fprintf( stderr, "%d ", d->giveDofManager(i)->givePartitionList()->at(j) ); } fprintf(stderr, "\n"); } } fprintf(stderr, "\n[%d] Element Table\n", myrank); for ( i = 1; i <= nelems; i++ ) { fprintf(stderr, "%5d {", i); for ( j = 1; j <= d->giveElement(i)->giveNumberOfDofManagers(); j++ ) { fprintf( stderr, "%d ", d->giveElement(i)->giveDofManager(j)->giveNumber() ); } fprintf(stderr, "}\n"); } #endif // migrate work transfer plugin data for ( i = 1; i <= wtpList.giveSize(); i++ ) { wtpList.at(i)->migrate(); } // update work transfer plugin data for ( i = 1; i <= wtpList.giveSize(); i++ ) { wtpList.at(i)->update(); } // print some local statistics int nelem = domain->giveNumberOfElements(); int nnode = domain->giveNumberOfDofManagers(); int lnode = 0, lelem = 0; for ( i = 1; i <= nnode; i++ ) { if ( domain->giveDofManager(i)->giveParallelMode() == DofManager_local ) { lnode++; } } for ( i = 1; i <= nelem; i++ ) { if ( domain->giveElement(i)->giveParallelMode() == Element_local ) { lelem++; } } OOFEM_LOG_RELEVANT("[%d] LB Statistics: local elem=%d local node=%d\n", myrank, lelem, lnode); }
LoadBalancerMonitor :: LoadBalancerDecisionType WallClockLoadBalancerMonitor :: decide(TimeStep *atTime) { int i, nproc = emodel->giveNumberOfProcesses(); int myrank = emodel->giveRank(); Domain *d = emodel->giveLoadBalancer()->giveDomain(); int ie, nelem; double *node_solutiontimes = new double [ nproc ]; double *node_relcomppowers = new double [ nproc ]; double *node_equivelements = new double [ nproc ]; double min_st, max_st; double relWallClockImbalance; double absWallClockImbalance; double neqelems, sum_relcomppowers; if ( node_solutiontimes == NULL ) { OOFEM_ERROR("LoadBalancer::LoadEvaluation failed to allocate node_solutiontimes array"); } if ( node_relcomppowers == NULL ) { OOFEM_ERROR("LoadBalancer::LoadEvaluation failed to allocate node_relcomppowers array"); } if ( node_equivelements == NULL ) { OOFEM_ERROR("LoadBalancer::LoadEvaluation failed to allocate node_equivelements array"); } // compute wall solution time of my node double mySolutionTime = emodel->giveTimer()->getWtime(EngngModelTimer :: EMTT_NetComputationalStepTimer); #ifdef __LB_DEBUG // perturb solution time artificially if requested bool perturb = false; dynaList< Range > :: iterator perturbedStepsIter; for ( perturbedStepsIter = perturbedSteps.begin(); perturbedStepsIter != perturbedSteps.end(); ++perturbedStepsIter ) { if ( ( * perturbedStepsIter ).test( atTime->giveNumber() ) ) { perturb = true; break; } } if ( perturb ) { mySolutionTime *= perturbFactor; OOFEM_LOG_RELEVANT("[%d] WallClockLoadBalancerMonitor: perturbed solution time by factor=%.2f\n", myrank, perturbFactor); } #endif // collect wall clock computational time MPI_Allgather(& mySolutionTime, 1, MPI_DOUBLE, node_solutiontimes, 1, MPI_DOUBLE, MPI_COMM_WORLD); OOFEM_LOG_RELEVANT("\nLoadBalancer:: individual processor times [sec]: ("); for ( i = 0; i < nproc; i++ ) { OOFEM_LOG_RELEVANT(" %.3f", node_solutiontimes [ i ]); } OOFEM_LOG_RELEVANT(")\n"); // detect imbalance min_st = max_st = node_solutiontimes [ 0 ]; for ( i = 0; i < nproc; i++ ) { min_st = min(min_st, node_solutiontimes [ i ]); max_st = max(max_st, node_solutiontimes [ i ]); } absWallClockImbalance = ( max_st - min_st ); if ( min_st ) { relWallClockImbalance = ( ( max_st - min_st ) / min_st ); } else { relWallClockImbalance = 0.0; } // update node (processor) weights // compute number or equivalent elements (equavalent element has computational weight equal to 1.0) nelem = d->giveNumberOfElements(); neqelems = 0.0; for ( ie = 1; ie <= nelem; ie++ ) { if ( d->giveElement(ie)->giveParallelMode() == Element_remote ) { continue; } neqelems += d->giveElement(ie)->predictRelativeComputationalCost(); } // exchange number or equivalent elements MPI_Allgather(& neqelems, 1, MPI_DOUBLE, node_equivelements, 1, MPI_DOUBLE, MPI_COMM_WORLD); if ( !this->staticNodeWeightFlag ) { // compute relative computational powers (solution_time/number_of_equivalent_elements) for ( i = 0; i < nproc; i++ ) { node_relcomppowers [ i ] = node_equivelements [ i ] / node_solutiontimes [ i ]; } // normalize computational powers sum_relcomppowers = 0.0; for ( i = 0; i < nproc; i++ ) { sum_relcomppowers += node_relcomppowers [ i ]; } for ( i = 0; i < nproc; i++ ) { nodeWeights(i) = node_relcomppowers [ i ] / sum_relcomppowers; } } // log equivalent elements on nodes OOFEM_LOG_RELEVANT("[%d] LoadBalancer: node equivalent elements: ", myrank); for ( i = 0; i < nproc; i++ ) { OOFEM_LOG_RELEVANT("%6d ", ( int ) node_equivelements [ i ]); } OOFEM_LOG_RELEVANT("\n"); // log processor weights OOFEM_LOG_RELEVANT("[%d] LoadBalancer: updated proc weights: ", myrank); for ( i = 0; i < nproc; i++ ) { #ifdef __LB_DEBUG OOFEM_LOG_RELEVANT( "%22.15e ", nodeWeights(i) ); #else OOFEM_LOG_RELEVANT( "%4.3f ", nodeWeights(i) ); #endif } OOFEM_LOG_RELEVANT("\n"); delete[] node_solutiontimes; delete[] node_relcomppowers; delete[] node_equivelements; #ifdef __LB_DEBUG if ( recoveredSteps.giveSize() ) { // recover lb if requested int pos; if ( ( pos = recoveredSteps.findFirstIndexOf( atTime->giveNumber() ) ) ) { double procWeight, sumWeight = 0.0, *procWeights = new double [ nproc ]; // assign prescribed processing weight procWeight = processingWeights.at(pos); OOFEM_LOG_RELEVANT("[%d] WallClockLoadBalancerMonitor: processing weight overriden by value=%e\n", myrank, procWeight); // exchange processing weights MPI_Allgather(& procWeight, 1, MPI_DOUBLE, procWeights, 1, MPI_DOUBLE, MPI_COMM_WORLD); for ( i = 0; i < nproc; i++ ) { nodeWeights(i) = procWeights [ i ]; sumWeight += procWeights [ i ]; } delete[] procWeights; if ( fabs(sumWeight - 1.0) > 1.0e-10 ) { OOFEM_ERROR2("[%d] WallClockLoadBalancerMonitor:processing weights do not sum to 1.0 (sum = %e)\n", sumWeight); } OOFEM_LOG_RELEVANT("[%d] LoadBalancer: wall clock imbalance rel=%.2f\%,abs=%.2fs, recovering load\n", myrank, 100 * relWallClockImbalance, absWallClockImbalance); return LBD_RECOVER; } else {
int LoadBalancer :: unpackMigratingData(Domain *d, ProcessCommunicator &pc) { // create temp space for dofManagers and elements // merging should be made by domain ? // maps of new dofmanagers and elements indexed by global number // we can put local dofManagers and elements into maps (should be done before unpacking) // int nproc=this->giveEngngModel()->giveNumberOfProcesses(); int myrank = d->giveEngngModel()->giveRank(); int iproc = pc.giveRank(); int _mode, _globnum, _type; bool _newentry; classType _etype; IntArray _partitions, local_partitions; //LoadBalancer::DofManMode dmode; DofManager *dofman; DomainTransactionManager *dtm = d->giveTransactionManager(); // ************************************************** // Unpack migrating data to remote partition // ************************************************** if ( iproc == myrank ) { return 1; // skip local partition } // query process communicator to use ProcessCommunicatorBuff *pcbuff = pc.giveProcessCommunicatorBuff(); ProcessCommDataStream pcDataStream(pcbuff); pcbuff->unpackInt(_type); // unpack dofman data while ( _type != LOADBALANCER_END_DATA ) { _etype = ( classType ) _type; pcbuff->unpackInt(_mode); switch ( _mode ) { case LoadBalancer :: DM_Remote: // receiving new local dofManager pcbuff->unpackInt(_globnum); /* * _newentry = false; * if ( ( dofman = dtm->giveDofManager(_globnum) ) == NULL ) { * // data not available -> create a new one * _newentry = true; * dofman = CreateUsrDefDofManagerOfType(_etype, 0, d); * } */ _newentry = true; dofman = CreateUsrDefDofManagerOfType(_etype, 0, d); dofman->setGlobalNumber(_globnum); // unpack dofman state (this is the local dofman, not available on remote) dofman->restoreContext(& pcDataStream, CM_Definition | CM_DefinitionGlobal | CM_State | CM_UnknownDictState); // unpack list of new partitions pcbuff->unpackIntArray(_partitions); dofman->setPartitionList(& _partitions); dofman->setParallelMode(DofManager_local); // add transaction if new entry allocated; otherwise existing one has been modified via returned dofman if ( _newentry ) { dtm->addTransaction(DomainTransactionManager :: DTT_ADD, DomainTransactionManager :: DCT_DofManager, _globnum, dofman); } //dmanMap[_globnum] = dofman; break; case LoadBalancer :: DM_Shared: // receiving new shared dofManager, that was local on sending partition // should be received only once (from partition where was local) pcbuff->unpackInt(_globnum); /* * _newentry = false; * if ( ( dofman = dtm->giveDofManager(_globnum) ) == NULL ) { * // data not available -> mode should be SharedUpdate * _newentry = true; * dofman = CreateUsrDefDofManagerOfType(_etype, 0, d); * } */ _newentry = true; dofman = CreateUsrDefDofManagerOfType(_etype, 0, d); dofman->setGlobalNumber(_globnum); // unpack dofman state (this is the local dofman, not available on remote) dofman->restoreContext(& pcDataStream, CM_Definition | CM_DefinitionGlobal | CM_State | CM_UnknownDictState); // unpack list of new partitions pcbuff->unpackIntArray(_partitions); dofman->setPartitionList(& _partitions); dofman->setParallelMode(DofManager_shared); #ifdef __VERBOSE_PARALLEL fprintf(stderr, "[%d] received Shared new dofman [%d]\n", myrank, _globnum); #endif // add transaction if new entry allocated; otherwise existing one has been modified via returned dofman if ( _newentry ) { dtm->addTransaction(DomainTransactionManager :: DTT_ADD, DomainTransactionManager :: DCT_DofManager, _globnum, dofman); } //dmanMap[_globnum] = dofman; break; default: OOFEM_ERROR2("LoadBalancer::unpackMigratingData: unexpected dof manager type (%d)", _type); } // get next type record pcbuff->unpackInt(_type); } ; // while (_type != LOADBALANCER_END_DATA); // unpack element data Element *elem; int nrecv = 0; do { pcbuff->unpackInt(_type); if ( _type == LOADBALANCER_END_DATA ) { break; } _etype = ( classType ) _type; elem = CreateUsrDefElementOfType(_etype, 0, d); elem->restoreContext(& pcDataStream, CM_Definition | CM_State); elem->initForNewStep(); dtm->addTransaction(DomainTransactionManager :: DTT_ADD, DomainTransactionManager :: DCT_Element, elem->giveGlobalNumber(), elem); nrecv++; //recvElemList.push_back(elem); } while ( 1 ); OOFEM_LOG_RELEVANT("[%d] LoadBalancer:: receiving %d migrating elements from %d\n", myrank, nrecv, iproc); return 1; }
int LoadBalancer :: packMigratingData(Domain *d, ProcessCommunicator &pc) { int myrank = d->giveEngngModel()->giveRank(); int iproc = pc.giveRank(); int idofman, ndofman; classType dtype; DofManager *dofman; LoadBalancer :: DofManMode dmode; // ************************************************** // Pack migrating data to remote partition // ************************************************** // pack dofManagers if ( iproc == myrank ) { return 1; // skip local partition } // query process communicator to use ProcessCommunicatorBuff *pcbuff = pc.giveProcessCommunicatorBuff(); ProcessCommDataStream pcDataStream(pcbuff); // loop over dofManagers ndofman = d->giveNumberOfDofManagers(); for ( idofman = 1; idofman <= ndofman; idofman++ ) { dofman = d->giveDofManager(idofman); dmode = this->giveDofManState(idofman); dtype = dofman->giveClassID(); // sync data to remote partition // if dofman already present on remote partition then there is no need to sync //if ((this->giveDofManPartitions(idofman)->findFirstIndexOf(iproc))) { if ( ( this->giveDofManPartitions(idofman)->findFirstIndexOf(iproc) ) && ( !dofman->givePartitionList()->findFirstIndexOf(iproc) ) ) { pcbuff->packInt(dtype); pcbuff->packInt(dmode); pcbuff->packInt( dofman->giveGlobalNumber() ); // pack dofman state (this is the local dofman, not available on remote) /* this is a potential performance leak, sending shared dofman to a partition, * in which is already shared does not require to send context (is already there) * here for simplicity it is always send */ dofman->saveContext(& pcDataStream, CM_Definition | CM_DefinitionGlobal | CM_State | CM_UnknownDictState); // send list of new partitions pcbuff->packIntArray( * ( this->giveDofManPartitions(idofman) ) ); } } // pack end-of-dofman-section record pcbuff->packInt(LOADBALANCER_END_DATA); int ielem, nelem = d->giveNumberOfElements(), nsend = 0; Element *elem; for ( ielem = 1; ielem <= nelem; ielem++ ) { // begin loop over elements elem = d->giveElement(ielem); if ( ( elem->giveParallelMode() == Element_local ) && ( this->giveElementPartition(ielem) == iproc ) ) { // pack local element (node numbers shuld be global ones!!!) // pack type pcbuff->packInt( elem->giveClassID() ); // nodal numbers shuld be packed as global !! elem->saveContext(& pcDataStream, CM_Definition | CM_DefinitionGlobal | CM_State); nsend++; } } // end loop over elements // pack end-of-element-record pcbuff->packInt(LOADBALANCER_END_DATA); OOFEM_LOG_RELEVANT("[%d] LoadBalancer:: sending %d migrating elements to %d\n", myrank, nsend, iproc); return 1; }
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."); } }
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 NodalAveragingRecoveryModel :: initRegionMap(IntArray ®ionMap, IntArray ®ionValSize, InternalStateType type) { int nregions = this->giveNumberOfVirtualRegions(); int ielem, nelem = domain->giveNumberOfElements(); int i, elemVR, regionsSkipped = 0; Element *element; NodalAveragingRecoveryModelInterface *interface; regionMap.resize(nregions); regionMap.zero(); regionValSize.resize(nregions); regionValSize.zero(); // loop over elements and check if implement interface for ( ielem = 1; ielem <= nelem; ielem++ ) { element = domain->giveElement(ielem); if ( !element-> isActivated(domain->giveEngngModel()->giveCurrentStep()) ) { //skip inactivated elements continue; } #ifdef __PARALLEL_MODE if ( element->giveParallelMode() != Element_local ) { continue; } #endif if ( ( interface = ( NodalAveragingRecoveryModelInterface * ) element-> giveInterface(NodalAveragingRecoveryModelInterfaceType) ) == NULL ) { // If an element doesn't implement the interface, it is ignored. //regionsSkipped = 1; //regionMap.at( element->giveRegionNumber() ) = 1; continue; } else { if ((elemVR = this->giveElementVirtualRegionNumber(ielem))) { // test if elemVR is nonzero if ( regionValSize.at(elemVR) ) { if ( regionValSize.at(elemVR) != interface->NodalAveragingRecoveryMI_giveDofManRecordSize(type) ) { // This indicates a size mis-match between different elements, no choice but to skip the region. regionMap.at(elemVR) = 1; regionsSkipped = 1; } } else { regionValSize.at(elemVR) = interface-> NodalAveragingRecoveryMI_giveDofManRecordSize(type); } } } } if ( regionsSkipped ) { OOFEM_LOG_RELEVANT("NodalAveragingRecoveryModel :: initRegionMap: skipping regions for InternalStateType %s\n", __InternalStateTypeToString(type) ); for ( i = 1; i <= nregions; i++ ) { if ( regionMap.at(i) ) { OOFEM_LOG_RELEVANT("%d ", i); } } OOFEM_LOG_RELEVANT("\n"); } }
void NonLinearStatic :: 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 // if ( initFlag ) { // // first step create space for stiffness Matrix // if ( !stiffnessMatrix ) { stiffnessMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); } if ( !stiffnessMatrix ) { OOFEM_ERROR("sparse matrix creation failed"); } if ( nonlocalStiffnessFlag ) { if ( !stiffnessMatrix->isAsymmetric() ) { OOFEM_ERROR("stiffnessMatrix does not support asymmetric storage"); } } stiffnessMatrix->buildInternalStructure( this, di, EModelDefaultEquationNumbering() ); } #if 0 if ( ( mstep->giveFirstStepNumber() == tStep->giveNumber() ) ) { #ifdef VERBOSE OOFEM_LOG_INFO("Resetting load level\n"); #endif if ( mstepCumulateLoadLevelFlag ) { cumulatedLoadLevel += loadLevel; } else { cumulatedLoadLevel = 0.0; } this->loadLevel = 0.0; } #endif if ( loadInitFlag || controlMode == nls_directControl ) { #ifdef VERBOSE OOFEM_LOG_DEBUG("Assembling reference load\n"); #endif // // assemble the incremental reference load vector // this->assembleIncrementalReferenceLoadVectors(incrementalLoadVector, incrementalLoadVectorOfPrescribed, refLoadInputMode, this->giveDomain(di), tStep); loadInitFlag = 0; } if ( tStep->giveNumber() == 1 ) { int neq = this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); totalDisplacement.resize(neq); totalDisplacement.zero(); incrementOfDisplacement.resize(neq); incrementOfDisplacement.zero(); } // // -> BEGINNING OF LOAD (OR DISPLACEMENT) STEP <- // // // set-up numerical model // this->giveNumericalMethod( this->giveMetaStep( tStep->giveMetaStepNumber() ) ); // // call numerical model to solve arise problem // #ifdef VERBOSE OOFEM_LOG_RELEVANT( "\n\nSolving [step number %5d.%d, time = %e]\n\n", tStep->giveNumber(), tStep->giveVersion(), tStep->giveIntrinsicTime() ); #endif if ( this->initialGuessType == IG_Tangent ) { #ifdef VERBOSE OOFEM_LOG_RELEVANT("Computing initial guess\n"); #endif FloatArray extrapolatedForces; this->assembleExtrapolatedForces( extrapolatedForces, tStep, TangentStiffnessMatrix, this->giveDomain(di) ); extrapolatedForces.negated(); this->updateComponent( tStep, NonLinearLhs, this->giveDomain(di) ); SparseLinearSystemNM *linSolver = nMethod->giveLinearSolver(); OOFEM_LOG_RELEVANT("solving for increment\n"); linSolver->solve(*stiffnessMatrix, extrapolatedForces, incrementOfDisplacement); OOFEM_LOG_RELEVANT("initial guess found\n"); totalDisplacement.add(incrementOfDisplacement); } else if ( this->initialGuessType != IG_None ) { OOFEM_ERROR("Initial guess type: %d not supported", initialGuessType); } else { incrementOfDisplacement.zero(); } //totalDisplacement.printYourself(); if ( initialLoadVector.isNotEmpty() ) { numMetStatus = nMethod->solve(*stiffnessMatrix, incrementalLoadVector, & initialLoadVector, totalDisplacement, incrementOfDisplacement, internalForces, internalForcesEBENorm, loadLevel, refLoadInputMode, currentIterations, tStep); } else { numMetStatus = nMethod->solve(*stiffnessMatrix, incrementalLoadVector, NULL, totalDisplacement, incrementOfDisplacement, internalForces, internalForcesEBENorm, loadLevel, refLoadInputMode, currentIterations, tStep); } ///@todo Martin: ta bort!!! //this->updateComponent(tStep, NonLinearLhs, this->giveDomain(di)); ///@todo Use temporary variables. updateYourself() should set the final values, while proceedStep should be callable multiple times for each step (if necessary). / Mikael OOFEM_LOG_RELEVANT("Equilibrium reached at load level = %f in %d iterations\n", cumulatedLoadLevel + loadLevel, currentIterations); prevStepLength = currentStepLength; }
void StaticStructural :: solveYourselfAt(TimeStep *tStep) { int neq; int di = 1; this->field->advanceSolution(tStep); this->field->applyBoundaryCondition(tStep); ///@todo Temporary hack, advanceSolution should apply the boundary conditions directly. neq = this->giveNumberOfDomainEquations( di, EModelDefaultEquationNumbering() ); if (tStep->giveNumber()==1) { this->field->initialize(VM_Total, tStep, this->solution, EModelDefaultEquationNumbering() ); } else { this->field->initialize(VM_Total, tStep->givePreviousStep(), this->solution, EModelDefaultEquationNumbering() ); this->field->update(VM_Total, tStep, this->solution, EModelDefaultEquationNumbering() ); } this->field->applyBoundaryCondition(tStep); ///@todo Temporary hack to override the incorrect values that is set by "update" above. Remove this when that is fixed. FloatArray incrementOfSolution(neq), externalForces(neq); // Create "stiffness matrix" if ( !this->stiffnessMatrix ) { this->stiffnessMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); if ( !this->stiffnessMatrix ) { OOFEM_ERROR("Couldn't create requested sparse matrix of type %d", sparseMtrxType); } this->stiffnessMatrix->buildInternalStructure( this, di, EModelDefaultEquationNumbering() ); } this->internalForces.resize(neq); this->giveNumericalMethod( this->giveCurrentMetaStep() ); this->initMetaStepAttributes( this->giveCurrentMetaStep() ); if ( this->initialGuessType == IG_Tangent ) { OOFEM_LOG_RELEVANT("Computing initial guess\n"); FloatArray extrapolatedForces(neq); this->assembleExtrapolatedForces( extrapolatedForces, tStep, TangentStiffnessMatrix, this->giveDomain(di) ); extrapolatedForces.negated(); ///@todo Need to find a general way to support this before enabling it by default. //this->assembleVector(extrapolatedForces, tStep, LinearizedDilationForceAssembler(), VM_Incremental, EModelDefaultEquationNumbering(), this->giveDomain(di) ); #if 0 // Some debug stuff: extrapolatedForces.printYourself("extrapolatedForces"); this->internalForces.zero(); this->assembleVectorFromElements(this->internalForces, tStep, InternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(di)); this->internalForces.printYourself("internal forces"); #endif OOFEM_LOG_RELEVANT("Computing old tangent\n"); this->updateComponent( tStep, NonLinearLhs, this->giveDomain(di) ); SparseLinearSystemNM *linSolver = nMethod->giveLinearSolver(); OOFEM_LOG_RELEVANT("Solving for increment\n"); linSolver->solve(*stiffnessMatrix, extrapolatedForces, incrementOfSolution); OOFEM_LOG_RELEVANT("Initial guess found\n"); this->solution.add(incrementOfSolution); this->field->update(VM_Total, tStep, this->solution, EModelDefaultEquationNumbering()); this->field->applyBoundaryCondition(tStep); ///@todo Temporary hack to override the incorrect values that is set by "update" above. Remove this when that is fixed. } else if ( this->initialGuessType != IG_None ) { OOFEM_ERROR("Initial guess type: %d not supported", initialGuessType); } else { incrementOfSolution.zero(); } // Build initial/external load externalForces.zero(); this->assembleVector( externalForces, tStep, ExternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); this->updateSharedDofManagers(externalForces, EModelDefaultEquationNumbering(), LoadExchangeTag); if ( this->giveProblemScale() == macroScale ) { OOFEM_LOG_INFO("\nStaticStructural :: solveYourselfAt - Solving step %d, metastep %d, (neq = %d)\n", tStep->giveNumber(), tStep->giveMetaStepNumber(), neq); } double loadLevel; int currentIterations; NM_Status status = this->nMethod->solve(*this->stiffnessMatrix, externalForces, NULL, this->solution, incrementOfSolution, this->internalForces, this->eNorm, loadLevel, // Only relevant for incrementalBCLoadVector? SparseNonLinearSystemNM :: rlm_total, currentIterations, tStep); if ( !( status & NM_Success ) ) { OOFEM_ERROR("No success in solving problem"); } }
int AdaptiveNonLinearStatic :: initializeAdaptiveFrom(EngngModel *sourceProblem) { int ielem, nelem, result = 1; // measure time consumed by mapping Timer timer; double mc1, mc2, mc3; timer.startTimer(); if ( dynamic_cast< AdaptiveNonLinearStatic * >(sourceProblem) ) { OOFEM_ERROR("source problem must also be AdaptiveNonlinearStatic."); } this->currentStep = new TimeStep( * ( sourceProblem->giveCurrentStep() ) ); if ( sourceProblem->givePreviousStep() ) { this->previousStep = new TimeStep( * ( sourceProblem->givePreviousStep() ) ); } // map primary unknowns EIPrimaryUnknownMapper mapper; totalDisplacement.resize( this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ) ); incrementOfDisplacement.resize( this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ) ); totalDisplacement.zero(); incrementOfDisplacement.zero(); result &= mapper.mapAndUpdate( totalDisplacement, VM_Total, sourceProblem->giveDomain(1), this->giveDomain(1), sourceProblem->giveCurrentStep() ); result &= mapper.mapAndUpdate( incrementOfDisplacement, VM_Incremental, sourceProblem->giveDomain(1), this->giveDomain(1), sourceProblem->giveCurrentStep() ); timer.stopTimer(); mc1 = timer.getUtime(); timer.startTimer(); // map internal ip state nelem = this->giveDomain(1)->giveNumberOfElements(); for ( ielem = 1; ielem <= nelem; ielem++ ) { result &= this->giveDomain(1)->giveElement(ielem)->adaptiveMap( sourceProblem->giveDomain(1), sourceProblem->giveCurrentStep() ); } timer.stopTimer(); mc2 = timer.getUtime(); timer.startTimer(); // computes the stresses and calls updateYourself to mapped state for ( ielem = 1; ielem <= nelem; ielem++ ) { result &= this->giveDomain(1)->giveElement(ielem)->adaptiveUpdate(currentStep); } // finish mapping process for ( ielem = 1; ielem <= nelem; ielem++ ) { result &= this->giveDomain(1)->giveElement(ielem)->adaptiveFinish(currentStep); } // increment time step if mapped state will be considered as new solution stepL /* * this->giveNextStep(); * if (equilibrateMappedConfigurationFlag) { * // we need to assemble the load vector in same time as the restarted step, * // so new time step is generated with same intrincic time as has the * // previous step if equilibrateMappedConfigurationFlag is set. * // this allows to equlibrate the previously reached state * TimeStep* cts = this->giveCurrentStep(); * cts->setTime(cts->giveTime()-cts->giveTimeIncrement()); * cts = this->givePreviousStep(); * cts->setTime(cts->giveTime()-cts->giveTimeIncrement()); * } * * * if (this->giveCurrentStep()->giveNumber() == * this->giveMetaStep(this->giveCurrentStep()->giveMetaStepNumber())->giveFirstStepNumber()) { * this->updateAttributes (this->giveCurrentStep()); * } */ this->updateAttributes( this->giveCurrentMetaStep() ); // increment solution state counter - not needed, IPs are updated by adaptiveUpdate previously called // and there is no change in primary vars. // this->giveCurrentStep()->incrementStateCounter(); // assemble new initial load for new discretization this->assembleInitialLoadVector( initialLoadVector, initialLoadVectorOfPrescribed, static_cast< AdaptiveNonLinearStatic * >(sourceProblem), 1, this->giveCurrentStep() ); // assemble new total load for new discretization // this->assembleCurrentTotalLoadVector (totalLoadVector, totalLoadVectorOfPrescribed, this->giveCurrentStep()); // set bcloadVector to zero (no increment within same step) timer.stopTimer(); mc3 = timer.getUtime(); // compute processor time used by the program OOFEM_LOG_INFO("user time consumed by primary mapping: %.2fs\n", mc1); OOFEM_LOG_INFO("user time consumed by ip mapping: %.2fs\n", mc2); OOFEM_LOG_INFO("user time consumed by ip update: %.2fs\n", mc3); OOFEM_LOG_INFO("user time consumed by mapping: %.2fs\n", mc1 + mc2 + mc3); // // // bring mapped configuration into equilibrium // if ( equilibrateMappedConfigurationFlag ) { // use secant stiffness to resrore equilibrium NonLinearStatic_stiffnessMode oldStiffMode = this->stiffMode; stiffMode = nls_secantStiffness; if ( initFlag ) { stiffnessMatrix = classFactory.createSparseMtrx(sparseMtrxType); if ( stiffnessMatrix == NULL ) { OOFEM_ERROR("sparse matrix creation failed"); } if ( nonlocalStiffnessFlag ) { if ( !stiffnessMatrix->isAsymmetric() ) { OOFEM_ERROR("stiffnessMatrix does not support asymmetric storage"); } } stiffnessMatrix->buildInternalStructure( this, 1, EID_MomentumBalance, EModelDefaultEquationNumbering() ); stiffnessMatrix->zero(); // zero stiffness matrix this->assemble( stiffnessMatrix, this->giveCurrentStep(), EID_MomentumBalance, SecantStiffnessMatrix, EModelDefaultEquationNumbering(), this->giveDomain(1) ); initFlag = 0; } // updateYourself() not necessary - the adaptiveUpdate previously called does the job //this->updateYourself(this->giveCurrentStep()); #ifdef VERBOSE OOFEM_LOG_INFO( "Equilibrating mapped configuration [step number %5d.%d]\n", this->giveCurrentStep()->giveNumber(), this->giveCurrentStep()->giveVersion() ); #endif //double deltaL = nMethod->giveUnknownComponent (StepLength, 0); double deltaL = nMethod->giveCurrentStepLength(); this->assembleIncrementalReferenceLoadVectors( incrementalLoadVector, incrementalLoadVectorOfPrescribed, refLoadInputMode, this->giveDomain(1), EID_MomentumBalance, this->giveCurrentStep() ); // // call numerical model to solve arised problem // #ifdef VERBOSE OOFEM_LOG_RELEVANT( "Solving [step number %5d.%d]\n", this->giveCurrentStep()->giveNumber(), this->giveCurrentStep()->giveVersion() ); #endif //nMethod -> solveYourselfAt(this->giveCurrentStep()) ; nMethod->setStepLength(deltaL / 5.0); if ( initialLoadVector.isNotEmpty() ) { numMetStatus = nMethod->solve( stiffnessMatrix, & incrementalLoadVector, & initialLoadVector, & totalDisplacement, & incrementOfDisplacement, & internalForces, internalForcesEBENorm, loadLevel, refLoadInputMode, currentIterations, this->giveCurrentStep() ); } else { numMetStatus = nMethod->solve( stiffnessMatrix, & incrementalLoadVector, NULL, & totalDisplacement, & incrementOfDisplacement, & internalForces, internalForcesEBENorm, loadLevel, refLoadInputMode, currentIterations, this->giveCurrentStep() ); } loadVector.zero(); this->updateYourself( this->giveCurrentStep() ); this->terminate( this->giveCurrentStep() ); this->updateLoadVectors( this->giveCurrentStep() ); // restore old step length nMethod->setStepLength(deltaL); stiffMode = oldStiffMode; } else { // comment this, if output for mapped configuration (not equilibrated) not wanted this->printOutputAt( this->giveOutputStream(), this->giveCurrentStep() ); } return result; }