Esempio n. 1
0
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);
}
Esempio n. 2
0
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 ) );
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
    }
}
Esempio n. 6
0
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;
}
Esempio n. 8
0
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();
}
Esempio n. 11
0
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);
}
Esempio n. 12
0
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   {
Esempio n. 13
0
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;
}
Esempio n. 14
0
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.");
    }
}
Esempio n. 16
0
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 &regionMap, IntArray &regionValSize, 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;
}
Esempio n. 19
0
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");
    }
}
Esempio n. 20
0
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;
}