void BeamBaseElement :: computeLocalForceLoadVector(FloatArray &answer, TimeStep *tStep, ValueModeType mode) // computes the part of load vector, which is imposed by force loads acting // on element volume (surface). // Why is this function taken separately ? // When reactions forces are computed, they are computed from element::GiveRealStressVector // in this vector a real forces are stored (temperature part is subtracted). // so we need further subtract part corresponding to non-nodal loading. { FloatArray helpLoadVector(1); answer.clear(); // loop over body load array first int nBodyLoads = this->giveBodyLoadArray()->giveSize(); for ( int i = 1; i <= nBodyLoads; i++ ) { int id = bodyLoadArray.at(i); Load *load = domain->giveLoad(id); bcGeomType ltype = load->giveBCGeoType(); if ( ( ltype == BodyLoadBGT ) && ( load->giveBCValType() == ForceLoadBVT ) ) { this->computeBodyLoadVectorAt(helpLoadVector, load, tStep, mode); if ( helpLoadVector.giveSize() ) { answer.add(helpLoadVector); } } else { if ( load->giveBCValType() != TemperatureBVT && load->giveBCValType() != EigenstrainBVT ) { // temperature and eigenstrain is handled separately at computeLoadVectorAt subroutine OOFEM_ERROR("body load %d is of unsupported type (%d)", id, ltype); } } } // loop over boundary load array int nBoundaryLoads = this->giveBoundaryLoadArray()->giveSize() / 2; for ( int i = 1; i <= nBoundaryLoads; i++ ) { int n = boundaryLoadArray.at(1 + ( i - 1 ) * 2); int id = boundaryLoadArray.at(i * 2); Load *load = domain->giveLoad(n); BoundaryLoad* bLoad; if ((bLoad = dynamic_cast<BoundaryLoad*> (load))) { bcGeomType ltype = load->giveBCGeoType(); if ( ltype == EdgeLoadBGT ) { this->computeBoundaryEdgeLoadVector(helpLoadVector, bLoad, id, ExternalForcesVector, mode, tStep, false); if ( helpLoadVector.giveSize() ) { answer.add(helpLoadVector); } } else if ( ltype == SurfaceLoadBGT ) { this->computeBoundarySurfaceLoadVector(helpLoadVector, bLoad, id, ExternalForcesVector, mode, tStep, false); if ( helpLoadVector.giveSize() ) { answer.add(helpLoadVector); } } else if ( ltype == PointLoadBGT ) { // id not used this->computePointLoadVectorAt(helpLoadVector, load, tStep, mode, false); if ( helpLoadVector.giveSize() ) { answer.add(helpLoadVector); } } else { OOFEM_ERROR("boundary load %d is of unsupported type (%d)", id, ltype); } } } // add exact end forces due to nonnodal loading applied indirectly (via sets) BCTracker *bct = this->domain->giveBCTracker(); BCTracker::entryListType bcList = bct->getElementRecords(this->number); FloatArray help; for (BCTracker::entryListType::iterator it = bcList.begin(); it != bcList.end(); ++it) { GeneralBoundaryCondition *bc = this->domain->giveBc((*it).bcNumber); BodyLoad *bodyLoad; BoundaryLoad *boundaryLoad; if (bc->isImposed(tStep)) { if ((bodyLoad = dynamic_cast<BodyLoad*>(bc))) { // body load this->computeBodyLoadVectorAt(help,bodyLoad, tStep, VM_Total); // this one is local answer.add(help); } else if ((boundaryLoad = dynamic_cast<BoundaryLoad*>(bc))) { // compute Boundary Edge load vector in GLOBAL CS !!!!!!! this->computeBoundaryEdgeLoadVector(help, boundaryLoad, (*it).boundaryId, ExternalForcesVector, VM_Total, tStep, false); // get it transformed back to local c.s. // this->computeGtoLRotationMatrix(t); // help.rotatedWith(t, 'n'); answer.add(help); } } } }
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."); } }