void TreeLattice<Impl>::partialRollback(DiscretizedAsset& asset, Time to) const { Time from = asset.time(); if (close(from,to)) return; QL_REQUIRE(from > to, "cannot roll the asset back to" << to << " (it is already at t = " << from << ")"); Integer iFrom = Integer(t_.index(from)); Integer iTo = Integer(t_.index(to)); for (Integer i=iFrom-1; i>=iTo; --i) { Array newValues(this->impl().size(i)); this->impl().stepback(i, asset.values(), newValues); asset.time() = t_[i]; asset.values() = newValues; // skip the very last adjustment if (i != iTo) asset.adjustValues(); } }
void fixedMeanFvPatchField<Type>::updateCoeffs() { if (this->updated()) { return; } gpuField<Type> newValues(this->patchInternalField()); Type meanValuePsi = gSum(this->patch().magSf()*newValues) /gSum(this->patch().magSf()); if (mag(meanValue_) > SMALL && mag(meanValuePsi)/mag(meanValue_) > 0.5) { newValues *= mag(meanValue_)/mag(meanValuePsi); } else { newValues += (meanValue_ - meanValuePsi); } this->operator==(newValues); fixedValueFvPatchField<Type>::updateCoeffs(); }
TableFunction *Bucket::FastCondition(const list<int> &ordering, const Assignment &cond) { if (functions.size() == 0) return new TableFunction(); Scope newDomain; for (unsigned int i = 0; i < functions.size(); ++i) { newDomain = newDomain + functions[i]->GetScope(); } newDomain = newDomain - cond; newDomain.SetOrdering(ordering); unsigned int card = newDomain.GetCard(); vector<double> newValues(card, 1); Assignment a(newDomain); a.SetAllVal(0); int idx = 0; unsigned int ii = cond.GetVal(cond.GetOrdering().back()); do { assert(idx < int(card)); for (unsigned int i = 0; i < functions.size(); ++i) { newValues[idx] *= functions[i]->GetValElim(a, ii); } idx++; } while (a.Iterate()); assert(newValues.size() == newDomain.GetCard()); TableFunction *message = new TableFunction(newDomain, newValues); return message; }
/** * Simulates a lineage splitting into two. (IE, the opposite of coalescing). * @param splitType The type to split. * @return A new R after this split. */ R split(int splitType) { ValueArray newValues(values); if (splitType != dims) newValues[splitType] += 1; return R(n+1,newValues); }
void toPieChart::setValues(std::list<double> &values, std::list<QString> &labels) { Values = values; Labels = labels; emit newValues(values, labels); update(); }
/** * Simulates coalescing two of the lineages into one. * @param coalesceType The type to coalesce. * @return A new R after coalesing. */ R coalesce(int coalesceType) { ValueArray newValues(values); if (coalesceType != dims) newValues[coalesceType] -=1; return R(n-1,newValues); }
/** * Simulates a mutation from the fromType to the toType. * @param fromType The source lineage type. * @param toType The destination lineage type. * @return A new R representing after the mutation. */ R transition(int fromType, int toType) { ValueArray newValues(values); if (fromType != dims) newValues[fromType] -=1; if (toType != dims) newValues[toType] += 1; return R(n,newValues); }
void KernelEstimator::addValue(double data, const double weight) { if (weight == 0) { return; } data = round(data); int insertIndex = findNearestValue(data); if ((mNumValues <= insertIndex) || (mValues[insertIndex] != data)) { if (mNumValues < mValues.size()) { int left = mNumValues - insertIndex; std::cout << "Please cross-check here for array copy"; std::copy(mValues.begin() + insertIndex, mValues.begin() + left, mValues.begin() + insertIndex + 1); std::copy(mWeights.begin() + insertIndex, mWeights.begin() + left, mWeights.begin() + insertIndex + 1); mValues[insertIndex] = data; mWeights[insertIndex] = weight; mNumValues++; } else { double_array newValues(mValues.size() * 2); double_array newWeights(mValues.size() * 2); int left = mNumValues - insertIndex; std::copy(mValues.begin(), mValues.begin() + insertIndex, newValues.begin()); std::copy(mWeights.begin(), mWeights.begin() + insertIndex, newWeights.begin()); newValues[insertIndex] = data; newWeights[insertIndex] = weight; std::copy(mValues.begin() + insertIndex, mValues.begin() + left, newValues.begin() + insertIndex + 1); std::copy(mWeights.begin() + insertIndex, mWeights.begin() + left, newWeights.begin() + insertIndex + 1); mNumValues++; mValues = newValues; mWeights = newWeights; } if (weight != 1) { mAllWeightsOne = false; } } else { mWeights[insertIndex] += weight; mAllWeightsOne = false; } mSumOfWeights += weight; double range = mValues[mNumValues - 1] - mValues[0]; if (range > 0) { mStandardDev = std::fmax(range / sqrt(mSumOfWeights), mPrecision / (2 * 3)); // allow at most 3 sds within one interval } }
void SampledCurve::regrid(const Array &new_grid) { CubicInterpolation priceSpline(grid_.begin(), grid_.end(), values_.begin(), CubicInterpolation::Spline, false, CubicInterpolation::SecondDerivative, 0.0, CubicInterpolation::SecondDerivative, 0.0); priceSpline.update(); Array newValues(new_grid.size()); Array::iterator val; Array::const_iterator grid; for (val = newValues.begin(), grid = new_grid.begin() ; grid != new_grid.end(); ++val, ++grid) { *val = priceSpline(*grid, true); } values_.swap(newValues); grid_ = new_grid; }
TableFunction *Bucket::FastSumElimination(const list<int> &ordering, const Scope &elimVar) { if (functions.size() == 0) return new TableFunction(); Scope newDomain; for (unsigned int i = 0; i < functions.size(); ++i) { newDomain = newDomain + functions[i]->GetScope(); } newDomain = newDomain - elimVar; newDomain.SetOrdering(ordering); unsigned int card = newDomain.GetCard(); vector<double> newValues(card, 0); Assignment a(newDomain); Assignment e(elimVar); a.SetAllVal(0); e.SetAllVal(0); /* vector<Assignment> fAssign; for (unsigned int i = 0; i < functions.size(); ++i) { fAssign.push_back(Assignment(functions[i]->GetScope())); } */ int idx = 0; do { for (unsigned int ii = 0; ii < e.GetCard(); ++ii) { double combVal = 1; for (unsigned int i = 0; i < functions.size(); ++i) { /* fAssign[i].SetAssign(a); fAssign[i].SetAssign(e); */ combVal *= functions[i]->GetValElim(a, ii); } newValues[idx] += combVal; } idx++; } while (a.Iterate()); assert(newValues.size() == newDomain.GetCard()); TableFunction *message = new TableFunction(newDomain, newValues); return message; }
ErrorCode Intx2MeshOnSphere::update_tracer_data(EntityHandle out_set, Tag & tagElem, Tag & tagArea) { EntityHandle dum = 0; Tag corrTag; ErrorCode rval = mb->tag_get_handle(CORRTAGNAME, 1, MB_TYPE_HANDLE, corrTag, MB_TAG_DENSE, &dum); // it should have been created ERRORR(rval, "can't get correlation tag"); Tag gid; rval = mb->tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, gid, MB_TAG_DENSE); ERRORR(rval,"can't get global ID tag" ); // get all polygons out of out_set; then see where are they coming from Range polys; rval = mb->get_entities_by_dimension(out_set, 2, polys); ERRORR(rval, "can't get polygons out"); // rs2 is the red range, arrival; rs1 is blue, departure; // there is a connection between rs1 and rs2, through the corrTag // corrTag is __correlation // basically, mb->tag_get_data(corrTag, &(redPoly), 1, &bluePoly); // also, mb->tag_get_data(corrTag, &(bluePoly), 1, &redPoly); // we start from rs2 existing, then we have to update something std::vector<double> currentVals(rs2.size()); rval = mb->tag_get_data(tagElem, rs2, ¤tVals[0]); ERRORR(rval, "can't get existing tag values"); // for each polygon, we have 2 indices: red and blue parents // we need index blue to update index red? std::vector<double> newValues(rs2.size(), 0.);// initialize with 0 all of them // area of the polygon * conc on red (old) current quantity // finaly, divide by the area of the red double check_intx_area=0.; for (Range::iterator it= polys.begin(); it!=polys.end(); it++) { EntityHandle poly=*it; int blueIndex, redIndex; rval = mb->tag_get_data(blueParentTag, &poly, 1, &blueIndex); ERRORR(rval, "can't get blue tag"); EntityHandle blue = rs1[blueIndex]; rval = mb->tag_get_data(redParentTag, &poly, 1, &redIndex); ERRORR(rval, "can't get red tag"); //EntityHandle red = rs2[redIndex]; // big assumption here, red and blue are "parallel" ;we should have an index from // blue to red (so a deformed blue corresponds to an arrival red) double areap = area_spherical_element(mb, poly, R); check_intx_area+=areap; // so the departure cell at time t (blueIndex) covers a portion of a redCell // that quantity will be transported to the redCell at time t+dt // the blue corresponds to a red arrival EntityHandle redArr; rval = mb->tag_get_data(corrTag, &blue, 1, &redArr); if (0==redArr || MB_TAG_NOT_FOUND==rval) { if (!remote_cells) ERRORR( MB_FAILURE, "no remote cells, failure\n"); // maybe the element is remote, from another processor int global_id_blue; rval = mb->tag_get_data(gid, &blue, 1, &global_id_blue); ERRORR(rval, "can't get arrival red for corresponding blue gid"); // find the int index_in_remote = remote_cells->find(1, global_id_blue); if (index_in_remote==-1) ERRORR( MB_FAILURE, "can't find the global id element in remote cells\n"); remote_cells->vr_wr[index_in_remote] += currentVals[redIndex]*areap; } else if (MB_SUCCESS==rval) { int arrRedIndex = rs2.index(redArr); if (-1 == arrRedIndex) ERRORR(MB_FAILURE, "can't find the red arrival index"); newValues[arrRedIndex] += currentVals[redIndex]*areap; } else ERRORR(rval, "can't get arrival red for corresponding "); } // now, send back the remote_cells to the processors they came from, with the updated values for // the tracer mass in a cell if (remote_cells) { // so this means that some cells will be sent back with tracer info to the procs they were sent from (parcomm->proc_config().crystal_router())->gs_transfer(1, *remote_cells, 0); // now, look at the global id, find the proper "red" cell with that index and update its mass //remote_cells->print("remote cells after routing"); int n = remote_cells->get_n(); for (int j=0; j<n; j++) { EntityHandle redCell = remote_cells->vul_rd[j];// entity handle sent back int arrRedIndex = rs2.index(redCell); if (-1 == arrRedIndex) ERRORR(MB_FAILURE, "can't find the red arrival index"); newValues[arrRedIndex] += remote_cells->vr_rd[j]; } } // now divide by red area (current) int j=0; Range::iterator iter = rs2.begin(); void * data=NULL; //used for stored area int count =0; double total_mass_local=0.; while (iter != rs2.end()) { rval = mb->tag_iterate(tagArea, iter, rs2.end(), count, data); ERRORR(rval, "can't tag iterate"); double * ptrArea=(double*)data; for (int i=0; i<count; i++, iter++, j++, ptrArea++) { total_mass_local+=newValues[j]; newValues[j]/= (*ptrArea); } } rval = mb->tag_set_data(tagElem, rs2, &newValues[0]); ERRORR(rval, "can't set new values tag"); double total_mass=0.; double total_intx_area =0; int mpi_err = MPI_Reduce(&total_mass_local, &total_mass, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); if (MPI_SUCCESS != mpi_err) return MB_FAILURE; // now reduce total area mpi_err = MPI_Reduce(&check_intx_area, &total_intx_area, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); if (MPI_SUCCESS != mpi_err) return MB_FAILURE; if (my_rank==0) { std::cout <<"total mass now:" << total_mass << "\n"; std::cout <<"check: total intersection area: (4 * M_PI * R^2): " << total_intx_area << "\n"; } if (remote_cells) { delete remote_cells; remote_cells=NULL; } return MB_SUCCESS; }
double_array Instance::toDoubleArray() const { double_array newValues(mAttValues.size()); std::copy(std::begin(mAttValues), std::end(mAttValues), std::begin(newValues)); return newValues; }
void Lockin2::interpretInput() { QTime time; time.start(); _timeValue += _outputPeriod; // récupère les nouvelles valeurs /* * le nombre de nouvelle valeurs = outputPeriod * sampleRate / 1000 * outputPeriod (~0.1 s) étant beaucoup plus grand que la periode du chopper (~1/500 s) * meme dans le cas d'un chopper lent et d'un temps de sortie rapide le nombre de periodes * du chopper reste elevé. (~50) * On peut donc garder uniquement les periodes entières * On a donc une perte de présision de l'ordre de 2/50 = 4% * Plus outputPeriod et grand et plus le chopper est rapide plus la perte diminue. * 0.5s 500Hz -> 0.8% * 1.0s 500Hz -> 0.4% */ QList<qreal> leftSignal; QList<int> chopperSignal; // les des données et les adapte // left [-1;+1] // right -1 ou +1 readSoudCard(leftSignal, chopperSignal); if (leftSignal.size() == 0 || chopperSignal.size() == 0) return; QList<QPair<qreal, qreal> > chopperSinCos = parseChopperSignal(chopperSignal, _phase); // multiplie le leftSignal ([-1;1]) par chopperSinCos ([-1;1]) for (int i = 0; i < leftSignal.size(); ++i) { qreal x, y; if (chopperSinCos[i].first != 3.0) { // 3.0 est la valeur qui indique ignoreValue dans parseChopperSignal(...) x = chopperSinCos[i].first * leftSignal[i]; // sin y = chopperSinCos[i].second * leftSignal[i]; // cos } else { x = y = 3.0; // ignore value } _dataXY << QPair<qreal, qreal>(x, y); } // renouvelle le view data (prend la fin des listes, qui correspond aux parties les plus récentes) if (_vumeterMutex.tryLock()) { _vumeterData.clear(); for (int i = leftSignal.size() - 1; i >= 0; --i) { if (_vumeterData.size() >= _sampleVumeter) break; if (chopperSinCos[i].first != 3.0) { _vumeterData.prepend(QPair<qreal, qreal>(leftSignal[i], chopperSinCos[i].first)); } } _vumeterMutex.unlock(); } else { qDebug() << __FUNCTION__ << ": the view Mutex is locked"; } // le nombre d'échantillons correslondant au temps d'integration if (_dataXY.size() < _sampleIntegration) { // pas encore assez d'elements pour faire la moyenne emit info("wait more input data..."); return; } // supprime les valeurs en trop while (_dataXY.size() > _sampleIntegration) _dataXY.removeFirst(); qreal dataCount = 0.0; qreal x = 0.0; qreal y = 0.0; for (int i = 0; i < _dataXY.size(); ++i) { // deux fois 3.0 indique ignoreValue if (_dataXY[i].first != 3.0) { x += _dataXY[i].first; y += _dataXY[i].second; dataCount += 1.0; } } if (dataCount == 0.0) { qDebug() << __FUNCTION__ << ": no data usable"; emit info("signal too low"); return; } x /= dataCount; y /= dataCount; // _values << QPair<qreal, QPair<qreal, qreal> >(_timeValue, QPair<qreal, qreal>(x, y)); _xValue = x; _yValue = y; emit newValues(_timeValue, x, y); qDebug() << __FUNCTION__ << ": execution time " << time.elapsed() << "ms"; }
void GridEditor::EditTool::frame(void) { /* Bail out if the tool is not active: */ if(!active) return; /* Update the tool's position and radius in model coordinates: */ Vrui::NavTrackerState newTrackerState=getButtonDeviceTransformation(0); newTrackerState.leftMultiply(Vrui::getInverseNavigationTransformation()); /* Update the brush position and size in model coordinates: */ modelCenter=Point(newTrackerState.getOrigin()); modelRadius=float(influenceRadius*newTrackerState.getScaling()); /* Determine the subdomain of the grid affected by the brush: */ EditableGrid::Index min,max; for(int i=0;i<3;++i) { min[i]=int(Math::floor((modelCenter[i]-modelRadius-fudgeSize)/grid->getCellSize(i))); if(min[i]<1) min[i]=1; max[i]=int(Math::ceil((modelCenter[i]+modelRadius+fudgeSize)/grid->getCellSize(i))); if(max[i]>grid->getNumVertices(i)-1) max[i]=grid->getNumVertices(i)-1; } /* Update the grid: */ float minr2=modelRadius>fudgeSize?Math::sqr(modelRadius-fudgeSize):0.0f; float maxr2=Math::sqr(modelRadius+fudgeSize); switch(editMode) { case ADD: { for(EditableGrid::Index v=min;v[0]<max[0];v.preInc(min,max)) { Point p; float dist=0.0f; for(int i=0;i<3;++i) { p[i]=float(v[i])*grid->getCellSize(i); dist+=Math::sqr(modelCenter[i]-p[i]); } if(dist<maxr2) { float val; if(dist<minr2) val=1.0f; else val=(modelRadius+fudgeSize-Math::sqrt(dist))/(2.0f*fudgeSize); float oldVal=grid->getValue(v); if(val>oldVal) grid->setValue(v,val); } } grid->invalidateVertices(min,max); break; } case SUBTRACT: { for(EditableGrid::Index v=min;v[0]<max[0];v.preInc(min,max)) { Point p; float dist=0.0f; for(int i=0;i<3;++i) { p[i]=float(v[i])*grid->getCellSize(i); dist+=Math::sqr(modelCenter[i]-p[i]); } if(dist<maxr2) { float val; if(dist<minr2) val=0.0f; else val=1.0f-(modelRadius+fudgeSize-Math::sqrt(dist))/(2.0f*fudgeSize); float oldVal=grid->getValue(v); if(val<oldVal) grid->setValue(v,val); } } grid->invalidateVertices(min,max); break; } case SMOOTH: { for(int i=0;i<3;++i) { if(min[i]==0) ++min[i]; if(max[i]==grid->getNumVertices(i)) --max[i]; } for(EditableGrid::Index v=min;v[0]<max[0];v.preInc(min,max)) { Point p; float dist=0.0f; for(int i=0;i<3;++i) { p[i]=float(v[i])*grid->getCellSize(i); dist+=Math::sqr(modelCenter[i]-p[i]); } if(dist<maxr2) { float avgVal=0.0f; EditableGrid::Index i; for(i[0]=v[0]-1;i[0]<=v[0]+1;++i[0]) for(i[1]=v[1]-1;i[1]<=v[1]+1;++i[1]) for(i[2]=v[2]-1;i[2]<=v[2]+1;++i[2]) avgVal+=grid->getValue(i); avgVal/=27.0f; if(dist<minr2) newValues(v)=avgVal; else { float w=(modelRadius+fudgeSize-Math::sqrt(dist))/(2.0f*fudgeSize); newValues(v)=avgVal*w+grid->getValue(v)*(1.0f-w); } } else newValues(v)=grid->getValue(v); } for(EditableGrid::Index v=min;v[0]<max[0];v.preInc(min,max)) grid->setValue(v,newValues(v)); grid->invalidateVertices(min,max); /* Request another frame to continue smoothing: */ Vrui::scheduleUpdate(Vrui::getApplicationTime()+1.0/125.0); break; } case DRAG: { /* Calculate the incremental tool transformation since the last frame: */ Vrui::NavTrackerState t=lastTrackerState; t*=Geometry::invert(newTrackerState); Geometry::OrthogonalTransformation<float,3> pt(t); float r2=Math::sqr(modelRadius); for(EditableGrid::Index v=min;v[0]<max[0];v.preInc(min,max)) { Point p; float dist=0.0f; for(int i=0;i<3;++i) { p[i]=float(v[i])*grid->getCellSize(i); dist+=Math::sqr(modelCenter[i]-p[i]); } if(dist<r2) { /* Compute the dragged position: */ Point dp=pt.transform(p); float w=Math::sqrt(dist)/modelRadius; dp=Geometry::affineCombination(dp,p,w); /* Look up the grid value at the dragged position: */ float dragVal=grid->getValue(dp); newValues(v)=dragVal; } else newValues(v)=grid->getValue(v); } for(EditableGrid::Index v=min;v[0]<max[0];v.preInc(min,max)) grid->setValue(v,newValues(v)); grid->invalidateVertices(min,max); break; } } lastTrackerState=newTrackerState; }
OptionalNode FindDivisions(const ast::Operands& operands, eval::SessionEnvironment& sessionEnvironment) { if ( operands.size() != 2 ) { sessionEnvironment.raiseMessage( Message(ids::FindDivisions, ids::argrx, { ast::Node::make<ast::Identifier>( ids::FindDivisions ), ast::Node::make<math::Rational>( operands.size() ), ast::Node::make<math::Rational>( 2 ) } )); return EvaluationFailure(); } const auto range = operands[0]; const auto numberOfElements = operands[1]; if ( !range.isFunctionCall(ids::List) || range.get<ast::FunctionCall>().getOperands().size() != 2) { sessionEnvironment.raiseMessage( Message(ids::FindDivisions, ids::fdargs, { range, ast::Node::make<ast::FunctionCall>( ids::FindDivisions, operands ) } )); return EvaluationFailure(); } if ( !numberOfElements.is<math::Rational>() || !math::isInteger(numberOfElements.get<math::Rational>()) ) { sessionEnvironment.raiseMessage( Message(ids::FindDivisions, ids::fdargs, { numberOfElements, ast::Node::make<ast::FunctionCall>( ids::FindDivisions, operands ) } )); return EvaluationFailure(); } std::vector<ast::Node> listParams = range.get<ast::FunctionCall>().getOperands(); auto endIt = std::find_if_not(listParams.begin(), listParams.end(), [](const ast::Node& param) { return param.isNumeric(); }); if (endIt != listParams.end()) { sessionEnvironment.raiseMessage( Message(ids::FindDivisions, ids::fdargs, { *endIt, ast::Node::make<ast::FunctionCall>( ids::FindDivisions, operands ) } )); return EvaluationFailure(); } const math::Real precision = (listParams[1].getNumeric() - listParams[0].getNumeric())/numberOfElements.getInteger(); const math::Rational left = math::findRationalNear(listParams[0].getNumeric(), precision); const math::Rational right = math::findRationalNear(listParams[1].getNumeric(), precision); std::vector<math::Rational> intermediates; // Impl here intermediates.push_back(left); const math::Rational distance = right - left; std::vector<math::Rational> multipliersbase = {1, 2, 5}; std::vector<math::Rational> multipliers; for(int i=-2;i<2;++i) { std::vector<math::Rational> newValues(multipliersbase.begin(), multipliersbase.end()); math::Rational magnitude = math::power(math::Rational{10}, i); for(auto& nv: newValues) { nv*=magnitude; } multipliers.insert(multipliers.end(), newValues.begin(), newValues.end()); } const auto multiplierIt = std::find_if(multipliers.begin(), multipliers.end(), [&](const math::Rational& multiplier) { // return true if multiplier would result in less ticks that requested return (math::Real{distance}/multiplier) < numberOfElements.getNumeric(); }); const auto multiplier = *(multiplierIt-1); for(math::Rational next = left + multiplier; next <= right ; next += multiplier) { intermediates.push_back(next); } ast::Operands elements; for(auto& intermediate: intermediates) { elements.push_back(ast::Node::make<math::Rational>(intermediate)); } return ast::Node::make<ast::FunctionCall>(ids::List, elements); }
void Constraint<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps>::Apply(const Matrix& P, Matrix& Projected) const { const size_t NSDim = X_->getNumVectors(); const size_t numRows = P.getNodeNumRows(); Projected.resumeFill(); Teuchos::SerialDenseVector<LO,SC> BcRow(NSDim, false); for (size_t i = 0; i < numRows; i++) { Teuchos::ArrayView<const LO> indices, pindices; Teuchos::ArrayView<const SC> values, pvalues; P .getLocalRowView(i, indices, values); Projected.getLocalRowView(i, pindices, pvalues); size_t nnz = pindices.size(); // number of nonzeros in the constrained matrix size_t nnz1 = indices.size(); // number of nonzeros in the supplied matrix Teuchos::Array<SC> newValues(nnz, Teuchos::ScalarTraits<SC>::zero()); // step 1: fix stencil // Projected already has the correct stencil // step 2: copy correct stencil values for (size_t j = 0; j < nnz1; j++) { // this might be accelerated if we know smth about ordering size_t k = 0; for (; k < nnz; k++) if (pindices[k] == indices[j]) break; if (k != nnz) { // index indices[j] is part of template, copy corresponding value newValues[k] = values[j]; } } // step 3: project to the space Teuchos::SerialDenseMatrix<LO,SC> locX(NSDim, nnz, false); for (size_t j = 0; j < nnz; j++) { for (size_t k = 0; k < NSDim; k++) BcRow[k] = X_->getData(k)[pindices[j]]; Teuchos::setCol(BcRow, (LO)j, locX); } Teuchos::SerialDenseVector<LO,SC> val(nnz, false), val1(NSDim, false), val2(NSDim, false); for (size_t j = 0; j < nnz; j++) val[j] = newValues[j]; Teuchos::BLAS<LO,SC> blas; blas.GEMV(Teuchos::NO_TRANS, NSDim, nnz, Teuchos::ScalarTraits<SC>::one(), locX.values(), locX.stride(), val.values(), (LO)1, Teuchos::ScalarTraits<SC>::zero(), val1.values(), (LO)1); blas.GEMV(Teuchos::NO_TRANS, NSDim, NSDim, Teuchos::ScalarTraits<SC>::one(), XXtInv_[i].values(), XXtInv_[i].stride(), val1.values(), (LO)1, Teuchos::ScalarTraits<SC>::zero(), val2.values(), (LO)1); blas.GEMV(Teuchos::CONJ_TRANS, NSDim, nnz, Teuchos::ScalarTraits<SC>::one(), locX.values(), locX.stride(), val2.values(), (LO)1, Teuchos::ScalarTraits<SC>::zero(), val.values(), (LO)1); for (size_t j = 0; j < nnz; j++) newValues[j] -= val[j]; Projected.replaceLocalValues(i, pindices, newValues); } Projected.fillComplete(Projected.getDomainMap(), Projected.getRangeMap()); //FIXME: maps needed? }