示例#1
0
Real
StressDivergenceRZ::computeQpOffDiagJacobian(unsigned int jvar)
{

  if ( _rdisp_coupled && jvar == _rdisp_var )
  {
    return calculateJacobian( _component, 0 );
  }
  else if ( _zdisp_coupled && jvar == _zdisp_var )
  {
    return calculateJacobian( _component, 1 );
  }
  else if ( _temp_coupled && jvar == _temp_var )
  {
    SymmTensor test;
    if (_component == 0)
    {
      test.xx() = _grad_test[_i][_qp](0);
      test.xy() = 0.5*_grad_test[_i][_qp](1);
      test.zz() = _test[_i][_qp] / _q_point[_qp](0);
    }
    else
    {
      test.xy() = 0.5*_grad_test[_i][_qp](0);
      test.yy() = _grad_test[_i][_qp](1);
    }
    return _d_stress_dT[_qp].doubleContraction(test) * _phi[_j][_qp];
  }

  return 0;
}
示例#2
0
Real
StressDivergenceRZTensors::computeQpOffDiagJacobian(unsigned int jvar)
{
  for (unsigned int i = 0; i < _ndisp; ++i)
  {
    if (jvar == _disp_var[i])
      return calculateJacobian(_component, i);
  }

  if (_temp_coupled && jvar == _temp_var)
  {
    Real jac = 0.0;
    if (_component == 0)
    {
      for (unsigned k = 0; k < LIBMESH_DIM; ++k)
        for (unsigned l = 0; l < LIBMESH_DIM; ++l)
          jac -= (_grad_test[_i][_qp](0) * _Jacobian_mult[_qp](0, 0, k, l) +
                  _test[_i][_qp] / _q_point[_qp](0) * _Jacobian_mult[_qp](2, 2, k, l) +
                  _grad_test[_i][_qp](1) * _Jacobian_mult[_qp](0, 1, k, l)) *
                 (*_deigenstrain_dT)[_qp](k, l);
      return jac * _phi[_j][_qp];
    }
    else if (_component == 1)
    {
      for (unsigned k = 0; k < LIBMESH_DIM; ++k)
        for (unsigned l = 0; l < LIBMESH_DIM; ++l)
          jac -= (_grad_test[_i][_qp](1) * _Jacobian_mult[_qp](1, 1, k, l) +
                  _grad_test[_i][_qp](0) * _Jacobian_mult[_qp](1, 0, k, l)) *
                 (*_deigenstrain_dT)[_qp](k, l);
      return jac * _phi[_j][_qp];
    }
  }

  return 0.0;
}
示例#3
0
void
FiniteStrainPlasticBase::checkJacobian()
{
  _console << "\n ++++++++++++++ \nChecking the Jacobian\n";
  outputAndCheckDebugParameters();

  RankFourTensor E_inv = _elasticity_tensor[_qp].invSymm();
  RankTwoTensor delta_dp = -E_inv*_fspb_debug_stress;

  std::vector<std::vector<Real> > jac;
  calculateJacobian(_fspb_debug_stress, _fspb_debug_intnl, _fspb_debug_pm, E_inv, jac);

  std::vector<std::vector<Real> > fdjac;
  fdJacobian(_fspb_debug_stress, _intnl_old[_qp], _fspb_debug_intnl, _fspb_debug_pm, delta_dp, E_inv, fdjac);

  _console << "Hand-coded Jacobian:\n";
  for (unsigned row = 0 ; row < jac.size() ; ++row)
  {
    for (unsigned col = 0 ; col < jac.size() ; ++col)
      _console << jac[row][col] << " ";
    _console << "\n";
  }

  _console << "Finite difference Jacobian:\n";
  for (unsigned row = 0 ; row < fdjac.size() ; ++row)
  {
    for (unsigned col = 0 ; col < fdjac.size() ; ++col)
      _console << fdjac[row][col] << " ";
    _console << "\n";
  }
}
void
MultiPlasticityDebugger::checkJacobian(const RankFourTensor & E_inv,
                                       const std::vector<Real> & intnl_old)
{
  Moose::err << "\n\n+++++++++++++++++++++\nChecking the Jacobian\n+++++++++++++++++++++\n";
  outputAndCheckDebugParameters();

  std::vector<bool> act;
  act.assign(_num_surfaces, true);
  std::vector<bool> deactivated_due_to_ld;
  deactivated_due_to_ld.assign(_num_surfaces, false);

  RankTwoTensor delta_dp = -E_inv * _fspb_debug_stress;

  std::vector<std::vector<Real>> jac;
  calculateJacobian(_fspb_debug_stress,
                    _fspb_debug_intnl,
                    _fspb_debug_pm,
                    E_inv,
                    act,
                    deactivated_due_to_ld,
                    jac);

  std::vector<std::vector<Real>> fdjac;
  fdJacobian(_fspb_debug_stress,
             intnl_old,
             _fspb_debug_intnl,
             _fspb_debug_pm,
             delta_dp,
             E_inv,
             false,
             fdjac);

  Real L2_numer = 0;
  Real L2_denom = 0;
  for (unsigned row = 0; row < jac.size(); ++row)
    for (unsigned col = 0; col < jac.size(); ++col)
    {
      L2_numer += Utility::pow<2>(jac[row][col] - fdjac[row][col]);
      L2_denom += Utility::pow<2>(jac[row][col] + fdjac[row][col]);
    }
  Moose::err << "\nRelative L2norm = " << std::sqrt(L2_numer / L2_denom) / 0.5 << "\n";

  Moose::err << "\nHand-coded Jacobian:\n";
  for (unsigned row = 0; row < jac.size(); ++row)
  {
    for (unsigned col = 0; col < jac.size(); ++col)
      Moose::err << jac[row][col] << " ";
    Moose::err << "\n";
  }

  Moose::err << "Finite difference Jacobian:\n";
  for (unsigned row = 0; row < fdjac.size(); ++row)
  {
    for (unsigned col = 0; col < fdjac.size(); ++col)
      Moose::err << fdjac[row][col] << " ";
    Moose::err << "\n";
  }
}
示例#5
0
void CQMathMatrixWidget::updateJacobianIfTabSelected()
{
  if (mpDataModel == NULL)
    return;

  CModel* pModel = mpDataModel->getModel();

  if (pModel == NULL)
    return;

  if (!mpTabWidgetJac->isVisible() && !mpTabWidgetJacRed->isVisible())
    return;

  try
    {
      // need to compile at this point otherwise elements might not be valid anymore
      pModel->compileIfNecessary(NULL);

      updateJacobianAnnotation(pModel);

      CMathContainer& container = pModel->getMathContainer();

      if (mpTabWidget->currentWidget() == mpTabWidgetJac)
        {
          calculateJacobian(mJacobian, &container, tableEigenValues, false, 1e-6);
          mpJacobianAnnotationWidget->setArrayAnnotation(mpJacobianAnn);
        }
      else if (mpTabWidget->currentWidget() == mpTabWidgetJacRed)
        {
          calculateJacobian(mJacobianRed, &container, tableEigenValuesRed, true, 1e-6);
          mpRedJacobianAnnotationWidget->setArrayAnnotation(mpJacobianAnnRed);
        }

    }
  catch (...)
    {
      // jacobian couldn't be calculated
      mpJacobianAnnotationWidget->setArrayAnnotation(NULL);
      mpRedJacobianAnnotationWidget->setArrayAnnotation(NULL);
    }
}
void
MultiPlasticityLinearSystem::nrStep(const RankTwoTensor & stress, const std::vector<Real> & intnl_old, const std::vector<Real> & intnl, const std::vector<Real> & pm, const RankFourTensor & E_inv, const RankTwoTensor & delta_dp, RankTwoTensor & dstress, std::vector<Real> & dpm, std::vector<Real> & dintnl, const std::vector<bool> & active, std::vector<bool> & deactivated_due_to_ld)
{
  // Calculate RHS and Jacobian
  std::vector<Real> rhs;
  calculateRHS(stress, intnl_old, intnl, pm, delta_dp, rhs, active, true, deactivated_due_to_ld);

  std::vector<std::vector<Real> > jac;
  calculateJacobian(stress, intnl, pm, E_inv, active, deactivated_due_to_ld, jac);


  // prepare for LAPACKgesv_ routine provided by PETSc
  int system_size = rhs.size();

  std::vector<double> a(system_size*system_size);
  // Fill in the a "matrix" by going down columns
  unsigned ind = 0;
  for (int col = 0 ; col < system_size ; ++col)
    for (int row = 0 ; row < system_size ; ++row)
      a[ind++] = jac[row][col];

  int nrhs = 1;
  std::vector<int> ipiv(system_size);
  int info;
  LAPACKgesv_(&system_size, &nrhs, &a[0], &system_size, &ipiv[0], &rhs[0], &system_size, &info);

  if (info != 0)
    mooseError("In solving the linear system in a Newton-Raphson process, the PETSC LAPACK gsev routine returned with error code " << info);



  // Extract the results back to dstress, dpm and dintnl
  std::vector<bool> active_not_deact(_num_surfaces);
  for (unsigned surface = 0 ; surface < _num_surfaces ; ++surface)
    active_not_deact[surface] = (active[surface] && !deactivated_due_to_ld[surface]);

  unsigned int dim = 3;
  ind = 0;

  for (unsigned i = 0 ; i < dim ; ++i)
    for (unsigned j = 0 ; j <= i ; ++j)
      dstress(i, j) = dstress(j, i) = rhs[ind++];
  dpm.assign(_num_surfaces, 0);
  for (unsigned surface = 0 ; surface < _num_surfaces ; ++surface)
    if (active_not_deact[surface])
      dpm[surface] = rhs[ind++];
  dintnl.assign(_num_models, 0);
  for (unsigned model = 0 ; model < _num_models ; ++model)
    if (anyActiveSurfaces(model, active_not_deact))
      dintnl[model] = rhs[ind++];

  mooseAssert(static_cast<int>(ind) == system_size, "Incorrect extracting of changes from NR solution in nrStep");
}
示例#7
0
		gmtl::Vec3f JacobianMatrix::calculateInverse(const Angle& angle, const gmtl::Vec3f& angular)
		{
			gmtl::Matrix33f matrixJ = calculateJacobian(angle);
	
			//gmtl::Matrix<float, 3, 1> velocityMatrix;
			//velocityMatrix[0][0] = velocity[0];
			//velocityMatrix[1][0] = velocity[1];
			//velocityMatrix[2][0] = velocity[2];

			//gmtl::Matrix<float, 3, 1> solution = matrixJ * velocityMatrix;
			//invert(matrixJ);
			return invert(matrixJ) * angular;//gmtl::Vec3f(solution[0][0], solution[1][0], solution[2][0]);
		}
