void VanderPolME2::solve()
  {
    if (mpd_->appExistsOnProcess(eq2_)) {

      // take a tentative time step
      TEUCHOS_ASSERT(true);
      tentativeTime_ = currentTime_ + currentTimeStepSize_;
      
      // Solve for x2 at new time using Newton's method with backward
      // Euler.
      //const double& t = tentativeTime_;
      const double relTol = 1.0e-5;
      const double absTol = 1.0e-8;
      bool converged = false;
      
      const int maxIters = 20;
      int iter = 0;
      double f = computeF(x2_);
      *mpd_->getApplicationOStream(eq2_) << "Solving for x2_ in me2, x1 = " << p_x1_ << std::endl;
      *mpd_->getApplicationOStream(eq2_) << iter << ": x2=" << x2_ << ", ||f||=" << std::abs(f) << std::endl;
      while (!converged && (iter < maxIters) ) {
	
	double dx = -f / computeJ(x2_);
	x2_ = dx + x2_;
	f = computeF(x2_);
	++iter;
	
	if ( (std::abs(dx) < relTol) && (std::abs(f) < absTol) )
	  converged = true;
	
	*mpd_->getApplicationOStream(eq2_) << iter << ": x2=" << x2_ << ", ||f||=" << std::abs(f) << std::endl;
      }

      if (converged)
	isLocallyConverged_ = true;
      else
	isLocallyConverged_ = false; 
      
      *mpd_->getApplicationOStream(eq2_) << "me2::solve(), x2_ = " << x2_ << std::endl; 
    }

    Teuchos::broadcast(*mpd_->getGlobalComm(), 1, const_cast<double*>(&x2_));

    // Send convergence status from proc 1 where eq 2 lives to all
    // procs.  Use int for mpi commmunication.
    int zeroMeansConverged = isLocallyConverged_ ? 0 : 1;
    Teuchos::broadcast(*mpd_->getGlobalComm(), 1, Teuchos::ptrFromRef(zeroMeansConverged));
    isLocallyConverged_ = (zeroMeansConverged == 0);

    sovledTentativeStep_ = true;
  }
