void
StructuralEngngModel :: updateInternalState(TimeStep *tStep)
{
    for ( auto &domain: domainList ) {
        if ( requiresUnknownsDictionaryUpdate() ) {
            for ( auto &dman : domain->giveDofManagers() ) {
                this->updateDofUnknownsDictionary(dman.get(), tStep);
            }
        }

        for ( auto &bc : domain->giveBcs() ) {
            ActiveBoundaryCondition *abc;

            if ( ( abc = dynamic_cast< ActiveBoundaryCondition * >(bc.get()) ) ) {
                int ndman = abc->giveNumberOfInternalDofManagers();
                for ( int j = 1; j <= ndman; j++ ) {
                    this->updateDofUnknownsDictionary(abc->giveInternalDofManager(j), tStep);
                }
            }
        }

        if ( internalVarUpdateStamp != tStep->giveSolutionStateCounter() ) {
            for ( auto &elem : domain->giveElements() ) {
                elem->updateInternalState(tStep);
            }

            internalVarUpdateStamp = tStep->giveSolutionStateCounter();
        }
    }
}
Exemple #2
0
void
StructuralEngngModel :: updateInternalState(TimeStep *tStep)
{
    int nnodes;
    Domain *domain;

    for ( int idomain = 1; idomain <= this->giveNumberOfDomains(); idomain++ ) {
        domain = this->giveDomain(idomain);

        nnodes = domain->giveNumberOfDofManagers();
        if ( requiresUnknownsDictionaryUpdate() ) {
            for ( int j = 1; j <= nnodes; j++ ) {
                this->updateDofUnknownsDictionary(domain->giveDofManager(j), tStep);
            }
        }

        int nbc = domain->giveNumberOfBoundaryConditions();
        for ( int i = 1; i <= nbc; ++i ) {
            GeneralBoundaryCondition *bc = domain->giveBc(i);
            ActiveBoundaryCondition *abc;

            if ( ( abc = dynamic_cast< ActiveBoundaryCondition * >(bc) ) ) {
                int ndman = abc->giveNumberOfInternalDofManagers();
                for ( int j = 1; j <= ndman; j++ ) {
                    this->updateDofUnknownsDictionary(abc->giveInternalDofManager(j), tStep);
                }
            }
        }

        if ( internalVarUpdateStamp != tStep->giveSolutionStateCounter() ) {
            int nelem = domain->giveNumberOfElements();
            for ( int j = 1; j <= nelem; j++ ) {
                domain->giveElement(j)->updateInternalState(tStep);
            }

            internalVarUpdateStamp = tStep->giveSolutionStateCounter();
        }
    }
}
Exemple #3
0
int DynCompCol :: buildInternalStructure(EngngModel *eModel, int di, const UnknownNumberingScheme &s)
{
    /*
     * int neq = eModel -> giveNumberOfDomainEquations (di);
     *
     **#ifndef DynCompCol_USE_STL_SETS
     * IntArray  loc;
     * Domain* domain = eModel->giveDomain(di);
     * int nelem = domain -> giveNumberOfElements() ;
     * int i,ii,j,jj,n, indx;
     * Element* elem;
     * IntArray colItems(neq);
     * // allocation map
     * char* map = new char[neq*neq];
     * if (map == NULL) {
     * printf ("CompCol::buildInternalStructure - map creation failed");
     * exit (1);
     * }
     *
     * for (i=0; i<neq*neq; i++)
     * map[i]=0;
     *
     *
     * for (n=1 ; n<=nelem ; n++) {
     * elem = domain -> giveElement(n);
     * elem -> giveLocationArray (loc) ;
     *
     * for (i=1 ; i <= loc.giveSize() ; i++) {
     * if ((ii = loc.at(i))) {
     *  for (j=1; j <= loc.giveSize() ; j++) {
     *   if ((jj=loc.at(j)))
     *    if (map[(ii-1)*neq+jj-1] == 0) {
     *     map[(ii-1)*neq+jj-1] = 1;
     *     colItems.at(ii) ++;
     *    }
     *  }
     * }
     * }
     * }
     *
     * if (rowind_) {
     * for (i=0; i< nColumns; i++) delete this->rowind_[i];
     * delete this->rowind_;
     * }
     * rowind_ = (IntArray**) new (IntArray*)[neq];
     * for (j=0; j<neq; j++) rowind_[j] = new IntArray(colItems(j));
     *
     * indx = 1;
     * for (j=0; j<neq; j++) { // column loop
     * indx = 1;
     * for (i=0; i<neq; i++) { // row loop
     * if (map[i*neq+j]) {
     *  rowind_[j]->at(indx) = i;
     *  indx++;
     * }
     * }
     * }
     *
     * // delete map
     * delete (map);
     *
     * // allocate value array
     * if (columns_) {
     * for (i=0; i< nColumns; i++) delete this->columns_[i];
     * delete this->columns_;
     * }
     * columns_= (FloatArray**) new (FloatArray*)[neq];
     * int nz_ = 0;
     * for (j=0; j<neq; j++) {
     * columns_[j] = new FloatArray (colItems(j));
     * nz_ += colItems(j);
     * }
     *
     * printf ("\nDynCompCol info: neq is %d, nelem is %d\n",neq,nz_);
     **#else
     * int i,j;
     * if (columns) {
     * for (i=0; i< nColumns; i++) delete this->columns[i];
     * delete this->columns;
     * }
     * columns= new std::map<int, double>*[neq];
     * for (j=0; j<neq; j++) {
     * columns[j] = new std::map<int, double>;
     * }
     *
     **#endif
     *
     * nColumns = nRows = neq;
     * // increment version
     * this->version++;
     *
     * return true;
     */
    int neq = eModel->giveNumberOfDomainEquations(di, s);

#ifndef DynCompCol_USE_STL_SETS
    IntArray loc;
    Domain *domain = eModel->giveDomain(di);
    int nelem = domain->giveNumberOfElements();
    int i, ii, j, jj, n;
    Element *elem;

    nColumns = nRows = neq;

    if ( rowind_ ) {
        for ( i = 0; i < nColumns; i++ ) {
            delete this->rowind_ [ i ];
        }

        delete this->rowind_;
    }

    rowind_ = ( IntArray ** ) new IntArray * [ neq ];
    for ( j = 0; j < neq; j++ ) {
        rowind_ [ j ] = new IntArray();
    }

    // allocate value array
    if ( columns_ ) {
        for ( i = 0; i < nColumns; i++ ) {
            delete this->columns_ [ i ];
        }

        delete this->columns_;
    }

    columns_ = ( FloatArray ** ) new FloatArray * [ neq ];
    for ( j = 0; j < neq; j++ ) {
        columns_ [ j ] = new FloatArray();
    }

    for ( n = 1; n <= nelem; n++ ) {
        elem = domain->giveElement(n);
        elem->giveLocationArray(loc, s);

        for ( i = 1; i <= loc.giveSize(); i++ ) {
            if ( ( ii = loc.at(i) ) ) {
                for ( j = 1; j <= loc.giveSize(); j++ ) {
                    if ( ( jj = loc.at(j) ) ) {
                        this->insertRowInColumn(ii - 1, jj - 1);
                    }
                }
            }
        }
    }

    // loop over active boundary conditions
    int nbc = domain->giveNumberOfBoundaryConditions();
    std :: vector< IntArray >r_locs;
    std :: vector< IntArray >c_locs;

    for ( int i = 1; i <= nbc; ++i ) {
        ActiveBoundaryCondition *bc = dynamic_cast< ActiveBoundaryCondition * >( domain->giveBc(i) );
        if ( bc != NULL ) {
            bc->giveLocationArrays(r_locs, c_locs, UnknownCharType, s, s);
            for ( std :: size_t k = 0; k < r_locs.size(); k++ ) {
                IntArray &krloc = r_locs [ k ];
                IntArray &kcloc = c_locs [ k ];
                for ( int i = 1; i <= krloc.giveSize(); i++ ) {
                    if ( ( ii = krloc.at(i) ) ) {
                        for ( int j = 1; j <= kcloc.giveSize(); j++ ) {
                            if ( ( jj = kcloc.at(j) ) ) {
                                this->insertRowInColumn(jj - 1, ii - 1);
                            }
                        }
                    }
                }
            }
        }
    }

    int nz_ = 0;
    for ( j = 0; j < neq; j++ ) {
        nz_ += this->rowind_ [ j ]->giveSize();
    }

    OOFEM_LOG_DEBUG("DynCompCol info: neq is %d, nelem is %d\n", neq, nz_);
#else
    nColumns = nRows = neq;

    columns.resize( neq );
    for ( auto &col: columns ) {
        col.clear();
    }

#endif

    // increment version
    this->version++;

    return true;
}
Exemple #4
0
void EffectiveTangentAssembler :: assembleFromActiveBC(SparseMtrx &k, ActiveBoundaryCondition &bc, TimeStep* tStep, const UnknownNumberingScheme &s_r, const UnknownNumberingScheme &s_c) const
{
    // TODO: Crucial part to add: We have to support a scaling factor for this method to support effective tangents.
    bc.assemble(k, tStep, TangentStiffnessMatrix, s_r, s_c, this->k);
}
Exemple #5
0
void TangentAssembler :: assembleFromActiveBC(SparseMtrx &k, ActiveBoundaryCondition &bc, TimeStep* tStep, const UnknownNumberingScheme &s_r, const UnknownNumberingScheme &s_c) const
{
    bc.assemble(k, tStep, TangentStiffnessMatrix, s_r, s_c);
}
Exemple #6
0
void ExternalForceAssembler :: assembleFromActiveBC(FloatArray &answer, ActiveBoundaryCondition &bc, TimeStep* tStep, ValueModeType mode, const UnknownNumberingScheme &s, FloatArray *eNorms) const
{
    bc.assembleVector(answer, tStep, ExternalForcesVector, mode, s, eNorms);
    //bc.assembleExternalForces(answer, tStep, s, eNorms);
}
Exemple #7
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.");
    }
}
Exemple #8
0
int Skyline :: buildInternalStructure(EngngModel *eModel, int di, const UnknownNumberingScheme &s)
{
    // first create array of
    // maximal column height for assembled characteristics matrix
    //

    int maxle;
    int ac1;
    int neq;
    if ( s.isDefault() ) {
        neq = eModel->giveNumberOfDomainEquations(di, s);
    } else {
        neq = s.giveRequiredNumberOfDomainEquation();
    }
    if ( neq == 0 ) {
        if ( mtrx ) {
            delete mtrx;
        }
        mtrx = NULL;
        adr.clear();
        return true;
    }

    IntArray loc;
    IntArray mht(neq);
    Domain *domain = eModel->giveDomain(di);

    for ( int j = 1; j <= neq; j++ ) {
        mht.at(j) = j; // initialize column height, maximum is line number (since it only stores upper triangular)
    }

    // loop over elements code numbers
    for ( auto &elem : domain->giveElements() ) {
        elem->giveLocationArray(loc, s);
        maxle = INT_MAX;
        for ( int ieq : loc ) {
            if ( ieq != 0 ) {
                maxle = min(maxle, ieq);
            }
        }

        for ( int ieq : loc ) {
            if ( ieq != 0 ) {
                mht.at(ieq) = min( maxle, mht.at(ieq) );
            }
        }
    }

    // loop over active boundary conditions (e.g. relative kinematic constraints)
    std :: vector< IntArray >r_locs;
    std :: vector< IntArray >c_locs;

    for ( auto &gbc : domain->giveBcs() ) {
        ActiveBoundaryCondition *bc = dynamic_cast< ActiveBoundaryCondition * >( gbc.get() );
        if ( bc != NULL ) {
            bc->giveLocationArrays(r_locs, c_locs, UnknownCharType, s, s);
            for ( std :: size_t k = 0; k < r_locs.size(); k++ ) {
                IntArray &krloc = r_locs [ k ];
                IntArray &kcloc = c_locs [ k ];
                maxle = INT_MAX;
                for ( int ii : krloc ) {
                    if ( ii > 0 ) {
                        maxle = min(maxle, ii);
                    }
                }
                for ( int jj : kcloc ) {
                    if ( jj > 0 ) {
                        mht.at(jj) = min( maxle, mht.at(jj) );
                    }
                }
            }
        }
    }

    
    if ( domain->hasContactManager() ) {
        ContactManager *cMan = domain->giveContactManager();
            
        for ( int i =1; i <= cMan->giveNumberOfContactDefinitions(); i++ ) {
            ContactDefinition *cDef = cMan->giveContactDefinition(i);
            for ( int k = 1; k <= cDef->giveNumbertOfContactElements(); k++ ) {
                ContactElement *cEl = cDef->giveContactElement(k);
                cEl->giveLocationArray(loc, s);
            
                maxle = INT_MAX;
                for ( int ieq : loc ) {
                    if ( ieq != 0 ) {
                        maxle = min(maxle, ieq);
                    }
                }

                for ( int ieq : loc ) {
                    if ( ieq != 0 ) {
                        mht.at(ieq) = min( maxle, mht.at(ieq) );
                    }
                  
                }
            }
        }
    }
    
    // NOTE
    // add there call to eModel if any possible additional equation added by
    // eModel
    // currently not supported

    // increases number of columns according to size of mht
    // mht is array containing minimal equation number per column
    // This method also increases column height.


    adr.resize(neq + 1);

    ac1 = 1;
    for ( int i = 1; i <= neq; i++ ) {
        adr.at(i) = ac1;
        ac1 += ( i - mht.at(i) + 1 );
    }

    adr.at(neq + 1) = ac1;
    nRows = nColumns = neq;
    nwk  = ac1;
    if ( mtrx ) {
        free(mtrx);
    }

    mtrx = ( double * ) calloc( ac1, sizeof( double ) );
    if ( !mtrx ) {
        OOFEM_ERROR("Can't allocate: %d", ac1);
    }

    // increment version
    this->version++;
    return true;
}
Exemple #9
0
int CompCol :: buildInternalStructure(EngngModel *eModel, int di, const UnknownNumberingScheme &s)
{
    /*
     * IntArray  loc;
     * Domain* domain = eModel->giveDomain(di);
     * int neq = eModel -> giveNumberOfDomainEquations (di);
     * int nelem = domain -> giveNumberOfElements() ;
     * int i,ii,j,jj,n, indx;
     * Element* elem;
     * // allocation map
     * char* map = new char[neq*neq];
     * if (map == NULL) {
     * printf ("CompCol::buildInternalStructure - map creation failed");
     * exit (1);
     * }
     *
     * for (i=0; i<neq*neq; i++)
     * map[i]=0;
     *
     *
     * this->nz_ = 0;
     *
     * for (n=1 ; n<=nelem ; n++) {
     * elem = domain -> giveElement(n);
     * elem -> giveLocationArray (loc) ;
     *
     * for (i=1 ; i <= loc.giveSize() ; i++) {
     * if ((ii = loc.at(i))) {
     *  for (j=1; j <= loc.giveSize() ; j++) {
     *   if ((jj=loc.at(j))) {
     *    if (map[(ii-1)*neq+jj-1] == 0) {
     *     map[(ii-1)*neq+jj-1] = 1;
     *     this->nz_ ++;
     *    }
     *   }
     *  }
     * }
     * }
     * }
     *
     * rowind_.resize (nz_);
     * colptr_.resize (neq+1);
     * indx = 0;
     * for (j=0; j<neq; j++) { // column loop
     * colptr_(j) = indx;
     * for (i=0; i<neq; i++) { // row loop
     *  if (map[i*neq+j]) {
     *   rowind_(indx) = i;
     *   indx++;
     *  }
     * }
     * }
     * colptr_(neq) = indx;
     *
     * // delete map
     * delete (map);
     *
     * // allocate value array
     * val_.resize(nz_);
     * val_.zero();
     *
     * printf ("\nCompCol info: neq is %d, nwk is %d\n",neq,nz_);
     *
     * dim_[0] = dim_[1] = nColumns = nRows = neq;
     *
     * // increment version
     * this->version++;
     *
     * return true;
     */
    IntArray loc;
    Domain *domain = eModel->giveDomain(di);
    int neq = eModel->giveNumberOfDomainEquations(di, s);
    int nelem = domain->giveNumberOfElements();
    int i, ii, j, jj, n, indx;
    Element *elem;
    // allocation map
    std :: vector< std :: set< int > > columns(neq);
    /*
     * std::set<int> **columns = new std::set<int>*[neq];
     * for (j=0; j<neq; j++) {
     * columns[j] = new std::set<int>;
     * }
     */

    this->nz_ = 0;

    for ( n = 1; n <= nelem; n++ ) {
        elem = domain->giveElement(n);
        elem->giveLocationArray(loc, s);

        for ( i = 1; i <= loc.giveSize(); i++ ) {
            if ( ( ii = loc.at(i) ) ) {
                for ( j = 1; j <= loc.giveSize(); j++ ) {
                    if ( ( jj = loc.at(j) ) ) {
                        columns [ jj - 1 ].insert(ii - 1);
                    }
                }
            }
        }
    }


    // loop over active boundary conditions
    int nbc = domain->giveNumberOfBoundaryConditions();
    std :: vector< IntArray >r_locs;
    std :: vector< IntArray >c_locs;

    for ( int i = 1; i <= nbc; ++i ) {
        ActiveBoundaryCondition *bc = dynamic_cast< ActiveBoundaryCondition * >( domain->giveBc(i) );
        if ( bc != NULL ) {
            bc->giveLocationArrays(r_locs, c_locs, UnknownCharType, s, s);
            for ( std :: size_t k = 0; k < r_locs.size(); k++ ) {
                IntArray &krloc = r_locs [ k ];
                IntArray &kcloc = c_locs [ k ];
                for ( int i = 1; i <= krloc.giveSize(); i++ ) {
                    if ( ( ii = krloc.at(i) ) ) {
                        for ( int j = 1; j <= kcloc.giveSize(); j++ ) {
                            if ( ( jj = kcloc.at(j) ) ) {
                                columns [ jj - 1 ].insert(ii - 1);
                            }
                        }
                    }
                }
            }
        }
    }

    for ( i = 0; i < neq; i++ ) {
        this->nz_ += columns [ i ].size();
    }

    rowind_.resize(nz_);
    colptr_.resize(neq + 1);
    indx = 0;

    for ( j = 0; j < neq; j++ ) { // column loop
        colptr_(j) = indx;
        for ( int row: columns [  j ] ) { // row loop
            rowind_(indx++) = row;
        }
    }

    colptr_(neq) = indx;

    /*
     * // delete map
     * for (i=0; i< neq; i++) {columns[i]->clear(); delete columns[i];}
     * delete columns;
     */

    // allocate value array
    val_.resize(nz_);
    val_.zero();

    OOFEM_LOG_DEBUG("CompCol info: neq is %d, nwk is %d\n", neq, nz_);

    dim_ [ 0 ] = dim_ [ 1 ] = nColumns = nRows = neq;

    // increment version
    this->version++;

    return true;
}
Exemple #10
0
int DSSMatrix :: buildInternalStructure(EngngModel *eModel, int di, const UnknownNumberingScheme &s)
{
    IntArray loc;
    Domain *domain = eModel->giveDomain(di);
    int neq = eModel->giveNumberOfDomainEquations(di, s);
    unsigned long indx;
    // allocation map
    std :: vector< std :: set< int > >columns(neq);

    unsigned long nz_ = 0;

    for ( auto &elem : domain->giveElements() ) {
        elem->giveLocationArray(loc, s);

        for ( int ii : loc ) {
            if ( ii > 0 ) {
                for ( int jj : loc ) {
                    if ( jj > 0 ) {
                        columns [ jj - 1 ].insert(ii - 1);
                    }
                }
            }
        }
    }

    // loop over active boundary conditions
    std::vector<IntArray> r_locs;
    std::vector<IntArray> c_locs;
    
    for ( auto &gbc : domain->giveBcs() ) {
        ActiveBoundaryCondition *bc = dynamic_cast< ActiveBoundaryCondition * >( gbc.get() );
        if ( bc != NULL ) {
            bc->giveLocationArrays(r_locs, c_locs, UnknownCharType, s, s);
            for (std::size_t k = 0; k < r_locs.size(); k++) {
                IntArray &krloc = r_locs[k];
                IntArray &kcloc = c_locs[k];
                for ( int ii : krloc ) {
                    if ( ii > 0 ) {
                        for ( int jj : kcloc ) {
                            if ( jj > 0 ) {
                                columns [ jj - 1 ].insert(ii - 1);
                            }
                        }
                    }
                }
            }
        }
    }
    
    for ( int i = 0; i < neq; i++ ) {
        nz_ += columns [ i ].size();
    }

    unsigned long *rowind_ = new unsigned long [ nz_ ];
    unsigned long *colptr_ = new unsigned long [ neq + 1 ];
    if ( ( rowind_ == NULL ) || ( colptr_ == NULL ) ) {
        OOFEM_ERROR("free store exhausted, exiting");
    }

    indx = 0;

    for ( int j = 0; j < neq; j++ ) { // column loop
        colptr_ [ j ] = indx;
        for ( auto &val : columns [ j ] ) { // row loop
            rowind_ [ indx++ ] = val;
        }
    }

    colptr_ [ neq ] = indx;

    _sm.reset( new SparseMatrixF(neq, NULL, rowind_, colptr_, 0, 0, true) ); 
    if ( !_sm ) {
        OOFEM_FATAL("free store exhausted, exiting");
    }


    /*
     *  Assemble block to equation mapping information
     */

    bool _succ = true;
    int _ndofs, _neq, ndofmans = domain->giveNumberOfDofManagers();
    int ndofmansbc = 0;

    ///@todo This still misses element internal dofs.
    // count number of internal dofmans on active bc
    for ( auto &bc : domain->giveBcs() ) {
        ndofmansbc += bc->giveNumberOfInternalDofManagers();
    }

    int bsize = 0;
    if ( ndofmans > 0 ) {
        bsize = domain->giveDofManager(1)->giveNumberOfDofs();
    }

    long *mcn = new long [ (ndofmans+ndofmansbc) * bsize ];
    long _c = 0;

    if ( mcn == NULL ) {
        OOFEM_FATAL("free store exhausted, exiting");
    }

    for ( auto &dman : domain->giveDofManagers() ) {
        _ndofs = dman->giveNumberOfDofs();
        if ( _ndofs > bsize ) {
            _succ = false;
            break;
        }

        for ( Dof *dof: *dman ) {
            if ( dof->isPrimaryDof() ) {
                _neq = dof->giveEquationNumber(s);
                if ( _neq > 0 ) {
                    mcn [ _c++ ] = _neq - 1;
                } else {
                    mcn [ _c++ ] = -1; // no corresponding row in sparse mtrx structure
                }
            } else {
                    mcn [ _c++ ] = -1; // no corresponding row in sparse mtrx structure
            }
        }

        for ( int i = _ndofs + 1; i <= bsize; i++ ) {
            mcn [ _c++ ] = -1;                         // no corresponding row in sparse mtrx structure
        }
    }

    // loop over internal dofmans of active bc
    for ( auto &bc : domain->giveBcs() ) {
      int ndman = bc->giveNumberOfInternalDofManagers();
      for (int idman = 1; idman <= ndman; idman ++) {
            DofManager *dman = bc->giveInternalDofManager(idman);
            _ndofs = dman->giveNumberOfDofs();
            if ( _ndofs > bsize ) {
                _succ = false;
                break;
            }

            for ( Dof *dof: *dman ) {
                if ( dof->isPrimaryDof() ) {
                    _neq = dof->giveEquationNumber(s);
                    if ( _neq > 0 ) {
                    mcn [ _c++ ] = _neq - 1;
                    } else {
                    mcn [ _c++ ] = -1; // no corresponding row in sparse mtrx structure
                    }
                }
            }

            for ( int i = _ndofs + 1; i <= bsize; i++ ) {
                mcn [ _c++ ] = -1;                         // no corresponding row in sparse mtrx structure
            }
        }
    }
    
    if ( _succ ) {
        _dss->SetMatrixPattern(_sm.get(), bsize);
        _dss->LoadMCN(ndofmans+ndofmansbc, bsize, mcn);
    } else {
        OOFEM_LOG_INFO("DSSMatrix: using assumed block structure");
        _dss->SetMatrixPattern(_sm.get(), bsize);
    }

    _dss->PreFactorize();
    // zero matrix, put unity on diagonal with supported dofs
    _dss->LoadZeros();
    delete[] mcn;

    OOFEM_LOG_DEBUG("DSSMatrix info: neq is %d, bsize is %d\n", neq, nz_);

    // increment version
    this->version++;

    return true;
}
int
PetscSparseMtrx :: buildInternalStructure(EngngModel *eModel, int di, EquationID ut, const UnknownNumberingScheme &s)
{
    IntArray loc;
    Domain *domain = eModel->giveDomain(di);
    int nelem;

    if ( mtrx ) {
        MatDestroy(&mtrx);
    }

    if ( this->kspInit ) {
      KSPDestroy(&ksp);
      this->kspInit  = false; // force ksp to be initialized
    }

    this->ut = ut;
    this->emodel = eModel;
    this->di = di;


#ifdef __PARALLEL_MODE
    if ( eModel->isParallel() ) {
        int rank;
        PetscNatural2GlobalOrdering *n2g;
        PetscNatural2LocalOrdering *n2l;
        rank = eModel->giveRank();
        n2g = eModel->givePetscContext(di, ut)->giveN2Gmap();
        n2l = eModel->givePetscContext(di, ut)->giveN2Lmap();

        n2l->init(eModel, ut, di);
        n2g->init(eModel, ut, di);

 #ifdef __VERBOSE_PARALLEL
        VERBOSEPARALLEL_PRINT("PetscSparseMtrx:: buildInternalStructure", "", rank);
 #endif

        leqs = n2g->giveNumberOfLocalEqs();
        geqs = n2g->giveNumberOfGlobalEqs();

        //printf("%d, leqs = %d, geqs = %d\n", this->emodel->giveRank(), leqs, geqs);

 #ifdef __VERBOSE_PARALLEL
        OOFEM_LOG_INFO( "[%d]PetscSparseMtrx:: buildInternalStructure: l_eqs = %d, g_eqs = %d, n_eqs = %d\n", rank, leqs, geqs, eModel->giveNumberOfEquations(ut) );
 #endif

        // determine nonzero structure of a "local (maintained)" part of matrix, and the off-diagonal part
        int i, ii, j, jj, n;
        Element *elem;
        // allocation map
        std :: vector< std :: set< int > >d_rows(leqs);  // diagonal sub-matrix allocation
        std :: vector< std :: set< int > >o_rows(leqs);  // off-diagonal allocation

        IntArray d_nnz(leqs), o_nnz(leqs), lloc, gloc;

        //fprintf (stderr,"[%d] n2l map: ",rank);
        //for (n=1; n<=n2l.giveN2Lmap()->giveSize(); n++) fprintf (stderr, "%d ", n2l.giveN2Lmap()->at(n));

        nelem = domain->giveNumberOfElements();
        for ( n = 1; n <= nelem; n++ ) {
            //fprintf (stderr, "(elem %d) ", n);
            elem = domain->giveElement(n);
            elem->giveLocationArray(loc, ut, s);
            n2l->map2New(lloc, loc, 0); // translate natural->local numbering (remark, 1-based indexing)
            n2g->map2New(gloc, loc, 0); // translate natural->global numbering (remark, 0-based indexing)
            // See the petsc manual for details on how this allocation is constructed.
            for ( i = 1; i <= lloc.giveSize(); i++ ) {
                if ( ( ii = lloc.at(i) ) ) {
                    for ( j = 1; j <= lloc.giveSize(); j++ ) {
                        if ( ( jj = gloc.at(j) ) >= 0 ) { // if negative, then it is prescribed
                            if ( lloc.at(j) ) { // if true, then its the local part (the diagonal block matrix)
                                d_rows [ ii - 1 ].insert(jj);
                            } else { // Otherwise it must be off-diagonal
                                o_rows [ ii - 1 ].insert(jj);
                            }
                        }
                    }
                }
            }
            //fprintf (stderr, "\n");
        }

        // Diagonal must always be allocated; this code ensures that for every local line, it adds the global column number
        IntArray *n2gmap = n2g->giveN2Gmap();
        IntArray *n2lmap = n2l->giveN2Lmap();
        for ( int n = 1; n <= n2lmap->giveSize(); ++n ) {
            if ( n2lmap->at(n) ) {
                d_rows [ n2lmap->at(n)-1 ].insert( n2gmap->at(n) );
            }
        }

        for ( i = 0; i < leqs; i++ ) {
            d_nnz(i) = d_rows [ i ].size();
            o_nnz(i) = o_rows [ i ].size();
        }

        //fprintf (stderr,"\n[%d]PetscSparseMtrx: Profile ...",rank);
        //for (i=0; i<leqs; i++) fprintf(stderr, "%d ", d_nnz(i));
        //fprintf (stderr,"\n[%d]PetscSparseMtrx: Creating MPIAIJ Matrix ...\n",rank);

        // create PETSc mat
        MatCreate(PETSC_COMM_WORLD, & mtrx);
        MatSetSizes(mtrx, leqs, leqs, geqs, geqs);
        MatSetType(mtrx, MATMPIAIJ);
        MatSetFromOptions(mtrx);
        MatSetUp(mtrx);
        MatMPIAIJSetPreallocation(mtrx, 0, d_nnz.givePointer(), 0, o_nnz.givePointer());
        //MatMPIBAIJSetPreallocation( mtrx, PETSC_DECIDE, 0, d_nnz.givePointer(), onz, onnz );
        //MatMPISBAIJSetPreallocation( mtrx, PETSC_DECIDE, 0, d_nnz_sym.givePointer(), onz, onnz );

        MatSetOption(mtrx, MAT_ROW_ORIENTED, PETSC_FALSE); // To allow the insertion of values using MatSetValues in column major order
        MatSetOption(mtrx, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);

 #ifdef __VERBOSE_PARALLEL
        VERBOSEPARALLEL_PRINT("PetscSparseMtrx:: buildInternalStructure", "done", rank);
 #endif
    } else {
#endif

    leqs = geqs = eModel->giveNumberOfEquations(ut);
    int i, ii, j, jj, n;
    Element *elem;
    // allocation map
    std :: vector< std :: set< int > >rows(leqs);
    std :: vector< std :: set< int > >rows_sym(leqs);

    nelem = domain->giveNumberOfElements();
    for ( n = 1; n <= nelem; n++ ) {
        elem = domain->giveElement(n);
        elem->giveLocationArray(loc, ut, s);
        for ( i = 1; i <= loc.giveSize(); i++ ) {
            if ( ( ii = loc.at(i) ) ) {
                for ( j = 1; j <= loc.giveSize(); j++ ) {
                    jj = loc.at(j);
                    if ( jj ) {
                        rows [ ii - 1 ].insert(jj - 1);
                        if ( jj >= ii ) {
                            rows_sym [ ii - 1 ].insert(jj - 1);
                        }
                    }
                }
            }
        }
    }

    // Structure from active boundary conditions.
    AList<IntArray> locs, temp;
    for ( n = 1; n <= domain->giveNumberOfBoundaryConditions(); n++ ) {
        ActiveBoundaryCondition *activebc = dynamic_cast<ActiveBoundaryCondition*>(domain->giveBc(n));
        if (activebc) {
            ///@todo Deal with the CharType here.
            activebc->giveLocationArrays(locs, temp, ut, TangentStiffnessMatrix, s, s, domain);
            for (int k = 1; k < locs.giveSize(); k++) {
                IntArray *kloc = locs.at(k);
                for ( i = 1; i <= kloc->giveSize(); i++ ) {
                    if ( ( ii = kloc->at(i) ) ) {
                        for ( j = 1; j <= kloc->giveSize(); j++ ) {
                            jj = kloc->at(j);
                            if ( jj ) {
                                rows [ ii - 1 ].insert(jj - 1);
                                if ( jj >= ii ) {
                                    rows_sym [ ii - 1 ].insert(jj - 1);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    IntArray d_nnz(leqs);
    IntArray d_nnz_sym(leqs);
    for ( i = 0; i < leqs; i++ ) {
        d_nnz(i) = rows [ i ].size();
        d_nnz_sym(i) = rows_sym [ i ].size();
    }

    MatCreate(PETSC_COMM_SELF, & mtrx);
    MatSetSizes(mtrx, leqs, leqs, geqs, geqs);
    MatSetType(mtrx, MATSEQAIJ);
    //MatSetType(mtrx, MATSBAIJ);
    //MatSetType(mtrx, MATDENSE);
    MatSetFromOptions(mtrx);

    MatSetUp(mtrx);
    MatSeqAIJSetPreallocation( mtrx, 0, d_nnz.givePointer() );
    MatSeqBAIJSetPreallocation( mtrx, PETSC_DECIDE, 0, d_nnz.givePointer() );
    MatSeqSBAIJSetPreallocation( mtrx, PETSC_DECIDE, 0, d_nnz_sym.givePointer() );

    MatSetOption(mtrx, MAT_ROW_ORIENTED, PETSC_FALSE); // To allow the insertion of values using MatSetValues in column major order
    MatSetOption(mtrx, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);

#ifdef __PARALLEL_MODE
    }
#endif

    nRows = nColumns = geqs;
    this->newValues = true;
    return true;
}
///@todo I haven't looked at the parallel code yet (lack of time right now, and i want to see it work first). / Mikael
int
PetscSparseMtrx :: buildInternalStructure(EngngModel *eModel, int di, EquationID ut, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s)
{
    IntArray loc;
    Domain *domain = eModel->giveDomain(di);
    int nelem;

    if ( mtrx ) {
        MatDestroy(&mtrx);
    }

    if ( this->kspInit ) {
      KSPDestroy(&ksp);
      this->kspInit  = false; // force ksp to be initialized
    }

    this->ut = ut;
    this->emodel = eModel;
    this->di = di;

#ifdef __PARALLEL_MODE
    if ( eModel->isParallel() ) {
        OOFEM_ERROR("PetscSparseMtrx :: buildInternalStructure - Not implemented");
    }
#endif
    // This should be based on the numberingscheme. Also, geqs seems redundant.

    // This could simplify things.
    int npeqs = eModel->giveNumberOfPrescribedEquations(ut);
    int neqs = eModel->giveNumberOfEquations(ut);
    nRows = r_s.isDefault() ? neqs : npeqs;
    nColumns = c_s.isDefault() ? neqs : npeqs;

    int totalEquations = eModel->giveNumberOfEquations(ut) + eModel->giveNumberOfPrescribedEquations(ut);

    //determine nonzero structure of matrix
    int ii, jj;
    Element *elem;
    IntArray r_loc, c_loc;
    std :: vector< std :: set< int > >rows(totalEquations);
    std :: vector< std :: set< int > >rows_sym(totalEquations); // Only the symmetric part

    nelem = domain->giveNumberOfElements();
    for ( int n = 1; n <= nelem; n++ ) {
        elem = domain->giveElement(n);
        elem->giveLocationArray(r_loc, ut, r_s);
        elem->giveLocationArray(c_loc, ut, c_s);
        for ( int i = 1; i <= r_loc.giveSize(); i++ ) {
            if ( ( ii = r_loc.at(i) ) ) {
                for ( int j = 1; j <= c_loc.giveSize(); j++ ) {
                    jj = c_loc.at(j);
                    if ( jj ) {
                        rows [ ii - 1 ].insert(jj - 1);
                        if ( jj >= ii ) {
                            rows_sym [ ii - 1 ].insert(jj - 1);
                        }
                    }
                }
            }
        }
    }
    // Structure from active boundary conditions.
    AList<IntArray> r_locs, c_locs;
    for ( int n = 1; n <= domain->giveNumberOfBoundaryConditions(); n++ ) {
        ActiveBoundaryCondition *activebc = dynamic_cast<ActiveBoundaryCondition*>(domain->giveBc(n));
        if (activebc) {
            ///@todo Deal with the CharType here.
            activebc->giveLocationArrays(r_locs, c_locs, ut, TangentStiffnessMatrix, r_s, c_s, domain);
            for (int k = 1; k < r_locs.giveSize(); k++) {
                IntArray *krloc = r_locs.at(k);
                IntArray *kcloc = c_locs.at(k);
                for ( int i = 1; i <= krloc->giveSize(); i++ ) {
                    if ( ( ii = krloc->at(i) ) ) {
                        for ( int j = 1; j <= kcloc->giveSize(); j++ ) {
                            jj = kcloc->at(j);
                            if ( jj ) {
                                rows [ ii - 1 ].insert(jj - 1);
                                if ( jj >= ii ) {
                                    rows_sym [ ii - 1 ].insert(jj - 1);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    geqs = leqs = nRows;

    IntArray d_nnz(leqs);
    IntArray d_nnz_sym(leqs);
    for ( int i = 0; i < leqs; i++ ) {
        d_nnz(i) = rows [ i ].size();
        d_nnz_sym(i) = rows_sym [ i ].size();
    }

    // create PETSc mat
    MatCreate(PETSC_COMM_SELF, & mtrx);
    MatSetSizes(mtrx, nRows, nColumns, nRows, nColumns);
    //MatSetType(mtrx, MATSEQAIJ);
    MatSetType(mtrx, MATSEQSBAIJ);
    MatSetFromOptions(mtrx);

    //The incompatible preallocations are ignored automatically.
    MatSetUp(mtrx);
    MatSeqAIJSetPreallocation( mtrx, 0, d_nnz.givePointer() );
    MatSeqBAIJSetPreallocation( mtrx, PETSC_DECIDE, 0, d_nnz.givePointer() ); ///@todo Not sure about PETSC_DECIDE here.
    //MatSeqSBAIJSetPreallocation( mtrx, PETSC_DECIDE, 0, d_nnz_sym.givePointer() ); // Symmetry should practically never apply here.

    MatSetOption(mtrx, MAT_ROW_ORIENTED, PETSC_FALSE); // To allow the insertion of values using MatSetValues in column major order
    MatSetOption(mtrx, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);

    this->newValues = true;
    return true;
}
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.");
    }
}
int DSSMatrix :: buildInternalStructure(EngngModel *eModel, int di, EquationID ut, const UnknownNumberingScheme &s)
{
    IntArray loc;
    Domain *domain = eModel->giveDomain(di);
    int neq = eModel->giveNumberOfDomainEquations(di, s);
    int nelem = domain->giveNumberOfElements();
    int i, ii, j, jj, n;
    unsigned long indx;
    Element *elem;
    // allocation map
    std :: vector< std :: set< int > >columns(neq);

    unsigned long nz_ = 0;

    for ( n = 1; n <= nelem; n++ ) {
        elem = domain->giveElement(n);
        elem->giveLocationArray(loc, ut, s);

        for ( i = 1; i <= loc.giveSize(); i++ ) {
            if ( ( ii = loc.at(i) ) ) {
                for ( j = 1; j <= loc.giveSize(); j++ ) {
                    if ( ( jj = loc.at(j) ) ) {
                        columns [ jj - 1 ].insert(ii - 1);
                    }
                }
            }
        }
    }

    // loop over active boundary conditions
    int nbc = domain->giveNumberOfBoundaryConditions();
    std::vector<IntArray> r_locs;
    std::vector<IntArray> c_locs;
    
    for ( i = 1; i <= nbc; ++i ) {
        ActiveBoundaryCondition *bc = dynamic_cast< ActiveBoundaryCondition * >( domain->giveBc(i) );
        if ( bc != NULL ) {
            bc->giveLocationArrays(r_locs, c_locs, ut, UnknownCharType, s, s);
	    for (std::size_t k = 0; k < r_locs.size(); k++) {
	      IntArray &krloc = r_locs[k];
	      IntArray &kcloc = c_locs[k];
	      for ( int ri = 1; ri <= krloc.giveSize(); ri++ ) {
		if ( ( ii = krloc.at(ri) ) ) {
		  for ( j = 1; j <= kcloc.giveSize(); j++ ) {
		    if ( (jj = kcloc.at(j) ) ) {
		      columns [ jj - 1 ].insert(ii - 1);
		    }
		  }
		}
	      }
	    }
	}
    }
    
    for ( i = 0; i < neq; i++ ) {
        nz_ += columns [ i ].size();
    }

    unsigned long *rowind_ = new unsigned long [ nz_ ];
    unsigned long *colptr_ = new unsigned long [ neq + 1 ];
    if ( ( rowind_ == NULL ) || ( colptr_ == NULL ) ) {
        OOFEM_ERROR("DSSMatrix::buildInternalStructure: free store exhausted, exiting");
    }

    indx = 0;

    std :: set< int > :: iterator pos;
    for ( j = 0; j < neq; j++ ) { // column loop
        colptr_ [ j ] = indx;
        for ( pos = columns [ j ].begin(); pos != columns [ j ].end(); ++pos ) { // row loop
            rowind_ [ indx++ ] = * pos;
        }
    }

    colptr_ [ neq ] = indx;

    if ( _sm ) {
        delete _sm;
    }

    if ( ( _sm = new SparseMatrixF(neq, NULL, rowind_, colptr_, 0, 0, true) ) == NULL ) {
        OOFEM_ERROR("DSSMatrix::buildInternalStructure: free store exhausted, exiting");
    }

    int bsize = eModel->giveDomain(1)->giveDefaultNodeDofIDArry().giveSize();
    /*
     *  Assemble block to equation mapping information
     */

    bool _succ = true;
    int _ndofs, _neq, ndofmans = domain->giveNumberOfDofManagers();
    int ndofmansbc = 0;
    // count number of internal dofmans on active bc
    for (n=1; n<=nbc; n++) {
      ndofmansbc+=domain->giveBc(n)->giveNumberOfInternalDofManagers();
    }

    long *mcn = new long [ (ndofmans+ndofmansbc) * bsize ];
    long _c = 0;
    DofManager *dman;

    if ( mcn == NULL ) {
        OOFEM_ERROR("DSSMatrix::buildInternalStructure: free store exhausted, exiting");
    }

    for ( n = 1; n <= ndofmans; n++ ) {
        dman = domain->giveDofManager(n);
        _ndofs = dman->giveNumberOfDofs();
        if ( _ndofs > bsize ) {
            _succ = false;
            break;
        }

        for ( i = 1; i <= _ndofs; i++ ) {
            if ( dman->giveDof(i)->isPrimaryDof() ) {
                _neq = dman->giveDof(i)->giveEquationNumber(s);
                if ( _neq > 0 ) {
                    mcn [ _c++ ] = _neq - 1;
                } else {
                    mcn [ _c++ ] = -1; // no corresponding row in sparse mtrx structure
                }
            }
        }

        for ( i = _ndofs + 1; i <= bsize; i++ ) {
            mcn [ _c++ ] = -1;                         // no corresponding row in sparse mtrx structure
        }
    }

    // loop over internal dofmans of active bc
    for (int ibc=1; ibc<=nbc; ibc++) {
      int ndman = domain->giveBc(ibc)->giveNumberOfInternalDofManagers();
      for (int idman = 1; idman <= ndman; idman ++) {
	dman = domain->giveBc(ibc)->giveInternalDofManager(idman);
	_ndofs = dman->giveNumberOfDofs();
        if ( _ndofs > bsize ) {
	  _succ = false;
	  break;
        }

        for ( i = 1; i <= _ndofs; i++ ) {
	  if ( dman->giveDof(i)->isPrimaryDof() ) {
	    _neq = dman->giveDof(i)->giveEquationNumber(s);
	    if ( _neq > 0 ) {
	      mcn [ _c++ ] = _neq - 1;
	    } else {
	      mcn [ _c++ ] = -1; // no corresponding row in sparse mtrx structure
	    }
	  }
        }

        for ( i = _ndofs + 1; i <= bsize; i++ ) {
	  mcn [ _c++ ] = -1;                         // no corresponding row in sparse mtrx structure
        }
      }
    }
    
    if ( _succ ) {
        _dss->SetMatrixPattern(_sm, bsize);
        _dss->LoadMCN(ndofmans+ndofmansbc, bsize, mcn);
    } else {
        OOFEM_LOG_INFO("DSSMatrix: using assumed block structure");
        _dss->SetMatrixPattern(_sm, bsize);
    }

    _dss->PreFactorize();
    // zero matrix, put unity on diagonal with supported dofs
    _dss->LoadZeros();
    delete[] mcn;

    OOFEM_LOG_DEBUG("DSSMatrix info: neq is %d, bsize is %d\n", neq, nz_);

    // increment version
    this->version++;

    return true;
}