Example #1
0
int main()
{
  GaussianEliminator terminator(4);
  unsigned short int r1[] = {0, 1, 2};
  unsigned short int r2[] = {1, 3};
  unsigned short int r3[] = {0, 1};
  unsigned short int r4[] = {3};

  Equation eq;
  std::copy ( r1, r1 + 3, std::back_inserter ( eq ) );
  terminator.addEquation(eq, true);
  eq.clear();
  std::copy ( r2, r2 + 2, std::back_inserter ( eq ) );
  terminator.addEquation(eq, true);
  eq.clear();
  std::copy ( r3, r3 + 2, std::back_inserter ( eq ) );
  terminator.addEquation(eq, false);
  eq.clear();
  std::copy ( r4, r4 + 1, std::back_inserter ( eq ) );
  terminator.addEquation(eq, true);
    
  std::vector <bool> sol = terminator.getSolution();
  for (std::vector <bool>::iterator it = sol.begin();
       it < sol.end(); it ++)
    std::cout << *it << std::endl;

  return 0;
}
Example #2
0
/***
 * FUNCTION: Integrates equation using Simpson method
 *   RETURN: Definite integral of equation
 *    PARAM: [IN] equation      - equation to integrate
 *    PARAM: [IN] start         - left integration border
 *    PARAM: [IN] end           - right integration border
 *    PARAM: [IN] numIterations - number of iterations
 *      SEE: write me
 *   AUTHOR: Eliseev Dmitry
 ***/
Equation ParametricIntegrator::Simpson( const Equation &equation, const double start, const double end, const unsigned int numIterations )
{
  unsigned int i = 0;

  /* Timer creation */
  Timer timer;

  /* Result equation */
  Equation result = Equation(start) + Equation(end);

  /* Odd members */
  Equation oddResult("0");
  for (i = 1; i <= 2 * numIterations - 1; i+=2)
    oddResult += equation.GetEquation(start + (end - start) * i / (2 * numIterations));

  /* Even members */
  Equation evenResult("0");
  for (i = 2; i <= 2 * numIterations - 2; i+=2)
    evenResult += equation.GetEquation(start + (end - start) * i / (2 * numIterations));

  /* Add calculated values */
  result += Equation("4") * oddResult + Equation("2") * evenResult;

  /* That's it */
  result *= Equation((end - start) / (6 * numIterations));
  result.Simplify();

  /* Determine spent time */
  numSeconds = timer.GetTimePassed();
  return result;
} /* End of 'Integrator::Simpson' method */
Example #3
0
 std::string operator()(Equation   const & e, bool use_parenthesis = false) const
 {
   std::stringstream ss;
   ss << operator()(e.lhs()) << " = " << operator()(e.rhs());
   static_cast<int>(use_parenthesis); //to silence unused parameter warnings
   return ss.str();
 }
