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(); } } }
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(); } } }
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; }
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); }
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); }
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); }
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 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; }
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; }
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; }