Status UpdateDriver::parse(const BSONObj& updateExpr) { clear(); // Check if the update expression is a full object replacement. if (*updateExpr.firstElementFieldName() != '$') { if (_multi) { return Status(ErrorCodes::FailedToParse, "multi update only works with $ operators"); } // Modifiers expect BSONElements as input. But the input to object replace is, by // definition, an object. We wrap the 'updateExpr' as the mod is expecting. Note // that the wrapper is temporary so the object replace mod should make a copy of // the object. auto_ptr<ModifierObjectReplace> mod(new ModifierObjectReplace); BSONObj wrapper = BSON( "dummy" << updateExpr ); Status status = mod->init(wrapper.firstElement(), _modOptions); if (!status.isOK()) { return status; } _mods.push_back(mod.release()); // Register the fact that this driver will only do full object replacements. _replacementMode = true; return Status::OK(); } // The update expression is made of mod operators, that is // { <$mod>: {...}, <$mod>: {...}, ... } BSONObjIterator outerIter(updateExpr); while (outerIter.more()) { BSONElement outerModElem = outerIter.next(); // Check whether this is a valid mod type. modifiertable::ModifierType modType = modifiertable::getType(outerModElem.fieldName()); if (modType == modifiertable::MOD_UNKNOWN) { return Status(ErrorCodes::FailedToParse, str::stream() << "Unknown modifier: " << outerModElem.fieldName()); } // Check whether there is indeed a list of mods under this modifier. if (outerModElem.type() != Object) { return Status(ErrorCodes::FailedToParse, str::stream() << "Modifiers operate on fields but we found a " << typeName(outerModElem.type()) << " instead. For example: {$mod: {<field>: ...}}" << " not {" << outerModElem.toString() << "}"); } // Check whether there are indeed mods under this modifier. if (outerModElem.embeddedObject().isEmpty()) { return Status(ErrorCodes::FailedToParse, str::stream() << "'" << outerModElem.fieldName() << "' is empty. You must specify a field like so: " "{$mod: {<field>: ...}}"); } BSONObjIterator innerIter(outerModElem.embeddedObject()); while (innerIter.more()) { BSONElement innerModElem = innerIter.next(); Status status = addAndParse(modType, innerModElem); if (!status.isOK()) { return status; } } } // Register the fact that there will be only $mod's in this driver -- no object // replacement. _replacementMode = false; return Status::OK(); }
Status UpdateDriver::parse(const BSONObj& updateExpr) { clear(); // Check if the update expression is a full object replacement. if (*updateExpr.firstElementFieldName() != '$') { if (_multi) { return Status(ErrorCodes::FailedToParse, "multi update only works with $ operators"); } // Modifiers expect BSONElements as input. But the input to object replace is, by // definition, an object. We wrap the 'updateExpr' as the mod is expecting. Note // that the wrapper is temporary so the object replace mod should make a copy of // the object. auto_ptr<ModifierObjectReplace> mod(new ModifierObjectReplace); BSONObj wrapper = BSON( "dummy" << updateExpr ); Status status = mod->init(wrapper.firstElement(), _modOptions); if (!status.isOK()) { return status; } _mods.push_back(mod.release()); // Register the fact that this driver will only do full object replacements. _replacementMode = true; return Status::OK(); } // The update expression is made of mod operators, that is // { <$mod>: {...}, <$mod>: {...}, ... } BSONObjIterator outerIter(updateExpr); while (outerIter.more()) { BSONElement outerModElem = outerIter.next(); // Check whether this is a valid mod type. modifiertable::ModifierType modType = modifiertable::getType(outerModElem.fieldName()); if (modType == modifiertable::MOD_UNKNOWN) { return Status(ErrorCodes::FailedToParse, "unknown modifier type"); } // Check whether there is indeed a list of mods under this modifier. if (outerModElem.type() != Object) { return Status(ErrorCodes::FailedToParse, "List of mods must be an object"); } // Check whether there are indeed mods under this modifier. if (outerModElem.embeddedObject().isEmpty()) { return Status(ErrorCodes::FailedToParse, "Empty expression after update $mod"); } BSONObjIterator innerIter(outerModElem.embeddedObject()); while (innerIter.more()) { BSONElement innerModElem = innerIter.next(); if (innerModElem.eoo()) { return Status(ErrorCodes::FailedToParse, "empty entry in $mod expression list"); } auto_ptr<ModifierInterface> mod(modifiertable::makeUpdateMod(modType)); dassert(mod.get()); Status status = mod->init(innerModElem, _modOptions); if (!status.isOK()) { return status; } _mods.push_back(mod.release()); } } // Register the fact that there will be only $mod's in this driver -- no object // replacement. _replacementMode = false; return Status::OK(); }
// Implementation of knupp metric untangling void knuppMetric::optimizeNodePosition(const scalar tolObsolete) { if( !bb_.contains(p_) ) p_ = 0.5 * (bb_.min() + bb_.max()); const scalar tol = Foam::sqr(2.0 * SMALL) * magSqr(bb_.min() - bb_.max()); label iterI, outerIter(0); vector gradF, disp; tensor gradGradF; scalar func, lastFunc; # ifdef DEBUGSmooth forAll(normals_, nI) { const scalar fx = normals_[nI] & (p_ - centres_[nI]); Info << "Tet " << nI << " has distance " << fx << " func " << Foam::sqr(mag(fx) - fx) << endl; } Info << "BoundBox size " << (bb_.max() - bb_.min()) << endl; Info << "Tolerance " << tol << endl; # endif bool finished; do { finished = true; lastFunc = evaluateMetric(); iterI = 0; do { # ifdef DEBUGSmooth Info << "Iteration " << iterI << endl; Info << "Initial metric value " << lastFunc << endl; # endif //- store previous value const point pOrig = p_; //- evaluate gradients evaluateGradients(gradF, gradGradF); //- calculate displacement const scalar determinant = det(gradGradF); if( determinant > SMALL ) { disp = (inv(gradGradF, determinant) & gradF); for(direction i=0;i<vector::nComponents;++i) { const scalar& val = disp[i]; if( (val != val) || ((val - val) != (val - val)) ) { disp = vector::zero; break; } } p_ -= disp; func = evaluateMetric(); # ifdef DEBUGSmooth Info << "Second grad " << gradGradF << endl; Info << "inv(gradGradF, determinant) " << inv(gradGradF, determinant) << endl; Info << "Gradient " << gradF << endl; Info << "Determinant " << determinant << endl; Info << "Displacement " << disp << endl; Info << "New metric value " << func << endl; # endif scalar relax(0.8); label nLoops(0); while( func > lastFunc ) { p_ = pOrig - relax * disp; relax *= 0.5; func = evaluateMetric(); if( func < lastFunc ) continue; //- it seems that this direction is wrong if( ++nLoops == 5 ) { p_ = pOrig; disp = vector::zero; func = 0.0; } } lastFunc = func; } else { disp = vector::zero; } } while( (magSqr(disp) > tol) && (++iterI < 10) ); if( (lastFunc < VSMALL) && (evaluateMetricNoBeta() > VSMALL) ) { beta_ /= 2.0; finished = false; } } while( !finished && (++outerIter < 5) ); # ifdef DEBUGSmooth Info << "Last value " << lastFunc << endl; Info << "Beta " << beta_ << endl; Info << "Metric with no beta " << evaluateMetricNoBeta() << endl; forAll(normals_, nI) { const scalar fx = normals_[nI] & (p_ - centres_[nI]); Info << "Tet " << nI << " has distance " << fx << " func " << Foam::sqr(mag(fx) - fx) << endl; } //::exit(1); # endif }