示例#2
0
/**
* Builds a Jacobian Matrix J[]
*/
Matd Solver::computeJ(Markers handles, int cID){
	Matd J;
	J.SetSize(mModel->GetDofCount(), 4);
	J.MakeZero();

	//Get the current Node
	Marker *h = handles[cID];
	Vec4d tempPos(h->mOffset, 1.0);
	TransformNode *node = mModel->mLimbs[h->mNodeIndex];

	// Utility identity matrix
	Mat4d identity;
	identity.MakeDiag(1.0);

	// Recursively create Jacobian
	computeJ(J, node, tempPos, identity);

	return J;
}
示例#3
0
void Solver::solve() {
	// Utility constants
	const int sIFreq = 20;
	const double sIF = 4.0;
	const double sDF = 2.0;
	const int eIFreq = 2;
	const double eIF = 2.0;
	// Loop over all valid frames
	for (int f = 0; f < mMaxFrames; f++)
	{
		// Build C[]
		buildConstraintMat(f);

		//Objective function value
		double o = 0.0;

		Markers &handles = mModel->mHandleList;
		for (int i = 0; i < constraintIDs.size(); i++)
		{
			// Get handle and target position for the given constraint
			Marker *h = handles[constraintIDs[i]];
			Vec3d cPos = mModel->mOpenedC3dFile->GetMarkerPos(f, constraintIDs[i]);

			// Calculate values and store
			Vec3d cVal = h->mGlobalPos - cPos;
			double cLength = sqrlen(cVal);

			//Store results
			constraintVals.push_back(cVal);
			constraintLengths.push_back(cLength);

			//Update objective function
			o += cLength; 
		}
		
		// Main loop
		double e = mEps;
		double s = mStep;
		int iterCount = 0;
		int stepCount = 0;
		while (o > e) //while Objective Function > Epsilon
		{
			// Compute gradient -- TODO: Move this somewhere else for the sake of keeping this compact!
			Vecd gradient;
			gradient.SetSize(mModel->GetDofCount());
			gradient.MakeZero();

			for (int i = 0; i < constraintIDs.size(); i++)
			{
				//Get Constraint
				Vec4d cVec(constraintVals[i], 1.0);

				//Get Jacobian
				Matd J = computeJ(mModel->mHandleList, constraintIDs[i]);

				//Calculate current and add to gradient matrix
				Vecd currentVal = J * cVec;
				gradient = gradient + currentVal;

			}

			// Finally, double it
			gradient = 2.0 * gradient;

			// Get previous DOFs
			Vecd prevDofs;
			prevDofs.SetSize(mModel->GetDofCount());
			mModel->mDofList.GetDofs(&prevDofs);

			// Update DOFs
			Vecd nextDofs = prevDofs - s * gradient;
			mModel->SetDofs(nextDofs);

			
			// Recalculate constraints and objective function
			double newO = 0.0;

			Markers &handles = mModel->mHandleList;
			for (int i = 0; i < constraintIDs.size(); i++)
			{
				// Get handle and target position for the given constraint
				Marker *h = handles[constraintIDs[i]];
				Vec3d cPos = mModel->mOpenedC3dFile->GetMarkerPos(f, constraintIDs[i]);

				// Calculate values and store
				Vec3d cVal = h->mGlobalPos - cPos;
				double cLength = sqrlen(cVal);

				//Store results
				constraintVals.push_back(cVal);
				constraintLengths.push_back(cLength);

				//Update objective function
				newO += cLength; 
			}


			// Attempting to make sure we don't go infinite...
			if (newO < o)
			{		
				if (newO > mEps && iterCount > 0 && iterCount % 20 == 0)
				{
					s *= 3.0;
				}
				o = newO;	
			}
			else
			{
				stepCount++;
				// Decrease step size
				s = s / 2.0;
				
				// based on how many times we've had to decrease the step size, choose different options
				if (stepCount < mMaxIters)
				{
					// Reset to the previous dofs and try again
					mModel->SetDofs(prevDofs);
				}
				else if (stepCount < eIFreq*mMaxIters)
				{
					// Try increasing epsilon
					e *= 3.0;

					// Reset to the previous dofs and try again
					mModel->SetDofs(prevDofs);
				}
				else
				{
					// Otherwise, halt or we will never finish
					o = 0.0;
				}
			}
			iterCount++;
		}

		// Update the frame counter
		UI->mFrameCounter_cou->value(f);

		//Refresh the screen
		UI->mGLWindow->flush();
	}	
}
示例#4
0
/*
* Jacobian recursive worker method
*/
void Solver::computeJ(Matd &J, TransformNode *node, Vec4d &pos, Mat4d &trans) {

	// Get initial transform data
	std::vector<Transform *> transforms = node->mTransforms;

	// LEFT MATRIX
	Mat4d leftMat;
	leftMat.MakeDiag(1.0);	// identity
	for (int i = 0; i < transforms.size(); i++)
	{
		Transform *tr = transforms[i];
		// Only need to calculate if DOF
		if (tr->IsDof())
		{
			for (int j = 0; j < tr->GetDofCount(); j++)
			{
				// Get DOF
				Dof *dof = tr->GetDof(j);
				int dofId = dof->mId;

				// Add to our map
				leftMap[dofId] = leftMat;
			}
		}
		// Now update leftMat
		leftMat = leftMat * tr->GetTransform();
	}

	// RIGHT MATRIX
	Mat4d rightMat;
	rightMat.MakeDiag(1.0);	// identity
	for (int i = transforms.size()-1; i >= 0; i--)
	{
		Transform *tr = transforms[i];
		// Only need to calculate if DOF
		if (tr->IsDof())
		{
			for (int j = tr->GetDofCount()- 1; j >= 0 ; j--)
			{
				// Get DOF
				Dof *dof = tr->GetDof(j);
				int dofId = dof->mId;

				// Add to our map
				rightMap[dofId] = rightMat;
			}
		}
		// Now update leftMat
		rightMat = tr->GetTransform() * rightMat;
	}

	// JACOBIAN
	Mat4d pTrans = node->mParentTransform;

	// New identity matrix for later use
	Mat4d newTransform;
	newTransform.MakeDiag(1.0);

	for (int i = 0; i < transforms.size(); i++)
	{		
		// Check if DOF, if so compute derivative
		Transform *tr = transforms[i];
		if (tr->IsDof())
		{
			for (int j = 0; j < tr->GetDofCount(); j++)
			{
				Mat4d deriv = tr->GetDeriv(j);

				// Get row
				Dof * dof = tr->GetDof(j);
				int dofId = dof->mId;

				Mat4d leftMat = leftMap[dofId];
				Mat4d rightMat = rightMap[dofId];
				Vec4d value = pTrans * leftMat * deriv * rightMat * trans * pos;

				J[dofId] = value;
			}
		}

		newTransform = newTransform * tr->GetTransform();
	}
	// Calculate J[] values for parent if necessary
	TransformNode *parent = node->mParentNode;
	// If the parent is non-null and not the current node
	if (parent != NULL && parent != node)
	{
		newTransform = newTransform * trans;
		computeJ(J, parent, pos, newTransform);
	}
}