示例#8
0
		gmtl::Vec3f JacobianMatrix::calculate(const Angle& angle, const gmtl::Vec3f& cartesian)
		{
			gmtl::Matrix33f matrixJ = calculateJacobian(angle);
	
			//gmtl::Matrix<float, 3, 1> velocityMatrix;
			//velocityMatrix[0][0] = velocity[0];
			//velocityMatrix[1][0] = velocity[1];
			//velocityMatrix[2][0] = velocity[2];

			//gmtl::Matrix<float, 3, 1> solution = matrixJ * velocityMatrix;
	
			return matrixJ * cartesian;//gmtl::Vec3f(solution[0][0], solution[1][0], solution[2][0]);
		}
示例#9
0
Real
StressDivergenceRZTensors::computeQpOffDiagJacobian(unsigned int jvar)
{
  for (unsigned int i = 0; i < _ndisp; ++i)
  {
    if (jvar == _disp_var[i])
      return calculateJacobian( _component, i);
  }

  if (_temp_coupled && jvar == _temp_var)
    return 0.0;

  return 0;
}
示例#10
0
void
FiniteStrainPlasticBase::nrStep(const RankTwoTensor & stress, const std::vector<Real> & intnl_old, const std::vector<Real> & intnl, const std::vector<Real> & pm, const RankFourTensor & E_inv, const RankTwoTensor & delta_dp, RankTwoTensor & dstress, std::vector<Real> & dpm, std::vector<Real> & dintnl)
{
  // Calculate RHS and Jacobian
  std::vector<Real> rhs;
  calculateRHS(stress, intnl_old, intnl, pm, delta_dp, rhs);

  std::vector<std::vector<Real> > jac;
  calculateJacobian(stress, intnl, pm, E_inv, jac);

  // prepare for LAPACKgesv_ routine provided by PETSc (at least since PETSc 3.0.0)
  int system_size = rhs.size();

  std::vector<double> a(system_size*system_size);
  // Fill in the a "matrix" by going down columns
  unsigned ind = 0;
  for (int col = 0 ; col < system_size ; ++col)
    for (int row = 0 ; row < system_size ; ++row)
      a[ind++] = jac[row][col];

  int nrhs = 1;
  std::vector<int> ipiv(system_size);
  int info;
  LAPACKgesv_(&system_size, &nrhs, &a[0], &system_size, &ipiv[0], &rhs[0], &system_size, &info);

  if (info != 0)
    mooseError("In solving the linear system in a Newton-Raphson process, the PETSC LAPACK gsev routine returned with error code " << info);

  // Extract the results back to dstress, dpm and dintnl
  unsigned int dim = 3;
  ind = 0;
  for (unsigned i = 0 ; i < dim ; ++i)
    for (unsigned j = 0 ; j <= i ; ++j)
      dstress(i, j) = dstress(j, i) = rhs[ind++];
  dpm.resize(numberOfYieldFunctions());
  for (unsigned alpha = 0 ; alpha < numberOfYieldFunctions() ; ++alpha)
    dpm[alpha] = rhs[ind++];
  dintnl.resize(numberOfInternalParameters());
  for (unsigned a = 0 ; a < numberOfInternalParameters() ; ++a)
    dintnl[a] = rhs[ind++];
}
示例#11
0
Real
StressDivergenceRZ::computeQpJacobian()
{
  return calculateJacobian( _component, _component );
}
示例#12
0
void
MultiPlasticityDebugger::checkSolution(const RankFourTensor & E_inv)
{
  Moose::err << "\n\n+++++++++++++++++++++\nChecking the Solution\n";
  Moose::err << "(Ie, checking Ax = b)\n+++++++++++++++++++++\n";
  outputAndCheckDebugParameters();

  std::vector<bool> act;
  act.assign(_num_surfaces, true);
  std::vector<bool> deactivated_due_to_ld;
  deactivated_due_to_ld.assign(_num_surfaces, false);

  RankTwoTensor delta_dp = -E_inv * _fspb_debug_stress;

  std::vector<Real> orig_rhs;
  calculateRHS(_fspb_debug_stress,
               _fspb_debug_intnl,
               _fspb_debug_intnl,
               _fspb_debug_pm,
               delta_dp,
               orig_rhs,
               act,
               true,
               deactivated_due_to_ld);

  Moose::err << "\nb = ";
  for (unsigned i = 0; i < orig_rhs.size(); ++i)
    Moose::err << orig_rhs[i] << " ";
  Moose::err << "\n\n";

  std::vector<std::vector<Real>> jac_coded;
  calculateJacobian(_fspb_debug_stress,
                    _fspb_debug_intnl,
                    _fspb_debug_pm,
                    E_inv,
                    act,
                    deactivated_due_to_ld,
                    jac_coded);

  Moose::err
      << "Before checking Ax=b is correct, check that the Jacobians given below are equal.\n";
  Moose::err
      << "The hand-coded Jacobian is used in calculating the solution 'x', given 'b' above.\n";
  Moose::err << "Note that this only includes degrees of freedom that aren't deactivated due to "
                "linear dependence.\n";
  Moose::err << "Hand-coded Jacobian:\n";
  for (unsigned row = 0; row < jac_coded.size(); ++row)
  {
    for (unsigned col = 0; col < jac_coded.size(); ++col)
      Moose::err << jac_coded[row][col] << " ";
    Moose::err << "\n";
  }

  deactivated_due_to_ld.assign(_num_surfaces,
                               false); // this potentially gets changed by nrStep, below
  RankTwoTensor dstress;
  std::vector<Real> dpm;
  std::vector<Real> dintnl;
  nrStep(_fspb_debug_stress,
         _fspb_debug_intnl,
         _fspb_debug_intnl,
         _fspb_debug_pm,
         E_inv,
         delta_dp,
         dstress,
         dpm,
         dintnl,
         act,
         deactivated_due_to_ld);

  std::vector<bool> active_not_deact(_num_surfaces);
  for (unsigned surface = 0; surface < _num_surfaces; ++surface)
    active_not_deact[surface] = !deactivated_due_to_ld[surface];

  std::vector<Real> x;
  x.assign(orig_rhs.size(), 0);
  unsigned ind = 0;
  for (unsigned i = 0; i < 3; ++i)
    for (unsigned j = 0; j <= i; ++j)
      x[ind++] = dstress(i, j);
  for (unsigned surface = 0; surface < _num_surfaces; ++surface)
    if (active_not_deact[surface])
      x[ind++] = dpm[surface];
  for (unsigned model = 0; model < _num_models; ++model)
    if (anyActiveSurfaces(model, active_not_deact))
      x[ind++] = dintnl[model];

  mooseAssert(ind == orig_rhs.size(),
              "Incorrect extracting of changes from NR solution in the "
              "finite-difference checking of nrStep");

  Moose::err << "\nThis yields x =";
  for (unsigned i = 0; i < orig_rhs.size(); ++i)
    Moose::err << x[i] << " ";
  Moose::err << "\n";

  std::vector<std::vector<Real>> jac_fd;
  fdJacobian(_fspb_debug_stress,
             _fspb_debug_intnl,
             _fspb_debug_intnl,
             _fspb_debug_pm,
             delta_dp,
             E_inv,
             true,
             jac_fd);

  Moose::err << "\nThe finite-difference Jacobian is used to multiply by this 'x',\n";
  Moose::err << "in order to check that the solution is correct\n";
  Moose::err << "Finite-difference Jacobian:\n";
  for (unsigned row = 0; row < jac_fd.size(); ++row)
  {
    for (unsigned col = 0; col < jac_fd.size(); ++col)
      Moose::err << jac_fd[row][col] << " ";
    Moose::err << "\n";
  }

  Real L2_numer = 0;
  Real L2_denom = 0;
  for (unsigned row = 0; row < jac_coded.size(); ++row)
    for (unsigned col = 0; col < jac_coded.size(); ++col)
    {
      L2_numer += Utility::pow<2>(jac_coded[row][col] - jac_fd[row][col]);
      L2_denom += Utility::pow<2>(jac_coded[row][col] + jac_fd[row][col]);
    }
  Moose::err << "Relative L2norm of the hand-coded and finite-difference Jacobian is "
             << std::sqrt(L2_numer / L2_denom) / 0.5 << "\n";

  std::vector<Real> fd_times_x;
  fd_times_x.assign(orig_rhs.size(), 0);
  for (unsigned row = 0; row < orig_rhs.size(); ++row)
    for (unsigned col = 0; col < orig_rhs.size(); ++col)
      fd_times_x[row] += jac_fd[row][col] * x[col];

  Moose::err << "\n(Finite-difference Jacobian)*x =\n";
  for (unsigned i = 0; i < orig_rhs.size(); ++i)
    Moose::err << fd_times_x[i] << " ";
  Moose::err << "\n";
  Moose::err << "Recall that b = \n";
  for (unsigned i = 0; i < orig_rhs.size(); ++i)
    Moose::err << orig_rhs[i] << " ";
  Moose::err << "\n";

  L2_numer = 0;
  L2_denom = 0;
  for (unsigned i = 0; i < orig_rhs.size(); ++i)
  {
    L2_numer += Utility::pow<2>(orig_rhs[i] - fd_times_x[i]);
    L2_denom += Utility::pow<2>(orig_rhs[i] + fd_times_x[i]);
  }
  Moose::err << "\nRelative L2norm of these is " << std::sqrt(L2_numer / L2_denom) / 0.5 << "\n";
}
int main(int argc, char* argv[])
{
	//--This first declaration is included for software engineering reasons: allow main method to control flow of data
	//create function pointer for calculateDependentVariable
	//We want to do this so that calculateJacobian can call calculateDependentVariables as it needs to,
	//but we explicitly give it this authority from the main method
	void (*yourCalculateDependentVariables)(const Teuchos::SerialDenseMatrix<int, std::complex<double> >&, const Teuchos::SerialDenseVector<int, std::complex<double> >&, Teuchos::SerialDenseVector<int, std::complex<double> >&);
	yourCalculateDependentVariables = &calculateDependentVariables;

	//Create an object to allow access to LAPACK using a library found in Trilinos
	//
	Teuchos::LAPACK<int, std::complex<double> > Teuchos_LAPACK_Object;	

	//The problem being solved is to find the intersection of three infinite paraboloids:
	//(x-1)^2 + y^2 + z = 0
	//x^2 + y^2 -(z+1) = 0
	//x^2 + y^2 +(z-1) = 0
	//
	//They should intersect at the point (1, 0, 0)
	Teuchos::SerialDenseMatrix<int, std::complex<double> > offsets(NUMDIMENSIONS, NUMDIMENSIONS); 
	offsets(0,0) = 1.0;
	offsets(1,2) = 1.0;
	offsets(2,2) = 1.0;

	//We need to initialize the target vectors and provide an initial guess
	Teuchos::SerialDenseVector<int, std::complex<double> > targetsDesired(NUMDIMENSIONS);
	Teuchos::SerialDenseVector<int, std::complex<double> > targetsCalculated(NUMDIMENSIONS);
	Teuchos::SerialDenseVector<int, std::complex<double> > unperturbedTargetsCalculated(NUMDIMENSIONS);
	Teuchos::SerialDenseVector<int, std::complex<double> > currentGuess(NUMDIMENSIONS);
	Teuchos::SerialDenseVector<int, std::complex<double> > guessAdjustment(NUMDIMENSIONS);

	currentGuess[0] = 2.0;
	currentGuess[1] = 1.0;
	currentGuess[2] = 1.0;
	//Place to store our tangent-stiffness matrix or Jacobian
	//One element for every combination of dependent variable with independent variable
	Teuchos::SerialDenseMatrix<int, std::complex<double> > jacobian(NUMDIMENSIONS, NUMDIMENSIONS);

	int count = 0;
	double error = 1.0E5;

	std::cout << "Running Forward Difference Example" << std::endl;
	while(count < MAXITERATIONS and error > ERRORTOLLERANCE)
	{


		//Calculate Jacobian tangent to currentGuess point
		//at the same time, an unperturbed targetsCalculated is, well, calculated
		calculateJacobian(offsets,
				  jacobian,
				  targetsCalculated,
				  unperturbedTargetsCalculated,
				  currentGuess,
                                  yourCalculateDependentVariables);


		//Compute a guessChange and immediately set the currentGuess equal to the guessChange
 		updateGuess(currentGuess,
			    targetsCalculated,
			    jacobian,
			    Teuchos_LAPACK_Object);


		//Compute F(x) with the updated, currentGuess
		calculateDependentVariables(offsets,
				            currentGuess,
			       		    targetsCalculated);	


		//Calculate the L2 norm of Ftarget - F(xCurrentGuess)
		calculateResidual(targetsDesired,
			          targetsCalculated,
			  	  error);	  


		count ++;
		//If we have converged, or if we have exceeded our alloted number of iterations, discontinue the loop
		std::cout << "Residual Error: " << error << std::endl;
	}
	
	std::cout << "******************************************" << std::endl;
	std::cout << "Number of iterations: " << count << std::endl;
	std::cout << "Final guess:\n x, y, z\n " << currentGuess[0] << ", " << currentGuess[1] << ", " << currentGuess[2] << std::endl;
	std::cout << "Error tollerance: " << ERRORTOLLERANCE << std::endl;
	std::cout << "Final error: " << error << std::endl;
	std::cout << "--program complete--" << std::endl;

	return 0;
}
int main(int argc, char* argv[])
{
	//--This first declaration is included for software engineering reasons: allow main method to control flow of data
	//create function pointer for calculateDependentVariable
	//We want to do this so that calculateJacobian can call calculateDependentVariables as it needs to,
	//but we explicitly give it this authority from the main method
	void (*yourCalculateDependentVariables)(const arma::Mat<std::complex<double> >&, const arma::Col<std::complex<double> >&, arma::Col<std::complex<double> >&);
	yourCalculateDependentVariables = &calculateDependentVariables;

	//The problem being solved is to find the intersection of three infinite paraboloids:
	//(x-1)^2 + y^2 + z = 0
	//x^2 + y^2 -(z+1) = 0
	//x^2 + y^2 +(z-1) = 0
	//
	//They should intersect at the point (1, 0, 0)
	arma::Mat<std::complex<double> > offsets(NUMDIMENSIONS, NUMDIMENSIONS); 
	offsets.fill(0.0);
	offsets.col(0)[0] = 1.0;
	offsets.col(2)[1] = 1.0;
	offsets.col(2)[2] = 1.0;

	//We need to initialize the target vectors and provide an initial guess
	arma::Col<std::complex<double> > targetsDesired(NUMDIMENSIONS);
	targetsDesired.fill(0.0);

	arma::Col<std::complex<double> > targetsCalculated(NUMDIMENSIONS);
	targetsCalculated.fill(0.0);

	arma::Col<double> realTargetsCalculated(NUMDIMENSIONS);
	realTargetsCalculated.fill(0.0);

	arma::Col<std::complex<double> > currentGuess(NUMDIMENSIONS);
	currentGuess.fill(2.0);

	//Place to store our tangent-stiffness matrix or Jacobian
	//One element for every combination of dependent variable with independent variable
	arma::Mat<double> jacobian(NUMDIMENSIONS, NUMDIMENSIONS);
	jacobian.fill(0.0);

	int count = 0;
	double error = 1.0E5;

	std::cout << "Running complex step example ................" << std::endl;
	while(count < MAXITERATIONS and error > ERRORTOLLERANCE)
	{

		//Calculate Jacobian tangent to currentGuess point
		//at the same time, an unperturbed targetsCalculated is, well, calculated
		calculateJacobian(offsets,
				  jacobian,
				  targetsCalculated,
				  currentGuess,
                                  yourCalculateDependentVariables);

		//Compute a new currentGuess 
		updateGuess(currentGuess,
			    realTargetsCalculated,
			    targetsCalculated,
			    jacobian);

		//Compute F(x) with the updated, currentGuess
		calculateDependentVariables(offsets,
				            currentGuess,
			       		    targetsCalculated);	

		//Calculate the L2 norm of Ftarget - F(xCurrentGuess)
		calculateResidual(targetsDesired,
			          targetsCalculated,
			  	  error);	  

		count ++;
		//If we have converged, or if we have exceeded our alloted number of iterations, discontinue the loop
		std::cout << "Residual Error: " << error << std::endl;
	}
	
	std::cout << "******************************************" << std::endl;
	std::cout << "Number of iterations: " << count << std::endl;
	std::cout << "Final guess:\n x, y, z\n" << arma::real(currentGuess.t());
	std::cout << "Error tollerance: " << ERRORTOLLERANCE << std::endl;
	std::cout << "Final error: " << error << std::endl;
	std::cout << "--program complete--" << std::endl;

	return 0;
}
Real
StressDivergenceRSphericalTensors::computeQpJacobian()
{
  return calculateJacobian(_component, _component);
}