Example #4
0
void slack_matrix::init_geqz_constraints(Matrix& m)
{
	geqz_constraints = new bool[m.num_vars()];
	memset(geqz_constraints, 0, m.num_vars()*sizeof(bool));
	Matrix::iterator it = m.begin();
	for(; it!= m.end(); it++)
	{
		bignum constant = it->second;
		if(constant > 0) continue;

		int index = -1;
		Equation* eq = it->first;
		for(int c=0; c<eq->num_entries(); c++)
		{
			bignum e = eq->get(c);
			if(e > 0){
				index = -1;
				break;
			}
			else if(e<0 && index != -1)
			{
				index = -1;
				break;
			}
			else if(e<0)
				index = c;
		}
		// Mark entry as 1 if var has non-negativity constraint
		if(index != -1)
			geqz_constraints[index] = true;

	}

}
Example #5
0
int main() {
    std::cout << "Hello World" << std::endl;


    // a # b # c # d # e # f # g # h # i = 60
    // a + 10 * b - c / d + 11 / e - f + 12 * g / h + i + 13 = 60

    Equation eq;
    eq.logical();


    return EXIT_SUCCESS;
}
Example #6
0
void CreateForces()
{
    //Creates force objects that can be referenced by the body object.
    //You can have multiple references to the same force object.

    for (int i = 0; i < 6; i++)
    {
        Active1.listCoefficients().push_back(complex<double>(i+1,-i-1));
    }

    //Create some equations with variables to add into derivative object
    Derivative Deriv1;
    Derivative Deriv2;

    Equation* temp;

    for (int i = 0; i < 6; i++)
    {
        Deriv1.listEquation().push_back(Equation());
        Deriv2.listEquation().push_back(Equation());

        temp = &(Deriv1.listEquation().at(i));
        temp->setDataIndex(i);

        //Set first derivative
        for (int j = 0; j < 6; j++)
        {
            temp->setCoefficient(j+1,j+1);
        }

        //Set second derivative
        temp = &(Deriv2.listEquation().at(i));
        temp->setDataIndex(i);
        for (int j = 0; j < 6; j++)
        {
            temp->setCoefficient(2*i+1,j*i+1);
        }
    }

    //add the two derivatives into the react force object
    React1.addDerivative(Deriv1, 0);
    React1.addDerivative(Deriv2, 1);

    //Add the two derivatives into the cross force object
    Cross1.addDerivative(Deriv1, 0);
    Cross1.addDerivative(Deriv2, 1);

}
Example #7
0
//-----------------------------------------------------------------------------
void dolfin::solve(const Equation& equation,
                   Function& u,
                   std::vector<const BoundaryCondition*> bcs,
                   const Form& J,
		   Parameters parameters)
{
  // Check that the problem is linear
  if (equation.is_linear())
    dolfin_error("solve.cpp",
                 "solve nonlinear variational problem",
                 "Variational problem is linear");

  // Solve nonlinear problem
  NonlinearVariationalProblem problem(*equation.lhs(), u, bcs, J);
  NonlinearVariationalSolver solver(problem);
  solver.parameters.update(parameters);
  solver.solve();
}
Example #8
0
//-----------------------------------------------------------------------------
void dolfin::solve(const Equation& equation, Function& u,
                   std::vector<const DirichletBC*> bcs,
                   const double tol, GoalFunctional& M)

{
  // Solve linear problem
  if (equation.is_linear())
  {
    LinearVariationalProblem problem(*equation.lhs(), *equation.rhs(), u, bcs);
    AdaptiveLinearVariationalSolver solver(problem, M);
    solver.solve(tol);
  }
  else
  {
    // Raise error if the problem is nonlinear (for now)
    dolfin_error("solve.cpp",
                 "solve nonlinear variational problem adaptively",
                 "Nonlinear adaptive solve not implemented without Jacobian");
  }
}
Example #9
0
int main() {
	string str;
	while(getline(cin,str)) {
		Equation *EQ = new Equation(str);
		if(!(EQ->IsValid())) {
			cout << "Invalid Equation!\n";
			continue;
		}

		EquationSolver *solver;
		if(EQ->IsLinear()) solver = new LinearEquationSolver(EQ);
		else solver = new NonLinearEquationSolver(EQ);
		   
		solver->Solve();
		vector<double> *SS = solver->GetSolutionSet();
		vector<pair<long long, long long> > *FR = solver->GetFractions();

		for(int i = 0; i < SS->size(); i++) cout << (*SS)[i] << endl;
	}
	return 0;
}
Example #10
0
//-----------------------------------------------------------------------------
void dolfin::solve(const Equation& equation,
                   Function& u,
                   std::vector<const DirichletBC*> bcs,
                   const Form& J,
                   const double tol,
                   GoalFunctional& M)

