void Tr21Stokes :: giveIntegratedVelocity(FloatMatrix &answer, TimeStep *tStep ) { /* * Integrate velocity over element */ IntegrationRule *iRule = integrationRulesArray [ 0 ]; FloatMatrix v, v_gamma, ThisAnswer, boundaryV, Nmatrix; double detJ; FloatArray *lcoords, N; int i, j, k=0; Dof *d; GaussPoint *gp; v.resize(12,1); v.zero(); boundaryV.resize(2,1); for (i=1; i<=this->giveNumberOfDofManagers(); i++) { for (j=1; j<=this->giveDofManager(i)->giveNumberOfDofs(); j++) { d = this->giveDofManager(i)->giveDof(j); if ((d->giveDofID()==V_u) || (d->giveDofID()==V_v)) { k=k+1; v.at(k,1)=d->giveUnknown(EID_ConservationEquation, VM_Total, tStep); /*} else if (d->giveDofID()==A_x) { boundaryV.at(1,1)=d->giveUnknown(EID_ConservationEquation, VM_Total, tStep); } else if (d->giveDofID()==A_y) { boundaryV.at(2,1)=d->giveUnknown(EID_ConservationEquation, VM_Total, tStep);*/ } } } answer.resize(2,1); answer.zero(); Nmatrix.resize(2,12); for (i=0; i<iRule->getNumberOfIntegrationPoints(); i++) { gp = iRule->getIntegrationPoint(i); lcoords = gp->giveCoordinates(); this->interpolation_quad.evalN(N, *lcoords, FEIElementGeometryWrapper(this)); detJ = this->interpolation_quad.giveTransformationJacobian(*lcoords, FEIElementGeometryWrapper(this)); N.times(detJ*gp->giveWeight()); for (j=1; j<=6;j++) { Nmatrix.at(1,j*2-1)=N.at(j); Nmatrix.at(2,j*2)=N.at(j); } ThisAnswer.beProductOf(Nmatrix,v); answer.add(ThisAnswer); } }
void MatlabExportModule :: doOutputData(TimeStep *tStep, FILE *FID) { Domain *domain = emodel->giveDomain(1); std :: vector< int >DofIDList; std :: vector< int > :: iterator it; std :: vector< std :: vector< double > * >valuesList; std :: vector< double > *values; for ( int i = 1; i <= domain->giveNumberOfDofManagers(); i++ ) { for ( int j = 1; j <= domain->giveDofManager(i)->giveNumberOfDofs(); j++ ) { Dof *thisDof; thisDof = domain->giveDofManager(i)->giveDof(j); it = std :: find( DofIDList.begin(), DofIDList.end(), thisDof->giveDofID() ); if ( it == DofIDList.end() ) { DofIDList.push_back( thisDof->giveDofID() ); values = new( std :: vector< double > ); valuesList.push_back(values); } else { int pos = it - DofIDList.begin(); values = valuesList.at(pos); } double value = thisDof->giveUnknown(EID_MomentumBalance, VM_Total, tStep); values->push_back(value); } } fprintf(FID, "\tdata.DofIDs=["); for ( size_t i = 0; i < DofIDList.size(); i++ ) { fprintf( FID, "%u, ", DofIDList.at(i) ); } fprintf(FID, "];\n"); for ( size_t i = 0; i < valuesList.size(); i++ ) { fprintf(FID, "\tdata.a{%lu}=[", static_cast<long unsigned int>(i) + 1); for ( size_t j = 0; j < valuesList.at(i)->size(); j++ ) { fprintf( FID, "%f,", valuesList.at(i)->at(j) ); } fprintf(FID, "];\n"); } }
void RigidArmNode :: computeMasterContribution(std::map< DofIDItem, IntArray > &masterDofID, std::map< DofIDItem, FloatArray > &masterContribution) { #if 0 // original implementation without support of different LCS in slave and master int k; IntArray R_uvw(3), uvw(3); FloatArray xyz(3); int numberOfMasterDofs = masterNode->giveNumberOfDofs(); //IntArray countOfMasterDofs((int)masterDofID.size()); // decode of masterMask uvw.at(1) = this->dofidmask->findFirstIndexOf(R_u); uvw.at(2) = this->dofidmask->findFirstIndexOf(R_v); uvw.at(3) = this->dofidmask->findFirstIndexOf(R_w); xyz.beDifferenceOf(*this->giveCoordinates(), *masterNode->giveCoordinates()); if ( hasLocalCS() ) { // LCS is stored as global-to-local, so LCS*xyz_glob = xyz_loc xyz.rotatedWith(* this->localCoordinateSystem, 'n'); } for ( int i = 1; i <= this->dofidmask->giveSize(); i++ ) { Dof *dof = this->giveDofWithID(dofidmask->at(i)); DofIDItem id = dof->giveDofID(); masterDofID [ id ].resize(numberOfMasterDofs); masterContribution [ id ].resize(numberOfMasterDofs); R_uvw.zero(); switch ( masterMask.at(i) ) { case 0: continue; break; case 1: if ( id == D_u ) { if ( uvw.at(2) && masterMask.at( uvw.at(2) ) ) { R_uvw.at(3) = ( ( int ) R_v ); } if ( uvw.at(3) && masterMask.at( uvw.at(3) ) ) { R_uvw.at(2) = -( ( int ) R_w ); } } else if ( id == D_v ) { if ( uvw.at(1) && masterMask.at( uvw.at(1) ) ) { R_uvw.at(3) = -( ( int ) R_u ); } if ( uvw.at(3) && masterMask.at( uvw.at(3) ) ) { R_uvw.at(1) = ( ( int ) R_w ); } } else if ( id == D_w ) { if ( uvw.at(1) && masterMask.at( uvw.at(1) ) ) { R_uvw.at(2) = ( ( int ) R_u ); } if ( uvw.at(2) && masterMask.at( uvw.at(2) ) ) { R_uvw.at(1) = -( ( int ) R_v ); } } break; default: OOFEM_ERROR("unknown value in masterMask"); } //k = ++countOfMasterDofs.at(i); k = 1; masterDofID [ id ].at(k) = ( int ) id; masterContribution [ id ].at(k) = 1.0; for ( int j = 1; j <= 3; j++ ) { if ( R_uvw.at(j) != 0 ) { int sign = R_uvw.at(j) < 0 ? -1 : 1; //k = ++countOfMasterDofs.at(i); k++; masterDofID [ id ].at(k) = sign * R_uvw.at(j); masterContribution [ id ].at(k) = sign * xyz.at(j); } } masterDofID [ id ].resizeWithValues(k); masterContribution [ id ].resizeWithValues(k); } #else // receiver lcs stored in localCoordinateSystem // (this defines the transformation from global to local) FloatArray xyz(3); FloatMatrix TG2L(6,6); // receiver global to receiver local FloatMatrix TR(6,6); // rigid arm transformation between receiver global DOFs and Master global DOFs FloatMatrix TMG2L(6,6); // master global to local FloatMatrix T(6,6); // full transformation for all dofs IntArray fullDofMask = {D_u, D_v, D_w, R_u, R_v, R_w}; bool hasg2l = this->computeL2GTransformation(TG2L, fullDofMask); bool mhasg2l = masterNode->computeL2GTransformation(TMG2L, fullDofMask); xyz.beDifferenceOf(*this->giveCoordinates(), *masterNode->giveCoordinates()); TR.beUnitMatrix(); TR.at(1,5) = xyz.at(3); TR.at(1,6) = -xyz.at(2); TR.at(2,4) = -xyz.at(3); TR.at(2,6) = xyz.at(1); TR.at(3,4) = xyz.at(2); TR.at(3,5) = -xyz.at(1); if (hasg2l && mhasg2l) { FloatMatrix h; h.beTProductOf(TG2L, TR); // T transforms global master DOfs to local dofs; T.beProductOf(h,TMG2L); // Add transformation to master local c.s. } else if (hasg2l) { T.beTProductOf(TG2L, TR); // T transforms global master DOfs to local dofs; } else if (mhasg2l) { T.beProductOf(TR,TMG2L); // Add transformation to master local c.s. } else { T = TR; } // assemble DOF weights for relevant dofs for ( int i = 1; i <= this->dofidmask->giveSize(); i++ ) { Dof *dof = this->giveDofWithID(dofidmask->at(i)); DofIDItem id = dof->giveDofID(); masterDofID [ id ] = *dofidmask; masterContribution [ id ].resize(dofidmask->giveSize()); for (int j = 1; j <= this->dofidmask->giveSize(); j++ ) { masterContribution [ id ].at(j) = T.at(id, dofidmask->at(j)); } } #endif }
bool NRSolver :: checkConvergence(FloatArray &RT, FloatArray &F, FloatArray &rhs, FloatArray &ddX, FloatArray &X, double RRT, const FloatArray &internalForcesEBENorm, int nite, bool &errorOutOfRange, TimeStep *tNow) { double forceErr, dispErr; FloatArray dg_forceErr, dg_dispErr, dg_totalLoadLevel, dg_totalDisp; bool answer; EModelDefaultEquationNumbering dn; #ifdef __PARALLEL_MODE #ifdef __PETSC_MODULE PetscContext *parallel_context = engngModel->givePetscContext(this->domain->giveNumber()); Natural2LocalOrdering *n2l = parallel_context->giveN2Lmap(); #endif #endif /* * The force errors are (if possible) evaluated as relative errors. * If the norm of applied load vector is zero (one may load by temperature, etc) * then the norm of reaction forces is used in relative norm evaluation. * * Note: This is done only when all dofs are included (nccdg = 0). Not implemented if * multiple convergence criteria are used. * */ answer = true; errorOutOfRange = false; if ( internalForcesEBENorm.giveSize() > 1 ) { // Special treatment when just one norm is given; No grouping int nccdg = this->domain->giveMaxDofID(); // Keeps tracks of which dof IDs are actually in use; IntArray idsInUse(nccdg); idsInUse.zero(); // zero error norms per group dg_forceErr.resize(nccdg); dg_forceErr.zero(); dg_dispErr.resize(nccdg); dg_dispErr.zero(); dg_totalLoadLevel.resize(nccdg); dg_totalLoadLevel.zero(); dg_totalDisp.resize(nccdg); dg_totalDisp.zero(); // loop over dof managers int ndofman = domain->giveNumberOfDofManagers(); for ( int idofman = 1; idofman <= ndofman; idofman++ ) { DofManager *dofman = domain->giveDofManager(idofman); #if ( defined ( __PARALLEL_MODE ) && defined ( __PETSC_MODULE ) ) if ( !parallel_context->isLocal(dofman) ) { continue; } #endif // loop over individual dofs int ndof = dofman->giveNumberOfDofs(); for ( int idof = 1; idof <= ndof; idof++ ) { Dof *dof = dofman->giveDof(idof); if ( !dof->isPrimaryDof() ) continue; int eq = dof->giveEquationNumber(dn); int dofid = dof->giveDofID(); if ( !eq ) continue; dg_forceErr.at(dofid) += rhs.at(eq) * rhs.at(eq); dg_dispErr.at(dofid) += ddX.at(eq) * ddX.at(eq); dg_totalLoadLevel.at(dofid) += RT.at(eq) * RT.at(eq); dg_totalDisp.at(dofid) += X.at(eq) * X.at(eq); idsInUse.at(dofid) = 1; } // end loop over DOFs } // end loop over dof managers // loop over elements and their DOFs int nelem = domain->giveNumberOfElements(); for ( int ielem = 1; ielem <= nelem; ielem++ ) { Element *elem = domain->giveElement(ielem); #ifdef __PARALLEL_MODE if ( elem->giveParallelMode() != Element_local ) { continue; } #endif // loop over element internal Dofs for ( int idofman = 1; idofman <= elem->giveNumberOfInternalDofManagers(); idofman++) { DofManager *dofman = elem->giveInternalDofManager(idofman); int ndof = dofman->giveNumberOfDofs(); // loop over individual dofs for ( int idof = 1; idof <= ndof; idof++ ) { Dof *dof = dofman->giveDof(idof); if ( !dof->isPrimaryDof() ) continue; int eq = dof->giveEquationNumber(dn); int dofid = dof->giveDofID(); if ( !eq ) continue; #if ( defined ( __PARALLEL_MODE ) && defined ( __PETSC_MODULE ) ) if ( engngModel->isParallel() && !n2l->giveNewEq(eq) ) continue; #endif dg_forceErr.at(dofid) += rhs.at(eq) * rhs.at(eq); dg_dispErr.at(dofid) += ddX.at(eq) * ddX.at(eq); dg_totalLoadLevel.at(dofid) += RT.at(eq) * RT.at(eq); dg_totalDisp.at(dofid) += X.at(eq) * X.at(eq); idsInUse.at(dofid) = 1; } // end loop over DOFs } // end loop over element internal dofmans } // end loop over elements // loop over boundary conditions and their internal DOFs for ( int ibc = 1; ibc <= domain->giveNumberOfBoundaryConditions(); ibc++ ) { GeneralBoundaryCondition *bc = domain->giveBc(ibc); // loop over element internal Dofs for ( int idofman = 1; idofman <= bc->giveNumberOfInternalDofManagers(); idofman++) { DofManager *dofman = bc->giveInternalDofManager(idofman); int ndof = dofman->giveNumberOfDofs(); // loop over individual dofs for ( int idof = 1; idof <= ndof; idof++ ) { Dof *dof = dofman->giveDof(idof); if ( !dof->isPrimaryDof() ) continue; int eq = dof->giveEquationNumber(dn); int dofid = dof->giveDofID(); if ( !eq ) continue; #if ( defined ( __PARALLEL_MODE ) && defined ( __PETSC_MODULE ) ) if ( engngModel->isParallel() && !n2l->giveNewEq(eq) ) continue; #endif dg_forceErr.at(dofid) += rhs.at(eq) * rhs.at(eq); dg_dispErr.at(dofid) += ddX.at(eq) * ddX.at(eq); dg_totalLoadLevel.at(dofid) += RT.at(eq) * RT.at(eq); dg_totalDisp.at(dofid) += X.at(eq) * X.at(eq); idsInUse.at(dofid) = 1; } // end loop over DOFs } // end loop over element internal dofmans } // end loop over elements #ifdef __PARALLEL_MODE // exchange individual partition contributions (simultaneously for all groups) #ifdef __PETSC_MODULE FloatArray collectiveErr(nccdg); parallel_context->accumulate(dg_forceErr, collectiveErr); dg_forceErr = collectiveErr; parallel_context->accumulate(dg_dispErr, collectiveErr); dg_dispErr = collectiveErr; parallel_context->accumulate(dg_totalLoadLevel, collectiveErr); dg_totalLoadLevel = collectiveErr; parallel_context->accumulate(dg_totalDisp, collectiveErr); dg_totalDisp = collectiveErr; #else if ( this->engngModel->isParallel() ) { FloatArray collectiveErr(nccdg); MPI_Allreduce(dg_forceErr.givePointer(), collectiveErr.givePointer(), nccdg, MPI_DOUBLE, MPI_SUM, comm); dg_forceErr = collectiveErr; MPI_Allreduce(dg_dispErr.givePointer(), collectiveErr.givePointer(), nccdg, MPI_DOUBLE, MPI_SUM, comm); dg_dispErr = collectiveErr; MPI_Allreduce(dg_totalLoadLevel.givePointer(), collectiveErr.givePointer(), nccdg, MPI_DOUBLE, MPI_SUM, comm); dg_totalLoadLevel = collectiveErr; MPI_Allreduce(dg_totalDisp.givePointer(), collectiveErr.givePointer(), nccdg, MPI_DOUBLE, MPI_SUM, comm); dg_totalDisp = collectiveErr; return globalNorm; } #endif #endif OOFEM_LOG_INFO("NRSolver: %-5d", nite); //bool zeroNorm = false; // loop over dof groups and check convergence individually for ( int dg = 1; dg <= nccdg; dg++ ) { bool zeroFNorm = false, zeroDNorm = false; // Skips the ones which aren't used in this problem (the residual will be zero for these anyway, but it is annoying to print them all) if ( !idsInUse.at(dg) ) { continue; } OOFEM_LOG_INFO( " %s:", __DofIDItemToString((DofIDItem)dg).c_str() ); if ( rtolf.at(1) > 0.0 ) { // compute a relative error norm if ( ( dg_totalLoadLevel.at(dg) + internalForcesEBENorm.at(dg) ) > nrsolver_ERROR_NORM_SMALL_NUM ) { forceErr = sqrt( dg_forceErr.at(dg) / ( dg_totalLoadLevel.at(dg) + internalForcesEBENorm.at(dg) ) ); } else { // If both external forces and internal ebe norms are zero, then the residual must be zero. //zeroNorm = true; // Warning about this afterwards. zeroFNorm = true; forceErr = sqrt( dg_forceErr.at(dg) ); } if ( forceErr > rtolf.at(1) * NRSOLVER_MAX_REL_ERROR_BOUND ) { errorOutOfRange = true; } if ( forceErr > rtolf.at(1) ) { answer = false; } OOFEM_LOG_INFO( zeroFNorm ? " *%.3e" : " %.3e", forceErr ); } if ( rtold.at(1) > 0.0 ) { // compute displacement error if ( dg_totalDisp.at(dg) > nrsolver_ERROR_NORM_SMALL_NUM ) { dispErr = sqrt( dg_dispErr.at(dg) / dg_totalDisp.at(dg) ); } else { ///@todo This is almost always the case for displacement error. nrsolveR_ERROR_NORM_SMALL_NUM is no good. //zeroNorm = true; // Warning about this afterwards. //zeroDNorm = true; dispErr = sqrt( dg_dispErr.at(dg) ); } if ( dispErr > rtold.at(1) * NRSOLVER_MAX_REL_ERROR_BOUND ) { errorOutOfRange = true; } if ( dispErr > rtold.at(1) ) { answer = false; } OOFEM_LOG_INFO( zeroDNorm ? " *%.3e" : " %.3e", dispErr ); } } OOFEM_LOG_INFO("\n"); //if ( zeroNorm ) OOFEM_WARNING("NRSolver :: checkConvergence - Had to resort to absolute error measure (marked by *)"); } else { // No dof grouping double dXX, dXdX; if ( engngModel->giveProblemScale() == macroScale ) { OOFEM_LOG_INFO("NRSolver: %-15d", nite); } else { OOFEM_LOG_INFO(" NRSolver: %-15d", nite); } #ifdef __PARALLEL_MODE forceErr = parallel_context->norm(rhs); forceErr *= forceErr; dXX = parallel_context->localNorm(X); dXX *= dXX; // Note: Solutions are always total global values (natural distribution makes little sense for the solution) dXdX = parallel_context->localNorm(ddX); dXdX *= dXdX; #else forceErr = rhs.computeSquaredNorm(); dXX = X.computeSquaredNorm(); dXdX = ddX.computeSquaredNorm(); #endif if ( rtolf.at(1) > 0.0 ) { // we compute a relative error norm if ( ( RRT + internalForcesEBENorm.at(1) ) > nrsolver_ERROR_NORM_SMALL_NUM ) { forceErr = sqrt( forceErr / ( RRT + internalForcesEBENorm.at(1) ) ); } else { forceErr = sqrt( forceErr ); // absolute norm as last resort } if ( fabs(forceErr) > rtolf.at(1) * NRSOLVER_MAX_REL_ERROR_BOUND ) { errorOutOfRange = true; } if ( fabs(forceErr) > rtolf.at(1) ) { answer = false; } OOFEM_LOG_INFO(" %-15e", forceErr); } if ( rtold.at(1) > 0.0 ) { // compute displacement error // err is relative displacement change if ( dXX > nrsolver_ERROR_NORM_SMALL_NUM ) { dispErr = sqrt( dXdX / dXX ); } else { dispErr = sqrt( dXdX ); } if ( fabs(dispErr) > rtold.at(1) * NRSOLVER_MAX_REL_ERROR_BOUND ) { errorOutOfRange = true; } if ( fabs(dispErr) > rtold.at(1) ) { answer = false; } OOFEM_LOG_INFO(" %-15e", dispErr); } OOFEM_LOG_INFO("\n"); } // end default case (all dofs contributing) return answer; }