SparseMtrx * PetscSparseMtrx :: GiveCopy() const { PetscSparseMtrx* answer = new PetscSparseMtrx(nRows, nColumns); if (answer) { MatDuplicate(this->mtrx, MAT_COPY_VALUES, &(answer->mtrx)); answer->symmFlag = this->symmFlag; answer->mType = this->mType; answer->leqs = this->leqs; answer->geqs = this->geqs; answer->di = this->di; answer->ut = this->ut; answer->emodel = this->emodel; answer->kspInit = false; answer->newValues= this->newValues; return answer; } else { OOFEM_FATAL("PetscSparseMtrx :: GiveCopy allocation failed"); return NULL; } }
void MMALeastSquareProjection :: __init(Domain *dold, IntArray &type, FloatArray &coords, Set &elemSet, TimeStep *tStep, bool iCohesiveZoneGP) //(Domain* dold, IntArray& varTypes, GaussPoint* gp, TimeStep* tStep) { GaussPoint *sourceIp; Element *sourceElement; SpatialLocalizer *sl = dold->giveSpatialLocalizer(); IntegrationRule *iRule; IntArray patchList; this->patchDomain = dold; // find the closest IP on old mesh sourceElement = sl->giveElementContainingPoint(coords, elemSet); if ( !sourceElement ) { OOFEM_ERROR("no suitable source element found"); } // determine the type of patch Element_Geometry_Type egt = sourceElement->giveGeometryType(); if ( egt == EGT_line_1 ) { this->patchType = MMALSPPatchType_1dq; } else if ( ( egt == EGT_triangle_1 ) || ( egt == EGT_quad_1 ) ) { this->patchType = MMALSPPatchType_2dq; } else { OOFEM_ERROR("unsupported material mode"); } /* Determine the state of closest point. * Only IP in the neighbourhood with same state can be used * to interpolate the values. */ FloatArray dam; int state = 0; if ( this->stateFilter ) { iRule = sourceElement->giveDefaultIntegrationRulePtr(); for ( GaussPoint *gp: *iRule ) { sourceElement->giveIPValue(dam, gp, IST_PrincipalDamageTensor, tStep); if ( dam.computeNorm() > 1.e-3 ) { state = 1; // damaged } } } // from source neighbours the patch will be constructed Element *element; IntArray neighborList; patchList.resize(1); patchList.at(1) = sourceElement->giveNumber(); int minNumberOfPoints = this->giveNumberOfUnknownPolynomialCoefficients(this->patchType); int actualNumberOfPoints = sourceElement->giveDefaultIntegrationRulePtr()->giveNumberOfIntegrationPoints(); int nite = 0; int elemFlag; // check if number of IP in patchList is sufficient // some recursion control would be appropriate while ( ( actualNumberOfPoints < minNumberOfPoints ) && ( nite <= 2 ) ) { //if not, construct the neighborhood dold->giveConnectivityTable()->giveElementNeighbourList(neighborList, patchList); // count number of available points patchList.clear(); actualNumberOfPoints = 0; for ( int i = 1; i <= neighborList.giveSize(); i++ ) { if ( this->stateFilter ) { element = patchDomain->giveElement( neighborList.at(i) ); // exclude elements in different regions if ( !elemSet.hasElement( element->giveNumber() ) ) { continue; } iRule = element->giveDefaultIntegrationRulePtr(); elemFlag = 0; for ( GaussPoint *gp: *iRule ) { element->giveIPValue(dam, gp, IST_PrincipalDamageTensor, tStep); if ( state && ( dam.computeNorm() > 1.e-3 ) ) { actualNumberOfPoints++; elemFlag = 1; } else if ( ( state == 0 ) && ( dam.computeNorm() < 1.e-3 ) ) { actualNumberOfPoints++; elemFlag = 1; } } if ( elemFlag ) { // include this element with corresponding state in neighbor search. patchList.followedBy(neighborList.at(i), 10); } } else { // if (! yhis->stateFilter) element = patchDomain->giveElement( neighborList.at(i) ); // exclude elements in different regions if ( !elemSet.hasElement( element->giveNumber() ) ) { continue; } actualNumberOfPoints += element->giveDefaultIntegrationRulePtr()->giveNumberOfIntegrationPoints(); patchList.followedBy(neighborList.at(i), 10); } } // end loop over neighbor list nite++; } if ( nite > 2 ) { // not enough points -> take closest point projection patchGPList.clear(); sourceIp = sl->giveClosestIP(coords, elemSet); patchGPList.push_front(sourceIp); //fprintf(stderr, "MMALeastSquareProjection: too many neighbor search iterations\n"); //exit (1); return; } #ifdef MMALSP_ONLY_CLOSEST_POINTS // select only the nval closest IP points GaussPoint **gpList = ( GaussPoint ** ) malloc(sizeof( GaussPoint * ) * actualNumberOfPoints); FloatArray dist(actualNumberOfPoints), srcgpcoords; int npoints = 0; // check allocation of gpList if ( gpList == NULL ) { OOFEM_FATAL("memory allocation error"); } for ( int ielem = 1; ielem <= patchList.giveSize(); ielem++ ) { element = patchDomain->giveElement( patchList.at(ielem) ); iRule = element->giveDefaultIntegrationRulePtr(); for ( GaussPoint *srcgp: *iRule ) { if ( element->computeGlobalCoordinates( srcgpcoords, * ( srcgp->giveNaturalCoordinates() ) ) ) { element->giveIPValue(dam, srcgp, IST_PrincipalDamageTensor, tStep); if ( this->stateFilter ) { // consider only points with same state if ( ( ( state == 1 ) && ( norm(dam) > 1.e-3 ) ) || ( ( ( state == 0 ) && norm(dam) < 1.e-3 ) ) ) { npoints++; dist.at(npoints) = coords.distance(srcgpcoords); gpList [ npoints - 1 ] = srcgp; } } else { // take all points into account npoints++; dist.at(npoints) = coords.distance(srcgpcoords); gpList [ npoints - 1 ] = srcgp; } } else { OOFEM_ERROR("computeGlobalCoordinates failed"); } } } if ( npoints != actualNumberOfPoints ) { OOFEM_ERROR("internal error"); } //minNumberOfPoints = min (actualNumberOfPoints, minNumberOfPoints+2); patchGPList.clear(); // now find the minNumberOfPoints with smallest distance // from point of interest double swap, minDist; int minDistIndx = 0; // loop over all points for ( int i = 1; i <= minNumberOfPoints; i++ ) { minDist = dist.at(i); minDistIndx = i; // search for point with i-th smallest distance for ( j = i + 1; j <= actualNumberOfPoints; j++ ) { if ( dist.at(j) < minDist ) { minDist = dist.at(j); minDistIndx = j; } } // remember this ip patchGPList.push_front(gpList [ minDistIndx - 1 ]); swap = dist.at(i); dist.at(i) = dist.at(minDistIndx); dist.at(minDistIndx) = swap; srcgp = gpList [ i - 1 ]; gpList [ i - 1 ] = gpList [ minDistIndx - 1 ]; gpList [ minDistIndx - 1 ] = srcgp; } if ( patchGPList.size() != minNumberOfPoints ) { OOFEM_ERROR("internal error 2"); exit(1); } free(gpList); #else // take all neighbors patchGPList.clear(); for ( int ielem = 1; ielem <= patchList.giveSize(); ielem++ ) { element = patchDomain->giveElement( patchList.at(ielem) ); iRule = element->giveDefaultIntegrationRulePtr(); for ( GaussPoint *gp: *iRule ) { patchGPList.push_front( gp ); } } #endif }
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; }