{
  // Raise error if problem is linear
  if (equation.is_linear())
    dolfin_error("solve.cpp",
                 "solve nonlinear variational problem adaptively",
                 "Variational problem is linear");

  // Define nonlinear problem
  NonlinearVariationalProblem problem(*equation.lhs(), u, bcs, J);

  // Solve nonlinear problem adaptively
  AdaptiveNonlinearVariationalSolver solver(problem, M);
  solver.solve(tol);
}
Example #11
0
//-----------------------------------------------------------------------------
void dolfin::solve(const Equation& equation,
                   Function& u,
                   std::vector<const BoundaryCondition*> bcs,
		   Parameters parameters)
{
  // Solve linear problem
  if (equation.is_linear())
  {
    LinearVariationalProblem problem(*equation.lhs(), *equation.rhs(), u, bcs);
    LinearVariationalSolver solver(problem);
    solver.parameters.update(parameters);
    solver.solve();
  }

  // Solve nonlinear problem
  else
  {
    NonlinearVariationalProblem problem(*equation.lhs(), u, bcs);
    NonlinearVariationalSolver solver(problem);
    solver.parameters.update(parameters);
    solver.solve();
  }
}
Example #12
0
/***
 * FUNCTION: Integrates equation using center-rectangles method
 *   RETURN: Definite integral of equation
 *    PARAM: [IN] equation      - equation to integrate
 *    PARAM: [IN] start         - left integration border
 *    PARAM: [IN] end           - right integration border
 *    PARAM: [IN] numIterations - number of iterations
 *      SEE: write me
 *   AUTHOR: Eliseev Dmitry
 ***/
Equation ParametricIntegrator::Rectangles( const Equation &equation, const double start, const double end, const unsigned int numIterations )
{
  double step = (end - start) / numIterations;
  unsigned int i = 0;

  /* Result equation */
  Equation result("0");
  Equation width(step);

  /* Timer creation */
  Timer timer;

  /* For each iteration */
  for (i = 0; i < numIterations; i++)
    result += width * equation.GetEquation(step * i);

  /* That's it */
  result.Simplify();

  /* Determine spent time */
  numSeconds = timer.GetTimePassed();
  return result;
} /* End of 'Integrator::Rectangles' method */
Example #13
0
bool
GaussianEliminator::addEquation(Equation eq, bool term)
{
  Row nrow; 

  while(eq.size()) {
    unsigned short int fp = eq[0];
    if (rows[fp].set){
      eq += rows[fp].eq;
      term ^= constTerms[fp];      
    } else {
      rows[fp].set = true;
      rows[fp].eq = eq;
      constTerms[fp] = term;
      rowsUnset --;
      break;
    }        
  }

  if (isSolvable())
    return true;

  return false;
}
Example #14
0
 void addVar(Variable var) { eq.push_back(var); } 
