void
MiniTensorVector<T, N>::
axpy(T const alpha, Vector<T> const & x)
{
  Intrepid2::Vector<T, N> const
  xval = MTfromROL<T, N>(x);

  auto const
  dim = xval.get_dimension();

  assert(vector_.get_dimension() == dim);

  for (Intrepid2::Index i{0}; i < dim; ++i) {
    vector_(i) += alpha * xval(i);
  }
}
Intrepid2::Vector<T, N>
CP::ResidualSlipNLS<NumDimT, NumSlipT, EvalT>::gradient(
    Intrepid2::Vector<T, N> const & x)
{
  // Get a convenience reference to the failed flag in case it is used more
  // than once.
  bool &
  failed = Base::failed;

  // Tensor mechanical state variables
  Intrepid2::Tensor<T, NumDimT>
  Fp_np1(num_dim_);

  Intrepid2::Tensor<T, NumDimT>
  Lp_np1(num_dim_);

  Intrepid2::Tensor<T, NumDimT>
  sigma_np1(num_dim_);

  Intrepid2::Tensor<T, NumDimT>
  S_np1(num_dim_);

  // Slip system state variables
  Intrepid2::Vector<T, NumSlipT>
  state_hardening_np1(num_slip_);

  Intrepid2::Vector<T, NumSlipT>
  slip_resistance(num_slip_);

  Intrepid2::Vector<T, NumSlipT>
  slip_np1(num_slip_);

  Intrepid2::Vector<T, NumSlipT>
  slip_computed(num_slip_);

  Intrepid2::Vector<T, NumSlipT>
  shear_np1(num_slip_);

  Intrepid2::Vector<T, NumSlipT>
  rate_slip(num_slip_);

  auto const
  num_unknowns = x.get_dimension();

  Intrepid2::Vector<T, N>
  residual(num_unknowns);

  // Return immediately if something failed catastrophically.
  if (failed == true) {
    residual.fill(Intrepid2::ZEROS);
    return residual;
  }

  Intrepid2::Tensor<T, NumDimT> const
  F_np1_peeled = LCM::peel_tensor<EvalT, T, N, NumDimT>()(F_np1_);

  Intrepid2::Tensor4<T, NumDimT> const
  C_peeled = LCM::peel_tensor4<EvalT, T, N, NumDimT>()(C_);

  for (int i = 0; i< num_slip_; ++i){
    slip_np1[i] = x[i];
  }

  if(dt_ > 0.0){
    rate_slip = (slip_np1 - slip_n_) / dt_;
  }
  else{
    rate_slip.fill(Intrepid2::ZEROS);
  }

  // Ensure that the slip increment is bounded
   if (Intrepid2::norm(rate_slip * dt_) > 1.0) {
       failed =  true;
       return residual;
   }

  // Compute Lp_np1, and Fp_np1
  CP::applySlipIncrement<NumDimT, NumSlipT, T>(
      slip_systems_,
      dt_,
      slip_n_,
      slip_np1,
      Fp_n_,
      Lp_np1,
      Fp_np1);

  // Compute sigma_np1, S_np1, and shear_np1
  CP::computeStress<NumDimT, NumSlipT, T>(
      slip_systems_,
      C_peeled,
      F_np1_peeled,
      Fp_np1,
      sigma_np1,
      S_np1,
      shear_np1);

  // Compute state_hardening_np1
  CP::updateHardness<NumDimT, NumSlipT, T>(
      slip_systems_,
      slip_families_,
      dt_,
      rate_slip,
      state_hardening_n_,
      state_hardening_np1,
      slip_resistance);

  // Compute slips
  CP::updateSlip<NumDimT, NumSlipT, T>(
      slip_systems_,
      slip_families_,
      dt_,
      slip_resistance,
      shear_np1,
      slip_n_,
      slip_computed);

  for (int i = 0; i< num_slip_; ++i){
    residual[i] = slip_np1[i] - slip_computed[i];
  }


  // ***** Residual scaling done below is commented out for now since it is in a preliminary stage.  

  // RealType
  // norm_resid = Sacado::ScalarValue<T>::eval(Intrepid2::norm(residual));

  // RealType
  // max_tol = std::numeric_limits<RealType>::max();
  
  // if (norm_resid > 0.5 * std::pow(max_tol, 1.0 / 10.0)) {
    
  //   residual *= 1.0 / norm_resid;
    
  // }

  return residual;
}
void FerroicModel<EvalT>::
computeState(
      const Intrepid2::Tensor<ScalarT, FM::THREE_D>& x,
      const Intrepid2::Vector<ScalarT, FM::THREE_D>& E,
      const Teuchos::Array<RealType>& oldfractions,
            Intrepid2::Tensor<ScalarT, FM::THREE_D>& X,
            Intrepid2::Vector<ScalarT, FM::THREE_D>& D,
            Teuchos::Array<ScalarT>& newfractions)
/******************************************************************************/
{

  // create non-linear system
  //
  using NLS = FM::DomainSwitching<EvalT>;
  NLS domainSwitching(crystalVariants, transitions, tBarriers, 
                      oldfractions, aMatrix, x, E, /* dt= */ 1.0);
  
  // solution variable
  //
  Intrepid2::Vector<ScalarT,FM::MAX_TRNS> xi;

  // solve for xi
  //
  switch (m_integrationType){
        
    default:
    break;

    case FM::IntegrationType::EXPLICIT:
    {

      switch (m_explicitMethod){
  
        default:
        break;

        case FM::ExplicitMethod::SCALED_DESCENT:
        {
          FM::ScaledDescent(domainSwitching, xi);
        }
        case FM::ExplicitMethod::DESCENT_NORM:
        {
          FM::DescentNorm(domainSwitching, xi);
        }
      }
    }
 
    case FM::IntegrationType::IMPLICIT:
    {

      // create minimizer
      using ValueT = typename Sacado::ValueType<ScalarT>::type;
      using MIN = Intrepid2::Minimizer<ValueT, MAX_TRNS>;
      MIN minimizer;

      // create stepper
      using STEP = Intrepid2::StepBase<NLS, ValueT, MAX_TRNS>;
      std::unique_ptr<STEP> 
        pstep = Intrepid2::stepFactory<NLS, ValueT, MAX_TRNS>(m_step_type);
      STEP &step = *pstep;

      // create solution vector with initial guess
      int ntrans = domainSwitching.getNumStates();
      xi.set_dimension(ntrans);
      for(int itrans=0; itrans<ntrans; itrans++)
        xi(itrans) = Sacado::ScalarValue<ScalarT>::eval(0.0);

      // solve
      LCM::MiniSolver<MIN, STEP, NLS, EvalT, MAX_TRNS>
        mini_solver(minimizer, step, domainSwitching, xi);
    }
  }

  // update based on new xi values
  //

}