void NonLinearStatic :: showSparseMtrxStructure(int type, oofegGraphicContext &gc, TimeStep *tStep) { Domain *domain = this->giveDomain(1); CharType ctype; if ( type != 1 ) { return; } if ( stiffMode == nls_tangentStiffness ) { ctype = TangentStiffnessMatrix; } else if ( stiffMode == nls_secantStiffness ) { ctype = SecantStiffnessMatrix; } else { ctype = SecantStiffnessMatrix; } for ( auto &elem : domain->giveElements() ) { elem->showSparseMtrxStructure(ctype, gc, tStep); } for ( auto &elem : domain->giveElements() ) { elem->showExtendedSparseMtrxStructure(ctype, gc, tStep); } }
void MatlabExportModule :: doOutputMesh(TimeStep *tStep, FILE *FID) { Domain *domain = emodel->giveDomain(1); fprintf(FID, "\tmesh.p=["); for ( auto &dman : domain->giveDofManagers() ) { for ( int j = 1; j <= domain->giveNumberOfSpatialDimensions(); j++) { double c = dman->giveCoordinate(j); fprintf(FID, "%f, ", c); } fprintf(FID, "; "); } fprintf(FID, "]';\n"); int numberOfDofMans=domain->giveElement(1)->giveNumberOfDofManagers(); fprintf(FID, "\tmesh.t=["); for ( auto &elem : domain->giveElements() ) { if ( elem->giveNumberOfDofManagers() == numberOfDofMans ) { for ( int j = 1; j <= elem->giveNumberOfDofManagers(); j++ ) { fprintf( FID, "%d,", elem->giveDofManagerNumber(j) ); } } fprintf(FID, ";"); } fprintf(FID, "]';\n"); }
TimeStep * CBS :: giveNextStep() { double dt = deltaT; if ( !currentStep ) { // first step -> generate initial step currentStep.reset( new TimeStep( *giveSolutionStepWhenIcApply() ) ); } previousStep = std :: move(currentStep); Domain *domain = this->giveDomain(1); // check for critical time step for ( auto &elem : domain->giveElements() ) { dt = min( dt, static_cast< CBSElement & >( *elem ).computeCriticalTimeStep(previousStep.get()) ); } dt *= 0.6; dt = max(dt, minDeltaT); dt /= this->giveVariableScale(VST_Time); currentStep.reset( new TimeStep(*previousStep, dt) ); OOFEM_LOG_INFO( "SolutionStep %d : t = %e, dt = %e\n", currentStep->giveNumber(), currentStep->giveTargetTime() * this->giveVariableScale(VST_Time), dt * this->giveVariableScale(VST_Time) ); return currentStep.get(); }
// needed for CemhydMat void NonStationaryTransportProblem :: averageOverElements(TimeStep *tStep) { ///@todo Verify this, the function is completely unused. Domain *domain = this->giveDomain(1); FloatArray vecTemperature; for ( auto &elem : domain->giveElements() ) { TransportMaterial *mat = dynamic_cast< CemhydMat * >( elem->giveMaterial() ); if ( mat ) { for ( GaussPoint *gp: *elem->giveDefaultIntegrationRulePtr() ) { elem->giveIPValue(vecTemperature, gp, IST_Temperature, tStep); //mat->IP_volume += dV; //mat->average_temp += vecState.at(1) * dV; } } } for ( auto &mat : domain->giveMaterials() ) { CemhydMat *cem = dynamic_cast< CemhydMat * >( mat.get() ); if ( cem ) { //cem->average_temp /= mat->IP_volume; } } }
void NonLinearDynamic :: showSparseMtrxStructure(int type, oofegGraphicContext &gc, TimeStep *tStep) { Domain *domain = this->giveDomain(1); CharType ctype; if ( type != 1 ) { return; } ctype = TangentStiffnessMatrix; for ( auto &elem : domain->giveElements() ) { elem->showSparseMtrxStructure(ctype, gc, tStep); } for ( auto &elem : domain->giveElements() ) { elem->showExtendedSparseMtrxStructure(ctype, gc, tStep); } }
void StructuralEngngModel :: showSparseMtrxStructure(int type, oofegGraphicContext &gc, TimeStep *tStep) { Domain *domain = this->giveDomain(1); if ( type != 1 ) { return; } for ( auto &elem : domain->giveElements() ) { elem->showSparseMtrxStructure(TangentStiffnessMatrix, gc, tStep); } }
int StokesFlow :: checkConsistency() { Domain *domain = this->giveDomain(1); // check for proper element type for ( auto &elem : domain->giveElements() ) { if ( dynamic_cast< FMElement * >( elem.get() ) == NULL ) { OOFEM_WARNING("Element %d has no FMElement base", elem->giveLabel()); return false; } } return EngngModel :: checkConsistency(); }
void NLTransientTransportProblem :: applyIC(TimeStep *stepWhenIcApply) { Domain *domain = this->giveDomain(1); NonStationaryTransportProblem :: applyIC(stepWhenIcApply); // update element state according to given ic for ( auto &elem : domain->giveElements() ) { TransportElement *element = static_cast< TransportElement * >( elem.get() ); element->updateInternalState(stepWhenIcApply); element->updateYourself(stepWhenIcApply); } }
void CBS :: applyIC(TimeStep *stepWhenIcApply) { Domain *domain = this->giveDomain(1); int mbneq = this->giveNumberOfDomainEquations(1, vnum); int pdneq = this->giveNumberOfDomainEquations(1, pnum); FloatArray *velocityVector, *pressureVector; #ifdef VERBOSE OOFEM_LOG_INFO("Applying initial conditions\n"); #endif VelocityField.advanceSolution(stepWhenIcApply); velocityVector = VelocityField.giveSolutionVector(stepWhenIcApply); velocityVector->resize(mbneq); velocityVector->zero(); PressureField.advanceSolution(stepWhenIcApply); pressureVector = PressureField.giveSolutionVector(stepWhenIcApply); pressureVector->resize(pdneq); pressureVector->zero(); for ( auto &node : domain->giveDofManagers() ) { for ( Dof *iDof: *node ) { // ask for initial values obtained from // bc (boundary conditions) and ic (initial conditions) if ( !iDof->isPrimaryDof() ) { continue; } int jj = iDof->__giveEquationNumber(); if ( jj ) { DofIDItem type = iDof->giveDofID(); if ( ( type == V_u ) || ( type == V_v ) || ( type == V_w ) ) { velocityVector->at(jj) = iDof->giveUnknown(VM_Total, stepWhenIcApply); } else { pressureVector->at(jj) = iDof->giveUnknown(VM_Total, stepWhenIcApply); } } } } // update element state according to given ic for ( auto &elem : domain->giveElements() ) { CBSElement *element = static_cast< CBSElement * >( elem.get() ); element->updateInternalState(stepWhenIcApply); element->updateYourself(stepWhenIcApply); } }
void NonlocalMaterialExtensionInterface :: updateDomainBeforeNonlocAverage(TimeStep *tStep) { Domain *d = this->giveDomain(); if ( d->giveNonlocalUpdateStateCounter() == tStep->giveSolutionStateCounter() ) { return; // already updated } for ( auto &elem : d->giveElements() ) { elem->updateBeforeNonlocalAverage(tStep); } // mark last update counter to prevent multiple updates d->setNonlocalUpdateStateCounter( tStep->giveSolutionStateCounter() ); }
int CBS :: checkConsistency() { // check internal consistency // if success returns nonzero Domain *domain = this->giveDomain(1); // check for proper element type for ( auto &elem : domain->giveElements() ) { if ( !dynamic_cast< CBSElement * >( elem.get() ) ) { OOFEM_WARNING("Element %d has no CBS base", elem->giveLabel()); return 0; } } EngngModel :: checkConsistency(); // scale boundary and initial conditions if ( equationScalingFlag ) { for ( auto &bc: domain->giveBcs() ) { if ( bc->giveBCValType() == VelocityBVT ) { bc->scale(1. / uscale); } else if ( bc->giveBCValType() == PressureBVT ) { bc->scale( 1. / this->giveVariableScale(VST_Pressure) ); } else if ( bc->giveBCValType() == ForceLoadBVT ) { bc->scale( 1. / this->giveVariableScale(VST_Force) ); } else { OOFEM_WARNING("unknown bc/ic type"); return 0; } } for ( auto &ic : domain->giveIcs() ) { if ( ic->giveICValType() == VelocityBVT ) { ic->scale(VM_Total, 1. / uscale); } else if ( ic->giveICValType() == PressureBVT ) { ic->scale( VM_Total, 1. / this->giveVariableScale(VST_Pressure) ); } else { OOFEM_WARNING("unknown bc/ic type"); return 0; } } } return 1; }
void TransientTransportProblem :: applyIC() { Domain *domain = this->giveDomain(1); OOFEM_LOG_INFO("Applying initial conditions\n"); this->field->applyDefaultInitialCondition(); ///@todo It's rather strange that the models need the initial values. // update element state according to given ic TimeStep *s = this->giveSolutionStepWhenIcApply(); for ( auto &elem : domain->giveElements() ) { TransportElement *element = static_cast< TransportElement * >( elem.get() ); element->updateInternalState(s); element->updateYourself(s); } }
void GnuplotExportModule::outputMesh(Domain &iDomain) { std::vector< std::vector<FloatArray> > pointArray; if(iDomain.giveNumberOfSpatialDimensions() == 2) { // Write all element edges to gnuplot for ( auto &el : iDomain.giveElements() ) { int numEdges = el->giveNumberOfNodes(); for ( int edgeIndex = 1; edgeIndex <= numEdges; edgeIndex++ ) { std::vector<FloatArray> points; IntArray bNodes; el->giveInterpolation()->boundaryGiveNodes(bNodes, edgeIndex); int niLoc = bNodes.at(1); const FloatArray &xS = *(el->giveNode(niLoc)->giveCoordinates() ); points.push_back(xS); int njLoc = bNodes.at( bNodes.giveSize() ); const FloatArray &xE = *(el->giveNode(njLoc)->giveCoordinates() ); points.push_back(xE); pointArray.push_back(points); } } double time = 0.0; TimeStep *ts = emodel->giveCurrentStep(); if ( ts != NULL ) { time = ts->giveTargetTime(); } std :: stringstream strMesh; strMesh << "MeshGnuplotTime" << time << ".dat"; std :: string nameMesh = strMesh.str(); WritePointsToGnuplot(nameMesh, pointArray); } }
void StokesFlowVelocityHomogenization :: computeTangent(FloatMatrix &answer, TimeStep *tStep) { IntArray loc, col; Domain *domain = this->giveDomain(1); int nsd = domain->giveNumberOfSpatialDimensions(); int ndof = this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); // Build F matrix IntArray dofs(nsd); for ( int i = 0; i < nsd; ++i ) { dofs[i] = V_u + i; ///@todo This is a hack. We should have these as user input instead. } FloatMatrix F(ndof, nsd), Fe, N; col.enumerate(nsd); for ( auto &elem : domain->giveElements() ) { this->integrateNMatrix(N, *elem, tStep); elem->giveLocationArray( loc, dofs, EModelDefaultEquationNumbering() ); Fe.beTranspositionOf(N); F.assemble(Fe, loc, col); } FloatMatrix H; std :: unique_ptr< SparseLinearSystemNM > solver( classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this) ); H.resize( F.giveNumberOfRows(), F.giveNumberOfColumns() ); H.zero(); // For correct homogenization, the tangent at the converged values should be used // (the one from the Newton iterations from solveYourselfAt is not updated to contain the latest values). SparseMtrxType stype = solver->giveRecommendedMatrix(true); std :: unique_ptr< SparseMtrx > Kff( classFactory.createSparseMtrx( stype ) ); Kff->buildInternalStructure(this, domain->giveNumber(), EModelDefaultEquationNumbering() ); this->assemble(*Kff, tStep, TangentStiffnessMatrix, EModelDefaultEquationNumbering(), domain); solver->solve(*Kff, F, H); answer.beTProductOf(H, F); answer.times( 1. / this->giveAreaOfRVE() ); }
int NonStationaryTransportProblem :: checkConsistency() { // check internal consistency // if success returns nonzero Domain *domain = this->giveDomain(1); // check for proper element type for ( auto &elem : domain->giveElements() ) { if ( !dynamic_cast< TransportElement * >( elem.get() ) ) { OOFEM_WARNING("Element %d has no TransportElement base", elem->giveLabel()); return 0; } } EngngModel :: checkConsistency(); return 1; }
int StructuralEngngModel :: checkConsistency() { Domain *domain = this->giveDomain(1); // check for proper element type for ( auto &elem : domain->giveElements() ) { StructuralElement *sePtr = dynamic_cast< StructuralElement * >( elem.get() ); StructuralInterfaceElement *siePtr = dynamic_cast< StructuralInterfaceElement * >( elem.get() ); StructuralElementEvaluator *see = dynamic_cast< StructuralElementEvaluator * >( elem.get() ); if ( sePtr == NULL && see == NULL && siePtr == NULL ) { OOFEM_WARNING("Element %d has no structural support", elem->giveLabel()); return 0; } } EngngModel :: checkConsistency(); return 1; }
TimeStep * SUPG :: giveNextStep() { double dt = deltaT; Domain *domain = this->giveDomain(1); if ( !currentStep ) { // first step -> generate initial step currentStep.reset( new TimeStep( *giveSolutionStepWhenIcApply() ) ); } previousStep = std :: move(currentStep); if ( deltaTF ) { dt *= domain->giveFunction(deltaTF)->evaluateAtTime(previousStep->giveNumber() + 1); } // check for critical time step for ( auto &elem : domain->giveElements() ) { dt = min( dt, static_cast< SUPGElement & >( *elem ).computeCriticalTimeStep(previousStep.get()) ); } if ( materialInterface ) { dt = min( dt, materialInterface->computeCriticalTimeStep(previousStep.get()) ); } // dt *= 0.6; dt /= this->giveVariableScale(VST_Time); currentStep.reset( new TimeStep(*previousStep, dt) ); OOFEM_LOG_INFO( "SolutionStep %d : t = %e, dt = %e\n", currentStep->giveNumber(), currentStep->giveTargetTime() * this->giveVariableScale(VST_Time), dt * this->giveVariableScale(VST_Time) ); return currentStep.get(); }
void GPExportModule :: doOutput(TimeStep *tStep, bool forcedOutput) { if ( !testTimeStepOutput(tStep) ) { return; } double weight; FloatArray gcoords, intvar; Domain *d = emodel->giveDomain(1); FILE *stream = this->giveOutputStream(tStep); // print the header fprintf(stream, "%%# gauss point data file\n"); fprintf(stream, "%%# output for time %g\n", tStep->giveTargetTime() ); fprintf(stream, "%%# variables: "); fprintf(stream, "%d ", vartypes.giveSize()); for ( auto &vartype : vartypes ) { fprintf( stream, "%d ", vartype ); } fprintf(stream, "\n %%# for interpretation see internalstatetype.h\n"); // loop over elements for ( auto &elem : d->giveElements() ) { //iRule = elem->giveDefaultIntegrationRulePtr(); //int numIntRules = elem->giveNumberOfIntegrationRules(); for ( int i = 0; i < elem->giveNumberOfIntegrationRules(); i++ ) { IntegrationRule *iRule = elem->giveIntegrationRule(i); // loop over Gauss points for ( GaussPoint *gp: *iRule ) { // export: // 1) element number // 2) material number ///@todo deprecated returns -1 // 3) Integration rule number // 4) Gauss point number // 5) contributing volume around Gauss point weight = elem->computeVolumeAround(gp); fprintf(stream, "%d %d %d %d %.6e ", elem->giveNumber(), -1, i + 1, gp->giveNumber(), weight); // export Gauss point coordinates if ( ncoords ) { // no coordinates exported if ncoords==0 elem->computeGlobalCoordinates( gcoords, gp->giveNaturalCoordinates() ); int nc = gcoords.giveSize(); if ( ncoords >= 0 ) { fprintf(stream, "%d ", ncoords); } else { fprintf(stream, "%d ", nc); } if ( ncoords > 0 && ncoords < nc ) { nc = ncoords; } for ( auto &c : gcoords ) { fprintf( stream, "%.6e ", c ); } for ( int ic = nc + 1; ic <= ncoords; ic++ ) { fprintf(stream, "%g ", 0.0); } } // export internal variables for ( auto vartype : vartypes ) { elem->giveIPValue(intvar, gp, ( InternalStateType )vartype, tStep); fprintf(stream, "%d ", intvar.giveSize()); for ( auto &val : intvar ) { fprintf( stream, "%.6e ", val ); } } fprintf(stream, "\n"); } } #if 0 // for CST elements write also nodal coordinates // (non-standard part, used only exceptionally) int nnode = elem->giveNumberOfNodes(); if ( nnode == 3 ) { for ( int inod = 1; inod <= 3; inod++ ) { fprintf( stream, "%f %f ", elem->giveNode(inod)->giveCoordinate(1), elem->giveNode(inod)->giveCoordinate(2) ); } } #endif } fclose(stream); }
void TransientTransportProblem :: solveYourselfAt(TimeStep *tStep) { Domain *d = this->giveDomain(1); int neq = this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); if ( tStep->isTheFirstStep() ) { this->applyIC(); } field->advanceSolution(tStep); #if 1 // This is what advanceSolution should be doing, but it can't be there yet // (backwards compatibility issues due to inconsistencies in other solvers). TimeStep *prev = tStep->givePreviousStep(); for ( auto &dman : d->giveDofManagers() ) { static_cast< DofDistributedPrimaryField* >(field.get())->setInitialGuess(*dman, tStep, prev); } for ( auto &elem : d->giveElements() ) { int ndman = elem->giveNumberOfInternalDofManagers(); for ( int i = 1; i <= ndman; i++ ) { static_cast< DofDistributedPrimaryField* >(field.get())->setInitialGuess(*elem->giveInternalDofManager(i), tStep, prev); } } for ( auto &bc : d->giveBcs() ) { int ndman = bc->giveNumberOfInternalDofManagers(); for ( int i = 1; i <= ndman; i++ ) { static_cast< DofDistributedPrimaryField* >(field.get())->setInitialGuess(*bc->giveInternalDofManager(i), tStep, prev); } } #endif field->applyBoundaryCondition(tStep); field->initialize(VM_Total, tStep, solution, EModelDefaultEquationNumbering()); if ( !effectiveMatrix ) { effectiveMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); effectiveMatrix->buildInternalStructure( this, 1, EModelDefaultEquationNumbering() ); if ( lumped ) { capacityDiag.resize(neq); this->assembleVector( capacityDiag, tStep, LumpedMassVectorAssembler(), VM_Total, EModelDefaultEquationNumbering(), d ); } else { capacityMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); capacityMatrix->buildInternalStructure( this, 1, EModelDefaultEquationNumbering() ); this->assemble( *capacityMatrix, tStep, MassMatrixAssembler(), EModelDefaultEquationNumbering(), d ); } if ( this->keepTangent ) { this->assemble( *effectiveMatrix, tStep, TangentAssembler(TangentStiffness), EModelDefaultEquationNumbering(), d ); effectiveMatrix->times(alpha); if ( lumped ) { effectiveMatrix->addDiagonal(1./tStep->giveTimeIncrement(), capacityDiag); } else { effectiveMatrix->add(1./tStep->giveTimeIncrement(), *capacityMatrix); } } } OOFEM_LOG_INFO("Assembling external forces\n"); FloatArray externalForces(neq); externalForces.zero(); this->assembleVector( externalForces, tStep, ExternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), d ); this->updateSharedDofManagers(externalForces, EModelDefaultEquationNumbering(), LoadExchangeTag); // set-up numerical method this->giveNumericalMethod( this->giveCurrentMetaStep() ); OOFEM_LOG_INFO("Solving for %d unknowns...\n", neq); internalForces.resize(neq); FloatArray incrementOfSolution; double loadLevel; int currentIterations; this->nMethod->solve(*this->effectiveMatrix, externalForces, NULL, // ignore NULL, this->solution, incrementOfSolution, this->internalForces, this->eNorm, loadLevel, // ignore SparseNonLinearSystemNM :: rlm_total, // ignore currentIterations, // ignore tStep); }
void MatlabExportModule :: computeArea(TimeStep *tStep) { Domain *domain = emodel->giveDomain(1); smax.clear(); smin.clear(); for (int i=1; i<=domain->giveNumberOfSpatialDimensions(); i++) { smax.push_back(domain->giveDofManager(1)->giveCoordinate(i)); smin.push_back(domain->giveDofManager(1)->giveCoordinate(i)); } for ( int i = 0; i < domain->giveNumberOfDofManagers(); i++ ) { for (int j=0; j < domain->giveNumberOfSpatialDimensions(); j++) { smax.at(j)=max(smax.at(j), domain->giveDofManager(i+1)->giveCoordinate(j+1)); smin.at(j)=min(smin.at(j), domain->giveDofManager(i+1)->giveCoordinate(j+1)); } } Area=0; Volume=0; if ( domain->giveNumberOfSpatialDimensions() == 2 ) { for ( auto &elem : domain->giveElements() ) { Area = Area + elem->computeArea(); } } else { for (size_t i = 0; i<partVolume.size(); i++ ) { partVolume.at(i)=0.0; } for ( auto &elem : domain->giveElements() ) { // double v; #ifdef __SM_MODULE if ( NLStructuralElement *e = dynamic_cast< NLStructuralElement *>( elem.get() ) ) { v = e->computeCurrentVolume(tStep); } else { #endif v = elem->computeVolume(); #ifdef __SM_MODULE } #endif std :: string eName ( elem->giveClassName() ); int j = -1; //printf("%s\n", eName.c_str()); for ( size_t k = 0; k < partName.size(); k++ ) { //printf("partName.at(%u) = %s\n", k, partName.at(k).c_str() ); if ( eName.compare(partName.at(k)) == 0 ) { j = k; break; } } if ( j == -1 ) { partName.push_back( elem->giveClassName() ); partVolume.push_back( v ); j = partVolume.size()-1; } else { partVolume.at(j) = partVolume.at(j) + v; } Volume = Volume + v; } } }
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 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; }
void NonStationaryTransportProblem :: applyIC(TimeStep *stepWhenIcApply) { Domain *domain = this->giveDomain(1); int neq = this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); FloatArray *solutionVector; double val; #ifdef VERBOSE OOFEM_LOG_INFO("Applying initial conditions\n"); #endif UnknownsField->advanceSolution(stepWhenIcApply); solutionVector = UnknownsField->giveSolutionVector(stepWhenIcApply); solutionVector->resize(neq); solutionVector->zero(); for ( auto &node : domain->giveDofManagers() ) { for ( Dof *dof: *node ) { // ask for initial values obtained from // bc (boundary conditions) and ic (initial conditions) if ( !dof->isPrimaryDof() ) { continue; } int jj = dof->__giveEquationNumber(); if ( jj ) { val = dof->giveUnknown(VM_Total, stepWhenIcApply); solutionVector->at(jj) = val; //update in dictionary, if the problem is growing/decreasing if ( this->changingProblemSize ) { dof->updateUnknownsDictionary(stepWhenIcApply, VM_Total, val); } } } } //project initial temperature to integration points // for ( int j = 1; j <= nelem; j++ ) { // domain->giveElement(j)->updateInternalState(stepWhenIcApply); // } #ifdef __CEMHYD_MODULE // Not relevant in linear case, but needed for CemhydMat for temperature averaging before solving balance equations // Update element state according to given ic for ( auto &elem : domain->giveElements() ) { TransportElement *element = static_cast< TransportElement * >( elem.get() ); CemhydMat *cem = dynamic_cast< CemhydMat * >( element->giveMaterial() ); //assign status to each integration point on each element if ( cem ) { cem->initMaterial(element); //create microstructures and statuses on specific GPs element->updateInternalState(stepWhenIcApply); //store temporary unequilibrated temperature element->updateYourself(stepWhenIcApply); //store equilibrated temperature cem->clearWeightTemperatureProductVolume(element); cem->storeWeightTemperatureProductVolume(element, stepWhenIcApply); } } //perform averaging on each material instance of CemhydMatClass for ( auto &mat : domain->giveMaterials() ) { CemhydMat *cem = dynamic_cast< CemhydMat * >( mat.get() ); if ( cem ) { cem->averageTemperature(); } } #endif //__CEMHYD_MODULE }