Example #15
0
void Newton::Solve(double xZ)
{
    //cout << "\n Solving:" << inputEQ << " x0:" << xZ << endl;
    vector<string> TermInitiators;
    string temp;

    for(int i = 0; i < inputEQ.size(); i++)
    {
        ///Check for sign of leading term
        if(i == 0)
        {
            if(inputEQ[i]=='-')
            {
                //First term was negative
                    //cout << inputEQ[i] << "<- 1 was neg" << endl;
                    temp = temp + inputEQ[i];
                }
                else
                {
                    //First term was positive
                    //cout << inputEQ[i] << "<- 1 was pos" << endl;
                    temp = temp + '+';
                    temp = temp + inputEQ[i];
                }
        }
        else
        {

            if( inputEQ[i] == '+' || inputEQ[i] == '-' )
            {
                if(inputEQ[i-1] == '^' && inputEQ[i] == '-')
                {
                    temp = temp + inputEQ[i];
                }
                else
                {
                    //End of term
                    TermInitiators.push_back(temp);
                    temp = "";
                    temp = temp + inputEQ[i];
                }
            }
            else
            {
                    //Term component
                    temp = temp + inputEQ[i];
                }
            }
        }
        //final push
        TermInitiators.push_back(temp);


        ///Now that we have terms in a vector of strings
        ///Pass that vector to the constructor of an
        ///Equation.


        double xIn = xZ;
        double xOut;
        double fX, fXPrime;//Results

        Equation * theEquation = new Equation(TermInitiators); ///creates an equation which can accept values



        ///Get derivative of equation
        theEquation->Derivative();

        vector<string> pTermsInitiators;

        for(int i = 0; i < theEquation->PrimeTerms.size(); i++)
        {
            pTermsInitiators.push_back(theEquation->PrimeTerms[i].og);
        }


        Equation * thePrimeEquation = new Equation(pTermsInitiators); ///creates an equation of prime terms which can accept values


        /*                                    x

        ------==Iterative Solving Part==------

        x                                     */

        double a = 0,b = 0;
        double test = 0;

        xIn = 1;
        int j = 0;
        while(solved == false)
        {

            theEquation->plugin(xIn);
            a = theEquation->anzwer;

            thePrimeEquation->plugin(xIn);
            b = thePrimeEquation->anzwer;

            xOut = a / b;
            xOut = xIn - xOut;
            xIn = xOut;

            ///Test if close enough
            theEquation->plugin(xIn);
            test = theEquation->anzwer;
            if(test < TOLERABLEERROR)
            {
                //cout << "!!Decent!!" << endl;
                solved = true;
            }

            j++;
        }

        cout << "\n\nAnswer is: "<< xOut << " after " << j << " iterations." << endl;


}
Example #16
0
// -----------Private methods ------------------//
void slack_matrix::populate_slack_matrix(Matrix& m)
{
	/*
	 * If the initial system is Ax <= b,
	 * the slack matrix will contain it in the form
	 * -x0 + y +Ax -b
	 * and the last row is the objective function, initially -x0.
	 */
	Matrix::iterator it = m.begin();
	int last = m.size()-1;

	/*
	vector<int> rows;
	std::set<int> used;
	for(int i=0; i <= last; i++)
	{
		int cur = rand()%(last+1);
		while(used.count(cur) > 0){
			cur++;
			cur = cur%(last+1);
		}
		used.insert(cur);
		rows.push_back(cur);

	}
	*/

	int r = 0;
	int i = 0;
	for(; it!=m.end(); it++, r++, i++)
	{
		r = i;//rows[i];
		// s0 entry is initially -1 for all rows
		sm->set(r, 0, -1);

		// In row r, set the corresponding slack variable to 1.
		sm->set(r, i+1, 1);

		Equation *eq = it->first;
		for(int c=0; c < eq->num_entries(); c++) {
			int start_index = index_mapping[c];
			bignum coef = eq->get(c);
			sm->set(r, start_index, coef);


			/* Figure out whether we needed to split
			 * x as x1-x2 for missing non-negative constraints
			 */
			if(geqz_constraints[c]) continue;
			sm->set(r, start_index+1, -coef);
		}
		//Deal with original constant
		sm->set_constant(r, -it->second);

		//Fill last slot with index of pivot variable for this row
		sm->set_pivot(r, i+1);

	}
	/*
	 *  Populate objective function row: Initially we want
	 *  to maximize -x0
	 */
	sm->set(last+1, 0, -1);
}
void Solver::solve(int printDebugInfo){
    int i, j, k, l;
    std::vector<Equation*> eqs;
    getEquations(&eqs);
    int numRows = getSystemMatrixRows(),
        neq = eqs.size(),
        nconstraints=m_constraints.size();

    // Compute RHS
    double * rhs = (double*)malloc(numRows*sizeof(double));
    for(i=0; i<neq; ++i){
        Equation * eq = eqs[i];
        double  Z = eq->getFutureVelocity() - eq->getVelocity(),
                GW = eq->getVelocity(),
                g = eq->getViolation(),
                a = eq->m_a,
                b = eq->m_b;
        rhs[i] = -a * g  - b * GW  - Z; // RHS = -a*g -b*G*W -Z
    }

    // Compute matrix S = G * inv(M) * G' = G * z
    // Should be easy, since we already got the entries from the user
    std::vector<int> Srow;
    std::vector<int> Scol;
    std::vector<double> Sval;

    for (int i = 0; i < neq; ++i){
        for (int j = 0; j < neq; ++j){
            // We are at element i,j in S
            Equation * ei = eqs[i];
            Equation * ej = eqs[j];

            double val = 0;
            int nonzero = 0;
            if(ei->getConnA() == ej->getConnA()){
                val += ei->getGA().multiply(ej->getddA());
                nonzero = 1;
            }
            if(ei->getConnA() == ej->getConnB()){
                val += ei->getGA().multiply(ej->getddB());
                nonzero = 1;
            }
            if(ei->getConnB() == ej->getConnA()){
                val += ei->getGB().multiply(ej->getddA());
                nonzero = 1;
            }
            if(ei->getConnB() == ej->getConnB()){
                val += ei->getGB().multiply(ej->getddB());
                nonzero = 1;
            }

            if(nonzero){
                Srow.push_back(i);
                Scol.push_back(j);
                Sval.push_back(val);
            }
        }
    }

    // Add regularization to diagonal entries
    for (int i = 0; i < eqs.size(); ++i){
        double eps = eqs[i]->m_epsilon;
        if(eps > 0){

            int found = 0;

            // Find the corresponding triplet
            for(int j = 0; j < Srow.size(); ++j){
                if(Srow[j] == i && Scol[j] == i){
                    Sval[j] += eps;
                    found = 1;
                    break;
                }
            }

            // Could not find triplet. Add it.
            if(!found){
                Sval.push_back(eps);
                Srow.push_back(i);
                Scol.push_back(i);
            }
        }
    }


    // Print matrices
    if(printDebugInfo){
        for (int i = 0; i < Srow.size(); ++i){
            printf("(%d,%d) => %g\n",Scol[i],Srow[i],Sval[i]);
        }
        char empty = '0';
        char tab = '\t';
        printf("G = [\n");
        for(int i=0; i<eqs.size(); ++i){
            Equation * eq = eqs[i];
            Connector * connA = eq->getConnA();
            Connector * connB = eq->getConnB();

            //printf("%d %d\n",connA->m_index,connB->m_index);

            int swapped = 0;
            if(connA->m_index > connB->m_index){
                Connector * temp = connA;
                connA = connB;
                connB = temp;
                swapped = 1;
            }

            // Print empty until first
            for (int j = 0; j < 6*connA->m_index; ++j){
                printf("%c\t",empty);
            }

            // Print contents of first ( 6 jacobian entries )
            JacobianElement G = !swapped ? eq->getGA() : eq->getGB();
            printf("%g%c%g%c%g%c%g%c%g%c%g%c",
                G.getSpatial().x(),tab,
                G.getSpatial().y(),tab,
                G.getSpatial().z(),tab,
                G.getRotational().x(),tab,
                G.getRotational().y(),tab,
                G.getRotational().z(),tab);

            // Print empty until second
            for (int j = 6*(connA->m_index+1); j < 6*connB->m_index; ++j){
                printf("%c\t",empty);
            }

            // Print contents of second ( 6 jacobian entries )
            JacobianElement G2 = !swapped ? eq->getGB() : eq->getGA();
            printf("%g%c%g%c%g%c%g%c%g%c%g%c",
                G2.getSpatial().x(),tab,
                G2.getSpatial().y(),tab,
                G2.getSpatial().z(),tab,
                G2.getRotational().x(),tab,
                G2.getRotational().y(),tab,
                G2.getRotational().z(),tab);

            // Print empty until end of row
            for (int j = 6*(connB->m_index+1); j < getSystemMatrixCols(); ++j){
                printf("%c\t",empty);
            }

            if(i == eqs.size()-1)
                printf("]\n");
            else
                printf(";\n");
        }

        printf("D = [\n");
        for(int i=0; i<eqs.size(); ++i){
            Equation * eq = eqs[i];
            Connector * connA = eq->getConnA();
            Connector * connB = eq->getConnB();

            //printf("%d %d\n",connA->m_index,connB->m_index);

            int swapped = 0;
            if(connA->m_index > connB->m_index){
                Connector * temp = connA;
                connA = connB;
                connB = temp;
                swapped = 1;
            }

            // Print empty until first
            for (int j = 0; j < 6*connA->m_index; ++j){
                printf("%c\t",empty);
            }

            // Print contents of first ( 6 jacobian entries )
            JacobianElement G = !swapped ? eq->getddA() : eq->getddB();
            printf("%g%c%g%c%g%c%g%c%g%c%g%c",
                G.getSpatial().x(),tab,
                G.getSpatial().y(),tab,
                G.getSpatial().z(),tab,
                G.getRotational().x(),tab,
                G.getRotational().y(),tab,
                G.getRotational().z(),tab);

            // Print empty until second
            for (int j = 6*(connA->m_index+1); j < 6*connB->m_index; ++j){
                printf("%c\t",empty);
            }

            // Print contents of second ( 6 jacobian entries )
            JacobianElement G2 = !swapped ? eq->getddB() : eq->getddA();
            printf("%g%c%g%c%g%c%g%c%g%c%g%c",
                G2.getSpatial().x(),tab,
                G2.getSpatial().y(),tab,
                G2.getSpatial().z(),tab,
                G2.getRotational().x(),tab,
                G2.getRotational().y(),tab,
                G2.getRotational().z(),tab);

            // Print empty until end of row
            for (int j = 6*(connB->m_index+1); j < getSystemMatrixCols(); ++j){
                printf("%c\t",empty);
            }

            if(i == eqs.size()-1)
                printf("]\n");
            else
                printf(";\n");
        }

        printf("E = [\n");
        for (int i = 0; i < eqs.size(); ++i){ // Rows
            for (int j = 0; j < eqs.size(); ++j){ // Cols
                if(i==j)
                    printf("%g\t", eqs[i]->m_epsilon);
                else
                    printf("0\t");
            }
            if(i == eqs.size()-1)
                printf("]\n");
            else
                printf(";\n");
        }

        printf("S = [\n");
        for (int i = 0; i < eqs.size(); ++i){ // Rows
            for (int j = 0; j < eqs.size(); ++j){ // Cols

                // Find element i,j
                int found = 0;
                for(int k = 0; k < Srow.size(); ++k){
                    if(Srow[k] == i && Scol[k] == j){
                        printf("%g\t", Sval[k]);
                        found = 1;
                        break;
                    }
                }
                if(!found)
                    printf("%c\t",empty);
            }
            if(i == eqs.size()-1)
                printf("]\n");
            else
                printf(";\n");
        }
    }

    // convert vectors to arrays
    int * aSrow =    (int *)    malloc ((Srow.size()+1) * sizeof (int));
    int * aScol =    (int *)    malloc ((Scol.size()+1) * sizeof (int));
    double * aSval = (double *) malloc ((Sval.size()+1) * sizeof (double));
    for (int i = 0; i < Srow.size(); ++i){
        aSval[i] = Sval[i];
        aScol[i] = Scol[i];
        aSrow[i] = Srow[i];

        //printf("(%d,%d) = %g\n", Srow[i], Scol[i], Sval[i]);
    }

    void *Symbolic, *Numeric;
    double Info [UMFPACK_INFO], Control [UMFPACK_CONTROL];

    // Default control
    umfpack_di_defaults (Control) ;

    // convert to column form
    int nz = Sval.size(),       // Non-zeros
        n = eqs.size(),         // Number of equations
        nz1 = std::max(nz,1) ;  // ensure arrays are not of size zero.
    int * Ap = (int *) malloc ((n+1) * sizeof (int)) ;
    int * Ai = (int *) malloc (nz1 * sizeof (int)) ;
    double * lambda = (double *) malloc (n * sizeof (double)) ;
    double * Ax = (double *) malloc (nz1 * sizeof (double)) ;
    if (!Ap || !Ai || !Ax){
        fprintf(stderr, "out of memory\n") ;
    }

    if(printDebugInfo)
        printf("n=%d, nz=%d\n",n, nz);

    // Triplet form to column form
    int status = umfpack_di_triplet_to_col (n, n, nz, aSrow, aScol, aSval, Ap, Ai, Ax, (int *) NULL) ;
    if (status < 0){
        umfpack_di_report_status (Control, status) ;
        fprintf(stderr, "umfpack_di_triplet_to_col failed\n") ;
        exit(1);
    }

    // symbolic factorization
    status = umfpack_di_symbolic (n, n, Ap, Ai, Ax, &Symbolic, Control, Info) ;
    if (status < 0){
        umfpack_di_report_info (Control, Info) ;
        umfpack_di_report_status (Control, status) ;
        fprintf(stderr,"umfpack_di_symbolic failed\n") ;
        exit(1);
    }

    // numeric factorization
    status = umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, Control, Info) ;
    if (status < 0){
        umfpack_di_report_info (Control, Info) ;
        umfpack_di_report_status (Control, status) ;
        fprintf(stderr,"umfpack_di_numeric failed\n") ;
        exit(1);
    }

    // solve S*lambda = B
    status = umfpack_di_solve (UMFPACK_A, Ap, Ai, Ax, lambda, rhs, Numeric, Control, Info) ;
    umfpack_di_report_info (Control, Info) ;
    umfpack_di_report_status (Control, status) ;
    if (status < 0){
        fprintf(stderr,"umfpack_di_solve failed\n") ;
        exit(1);
    }

    // Set current connector forces to zero
    resetConstraintForces();

    // Store results
    // Remember that we need to divide lambda by the timestep size
    // f = G'*lambda
    for (int i = 0; i<eqs.size(); ++i){
        Equation * eq = eqs[i];
        double l = lambda[i] / eq->m_timeStep;

        JacobianElement GA = eq->getGA();
        JacobianElement GB = eq->getGB();
        Vec3 fA = GA.getSpatial()    * l;
        Vec3 tA = GA.getRotational() * l;
        Vec3 fB = GB.getSpatial()    * l;
        Vec3 tB = GB.getRotational() * l;

        // We are on row i in the matrix
        eq->getConnA()->m_force  += fA;
        eq->getConnA()->m_torque += tA;
        eq->getConnB()->m_force  += fB;
        eq->getConnB()->m_torque += tB;

        /*
        printf("forceA  += %g %g %g\n", fA[0], fA[1], fA[2]);
        printf("torqueA += %g %g %g\n", tA[0], tA[1], tA[2]);
        printf("forceB  += %g %g %g\n", fB[0], fB[1], fB[2]);
        printf("torqueB += %g %g %g\n", tB[0], tB[1], tB[2]);


        printf("   GAs = %g %g %g\n", GA.getSpatial()[0], GA.getSpatial()[1], GA.getSpatial()[2]);
        printf("   GBs = %g %g %g\n", GB.getSpatial()[0], GB.getSpatial()[1], GB.getSpatial()[2]);
        printf("   GAr = %g %g %g\n", GA.getRotational()[0], GA.getRotational()[1], GA.getRotational()[2]);
        printf("   GBr = %g %g %g\n", GB.getRotational()[0], GB.getRotational()[1], GB.getRotational()[2]);

        printf("\n");
        */
    }

    // Print matrices
    if(printDebugInfo){

        printf("RHS = [\n");
        for (int i = 0; i < eqs.size(); ++i){
            printf("%g\n",rhs[i]);
        }
        printf("]\n");

        printf("umfpackSolution = [\n");
        for (int i = 0; i < eqs.size(); ++i){
            printf("%g\n",lambda[i]);
        }
        printf("]\n");

        printf("octaveSolution = S \\ RHS\n");


        printf("Gt_lambda = [\n");
        int numSlaves = m_slaves.size();
        for(int i=0; i<numSlaves; ++i){
            int Nconns = m_slaves[i]->numConnectors();
            for(int j=0; j<Nconns; ++j){
                Connector * c = m_slaves[i]->getConnector(j);
                printf("%g\n%g\n%g\n%g\n%g\n%g\n",
                    c->m_force[0],
                    c->m_force[1],
                    c->m_force[2],
                    c->m_torque[0],
                    c->m_torque[1],
                    c->m_torque[2]);
            }
        }
        printf("]\n");
    }

    free(rhs);
    free(lambda);
    free(aSrow);
    free(aScol);
    free(aSval);
    free(Ap);
    free(Ai);
    free(Ax);
    umfpack_di_free_symbolic(&Symbolic);
    umfpack_di_free_numeric(&Numeric);
}