void panzer::EquationSet_DefaultImpl<EvalT>::
buildAndRegisterDOFProjectionsToIPEvaluators(PHX::FieldManager<panzer::Traits>& fm,
                                             const panzer::FieldLayoutLibrary& fl,
                                             const Teuchos::RCP<panzer::IntegrationRule>& ir,
                                             const Teuchos::Ptr<const panzer::LinearObjFactory<panzer::Traits> > & lof,
                                             const Teuchos::ParameterList& user_data) const
{
  using Teuchos::ParameterList;
  using Teuchos::RCP;
  using Teuchos::rcp;

  Teuchos::RCP<const panzer::UniqueGlobalIndexerBase> globalIndexer;
  if(lof!=Teuchos::null) 
    globalIndexer = lof->getUniqueGlobalIndexerBase();
  
  // DOFs: Scalar value @ basis --> Scalar value @ IP 
  for (DescriptorIterator dof_iter = m_provided_dofs_desc.begin(); dof_iter != m_provided_dofs_desc.end(); ++dof_iter) {

    ParameterList p;
    p.set("Name", dof_iter->first);
    p.set("Basis", fl.lookupLayout(dof_iter->first));
    p.set("IR", ir);

    if(globalIndexer!=Teuchos::null) {
      // build the offsets for this field
      int fieldNum = globalIndexer->getFieldNum(dof_iter->first);
      RCP<const std::vector<int> > offsets = 
          rcp(new std::vector<int>(globalIndexer->getGIDFieldOffsets(m_block_id,fieldNum)));
      p.set("Jacobian Offsets Vector", offsets);
    }
    // else default to the slow DOF call
    
    RCP< PHX::Evaluator<panzer::Traits> > op = 
      rcp(new panzer::DOF<EvalT,panzer::Traits>(p));
    
    this->template registerEvaluator<EvalT>(fm, op);
  }

  // Gradients of DOFs: Scalar value @ basis --> Vector value @ IP

  for(typename std::map<std::string,DOFDescriptor>::const_iterator itr=m_provided_dofs_desc.begin();
      itr!=m_provided_dofs_desc.end();++itr) {
    
    if(itr->second.basis->supportsGrad()) {
      
      // is gradient required for this variable
      if(!itr->second.grad.first) 
        continue; // its not required, quit the loop

      const std::string dof_name =      itr->first;
      const std::string dof_grad_name = itr->second.grad.second;

      ParameterList p;
      p.set("Name", dof_name);
      p.set("Gradient Name", dof_grad_name);
      p.set("Basis", fl.lookupLayout(dof_name)); 
      p.set("IR", ir);
      
      RCP< PHX::Evaluator<panzer::Traits> > op = 
        rcp(new panzer::DOFGradient<EvalT,panzer::Traits>(p));

      this->template registerEvaluator<EvalT>(fm, op);
    }
  }

  // Curl of DOFs: Vector value @ basis --> Vector value @ IP (3D) or Scalar value @ IP (2D)

  for(typename std::map<std::string,DOFDescriptor>::const_iterator itr=m_provided_dofs_desc.begin();
      itr!=m_provided_dofs_desc.end();++itr) {
    
    if(itr->second.basis->supportsCurl()) {

      // is curl required for this variable
      if(!itr->second.curl.first) 
        continue; // its not required, quit the loop

      const std::string dof_name =      itr->first;
      const std::string dof_curl_name = itr->second.curl.second;

      ParameterList p;
      p.set("Name", dof_name);
      p.set("Curl Name", dof_curl_name);
      p.set("Basis", fl.lookupLayout(dof_name)); 
      p.set("IR", ir);

      // this will help accelerate the DOFCurl evaluator when Jacobians are needed
      if(globalIndexer!=Teuchos::null) {
        // build the offsets for this field
        int fieldNum = globalIndexer->getFieldNum(dof_name);
        RCP<const std::vector<int> > offsets = 
            rcp(new std::vector<int>(globalIndexer->getGIDFieldOffsets(m_block_id,fieldNum)));
        p.set("Jacobian Offsets Vector", offsets);
      }
      // else default to the slow DOF call
    
      
      RCP< PHX::Evaluator<panzer::Traits> > op = 
        rcp(new panzer::DOFCurl<EvalT,panzer::Traits>(p));

      this->template registerEvaluator<EvalT>(fm, op);
    }

  }

  // Div of DOFs: Vector value @ basis --> Scalar value @ IP

  for(typename std::map<std::string,DOFDescriptor>::const_iterator itr=m_provided_dofs_desc.begin();
      itr!=m_provided_dofs_desc.end();++itr) {

    if(itr->second.basis->supportsDiv()) {

      // is div required for this variable
      if(!itr->second.div.first) 
        continue; // its not required, quit the loop

      const std::string dof_name =      itr->first;
      const std::string dof_div_name = itr->second.div.second;

      ParameterList p;
      p.set("Name", dof_name);
      p.set("Div Name", dof_div_name);
      p.set("Basis", fl.lookupLayout(dof_name)); 
      p.set("IR", ir);

      // this will help accelerate the DOFDiv evaluator when Jacobians are needed
      if(globalIndexer!=Teuchos::null) {
        // build the offsets for this field
        int fieldNum = globalIndexer->getFieldNum(dof_name);
        RCP<const std::vector<int> > offsets = 
            rcp(new std::vector<int>(globalIndexer->getGIDFieldOffsets(m_block_id,fieldNum)));
        p.set("Jacobian Offsets Vector", offsets);
      }
      // else default to the slow DOF call
    
      
      RCP< PHX::Evaluator<panzer::Traits> > op = 
        rcp(new panzer::DOFDiv<EvalT,panzer::Traits>(p));

      this->template registerEvaluator<EvalT>(fm, op);
    }
  }

  // Time derivative of DOFs: Scalar value @ basis --> Scalar value @ IP 
  for(typename std::map<std::string,DOFDescriptor>::const_iterator itr=m_provided_dofs_desc.begin();
      itr!=m_provided_dofs_desc.end();++itr) {
    // is td required for this variable
    if(!itr->second.timeDerivative.first) 
      continue; // its not required, quit the loop

    const std::string td_name = itr->second.timeDerivative.second;

    ParameterList p;
    p.set("Name", td_name);
    p.set("Basis", fl.lookupLayout(itr->first)); 
    p.set("IR", ir);

    if(globalIndexer!=Teuchos::null) {
      // build the offsets for this field
      int fieldNum = globalIndexer->getFieldNum(itr->first);
      RCP<const std::vector<int> > offsets = 
          rcp(new std::vector<int>(globalIndexer->getGIDFieldOffsets(m_block_id,fieldNum)));
      p.set("Jacobian Offsets Vector", offsets);
    }
    // else default to the slow DOF call

    // set the orientiation field name explicitly if orientations are
    // required for the basis
    if(itr->second.basis->requiresOrientations())
      p.set("Orientation Field Name", itr->first+" Orientation");
    
    RCP< PHX::Evaluator<panzer::Traits> > op = 
      rcp(new panzer::DOF<EvalT,panzer::Traits>(p));
    
    this->template registerEvaluator<EvalT>(fm, op);
  }

}
Teuchos::RCP< std::vector< Teuchos::RCP<PHX::Evaluator<panzer::Traits> > > >
user_app::MyModelFactory<EvalT>::
buildClosureModels(const std::string& model_id,
                   const Teuchos::ParameterList& models,
                   const panzer::FieldLayoutLibrary& fl,
                   const Teuchos::RCP<panzer::IntegrationRule>& ir,
                   const Teuchos::ParameterList& default_params,
                   const Teuchos::ParameterList& user_data,
                   const Teuchos::RCP<panzer::GlobalData>& global_data,
                   PHX::FieldManager<panzer::Traits>& fm) const
{

    using std::string;
    using std::vector;
    using Teuchos::RCP;
    using Teuchos::rcp;
    using Teuchos::ParameterList;
    using PHX::Evaluator;

    RCP< vector< RCP<Evaluator<panzer::Traits> > > > evaluators =
        rcp(new vector< RCP<Evaluator<panzer::Traits> > > );

    if (!models.isSublist(model_id)) {
        models.print(std::cout);
        std::stringstream msg;
        msg << "Falied to find requested model, \"" << model_id
            << "\", for equation set:\n" << std::endl;
        TEUCHOS_TEST_FOR_EXCEPTION(!models.isSublist(model_id), std::logic_error, msg.str());
    }

    std::vector<Teuchos::RCP<const panzer::PureBasis> > bases;
    fl.uniqueBases(bases);

    const ParameterList& my_models = models.sublist(model_id);

    for (ParameterList::ConstIterator model_it = my_models.begin();
            model_it != my_models.end(); ++model_it) {

        bool found = false;

        const std::string key = model_it->first;
        ParameterList input;
        const Teuchos::ParameterEntry& entry = model_it->second;
        const ParameterList& plist = Teuchos::getValue<Teuchos::ParameterList>(entry);

        if (plist.isType<std::string>("Type")) {

            if (plist.get<std::string>("Type") == "Parameter") {
                TEUCHOS_ASSERT(!plist.isParameter("Value"));
                // Defaults for backward compatibility
                std::string parameter_name = key;
                std::string field_name = key;
                if (plist.isType<std::string>("Parameter Name"))
                    parameter_name = plist.get<std::string>("Parameter Name");
                if (plist.isType<std::string>("Field Name"))
                    field_name = plist.get<std::string>("Field Name");

                {   // at IP
                    RCP< Evaluator<panzer::Traits> > e =
                        rcp(new panzer::Parameter<EvalT,panzer::Traits>(parameter_name,field_name,ir->dl_scalar,*global_data->pl));
                    evaluators->push_back(e);
                }

                for (std::vector<Teuchos::RCP<const panzer::PureBasis> >::const_iterator basis_itr = bases.begin();
                        basis_itr != bases.end(); ++basis_itr) { // at BASIS
                    Teuchos::RCP<const panzer::BasisIRLayout> basis = basisIRLayout(*basis_itr,*ir);
                    RCP< Evaluator<panzer::Traits> > e =
                        rcp(new panzer::Parameter<EvalT,panzer::Traits>(parameter_name,field_name,basis->functional,*global_data->pl));
                    evaluators->push_back(e);
                }

                found = true;

                continue;
            }
            else if (plist.get<std::string>("Type") == "Distributed Parameter") {
                // sanity check
                TEUCHOS_ASSERT(distr_param_lof!=Teuchos::null);

                // build a nodal basis
                Teuchos::RCP<const panzer::PureBasis> nodal_basis
                    = Teuchos::rcp(new panzer::PureBasis("HGrad",1,bases[0]->numCells(),
                                   bases[0]->getCellTopology()));

                {
                    Teuchos::RCP<std::vector<std::string> > dof_names = Teuchos::rcp(new std::vector<std::string>);
                    dof_names->push_back(key);

                    ParameterList p("Gather");
                    p.set("Basis", nodal_basis);
                    p.set("DOF Names", dof_names);
                    p.set("Indexer Names", dof_names);
                    p.set("Sensitivities Name", key);
                    p.set("Disable Sensitivities", false);
                    p.set("Gather Seed Index", 0);
                    p.set("Global Data Key", key);

                    RCP< PHX::Evaluator<panzer::Traits> > e = distr_param_lof->buildGatherDomain<EvalT>(p);

                    evaluators->push_back(e);
                }

                {
                    ParameterList p;
                    p.set("Name", key);
                    p.set("Basis", basisIRLayout(nodal_basis,*ir));
                    p.set("IR", ir);

                    RCP< PHX::Evaluator<panzer::Traits> > e = rcp(new panzer::DOF<EvalT,panzer::Traits>(p));

                    evaluators->push_back(e);
                }

                found = true;
            }
            else if (plist.get<std::string>("Type") == "Product") {
                RCP<std::vector<std::string> > valuesNames = rcp(new std::vector<std::string>);
                // Tokenize a string, put tokens in a vector
                panzer::StringTokenizer(*valuesNames,plist.get<std::string>("Term Names"));
                double scaling = 1.0;
                if(plist.isType<double>("Scaling"))
                    scaling = plist.get<double>("Scaling");

                {
                    Teuchos::ParameterList input;
                    input.set("Scaling", scaling);
                    input.set("Product Name", key);
                    input.set("Values Names", valuesNames);
                    input.set("Data Layout", ir->dl_scalar);

                    RCP< panzer::Product<EvalT,panzer::Traits> > e =
                        rcp(new panzer::Product<EvalT,panzer::Traits>(input));
                    evaluators->push_back(e);
                }

                found = true;
            }

        }
        else if (plist.isType<double>("Value")) {
            {   // at IP
                input.set("Name", key);
                input.set("Value", plist.get<double>("Value"));
                input.set("Data Layout", ir->dl_scalar);
                RCP< Evaluator<panzer::Traits> > e =
                    rcp(new panzer::Constant<EvalT,panzer::Traits>(input));
                evaluators->push_back(e);
            }
            // at BASIS
            for (std::vector<Teuchos::RCP<const panzer::PureBasis> >::const_iterator basis_itr = bases.begin();
                    basis_itr != bases.end(); ++basis_itr) {
                input.set("Name", key);
                input.set("Value", plist.get<double>("Value"));
                Teuchos::RCP<const panzer::BasisIRLayout> basis = basisIRLayout(*basis_itr,*ir);
                input.set("Data Layout", basis->functional);
                RCP< Evaluator<panzer::Traits> > e =
                    rcp(new panzer::Constant<EvalT,panzer::Traits>(input));
                evaluators->push_back(e);
            }
            found = true;
        }

        if (plist.isType<std::string>("Value")) {

            const std::string value = plist.get<std::string>("Value");

            if (key == "Global Statistics") {
                if (typeid(EvalT) == typeid(panzer::Traits::Residual)) {
                    input.set("Comm", user_data.get<Teuchos::RCP<const Teuchos::Comm<int> > >("Comm"));
                    input.set("Names", value);
                    input.set("IR", ir);
                    input.set("Global Data", global_data);
                    RCP< panzer::GlobalStatistics<EvalT,panzer::Traits> > e =
                        rcp(new panzer::GlobalStatistics<EvalT,panzer::Traits>(input));
                    evaluators->push_back(e);

                    // Require certain fields be evaluated
                    fm.template requireField<EvalT>(e->getRequiredFieldTag());
                }
                found = true;
            }
            else if(value=="Field Spy") {
                const std::string & source = plist.get<std::string>("Source Field");

                RCP<panzer::FieldSpy<EvalT,panzer::Traits> > e =
                    rcp(new panzer::FieldSpy<EvalT,panzer::Traits>(source,ir->dl_scalar));
                evaluators->push_back(e);

                fm.template requireField<EvalT>(e->getRequiredFieldTag());

                found = true;
            }
            else if(value=="Field Spy Basis") {
                const std::string & source = plist.get<std::string>("Source Field");

                RCP<panzer::FieldSpy<EvalT,panzer::Traits> > e =
                    rcp(new panzer::FieldSpy<EvalT,panzer::Traits>(source,bases[0]->functional));
                evaluators->push_back(e);

                fm.template requireField<EvalT>(e->getRequiredFieldTag());

                found = true;
            }

        }

        if (key == "Volume Integral") {

            {
                ParameterList input;
                input.set("Name", "Unit Value");
                input.set("Value", 1.0);
                input.set("Data Layout", ir->dl_scalar);
                RCP< Evaluator<panzer::Traits> > e =
                    rcp(new panzer::Constant<EvalT,panzer::Traits>(input));
                evaluators->push_back(e);
            }

            {
                ParameterList input;
                input.set("Integral Name", "Volume_Integral");
                input.set("Integrand Name", "Unit Value");
                input.set("IR", ir);

                RCP< Evaluator<panzer::Traits> > e =
                    rcp(new panzer::Integrator_Scalar<EvalT,panzer::Traits>(input));
                evaluators->push_back(e);
            }

            found = true;
        }

        if (key == "Coordinates") {
            std::string dim_str[3] = {"X","Y","Z"};
            panzer::CellData cell_data(ir->workset_size,ir->topology);
            panzer::PureBasis basis("HGrad",1,cell_data);

            for(int i=0; i<basis.dimension(); i++) {
                ParameterList input;
                input.set("Field Name", "COORD"+dim_str[i]);
                input.set("Data Layout", basis.functional);
                input.set("Dimension", i);

                RCP< Evaluator<panzer::Traits> > e =
                    rcp(new panzer::CoordinatesEvaluator<EvalT,panzer::Traits>(input));
                evaluators->push_back(e);
            }

            found = true;
        }


        if (!found) {
            std::stringstream msg;
            msg << "ClosureModelFactory failed to build evaluator for key \"" << key
                << "\"\nin model \"" << model_id
                << "\".  Please correct the type or add support to the \nfactory." <<std::endl;
            TEUCHOS_TEST_FOR_EXCEPTION(!found, std::logic_error, msg.str());
        }

    }

    return evaluators;
}
Teuchos::RCP< std::vector< Teuchos::RCP<PHX::Evaluator<panzer::Traits> > > > 
user_app::MyModelFactory<EvalT>::
buildClosureModels(const std::string& model_id,
		   const Teuchos::ParameterList& models, 
		   const panzer::FieldLayoutLibrary& fl,
		   const Teuchos::RCP<panzer::IntegrationRule>& ir,
		   const Teuchos::ParameterList& default_params,
		   const Teuchos::ParameterList& user_data,
		   const Teuchos::RCP<panzer::GlobalData>& global_data,
		   PHX::FieldManager<panzer::Traits>& fm) const
{

  using std::string;
  using std::vector;
  using Teuchos::RCP;
  using Teuchos::rcp;
  using Teuchos::ParameterList;
  using PHX::Evaluator;

  RCP< vector< RCP<Evaluator<panzer::Traits> > > > evaluators = 
    rcp(new vector< RCP<Evaluator<panzer::Traits> > > );

  if (!models.isSublist(model_id)) {
    models.print(std::cout);
    std::stringstream msg;
    msg << "Falied to find requested model, \"" << model_id 
	<< "\", for equation set:\n" << std::endl;
    TEUCHOS_TEST_FOR_EXCEPTION(!models.isSublist(model_id), std::logic_error, msg.str());
  }

  std::vector<Teuchos::RCP<const panzer::PureBasis> > bases;
  fl.uniqueBases(bases);

  const ParameterList& my_models = models.sublist(model_id);

  for (ParameterList::ConstIterator model_it = my_models.begin(); 
       model_it != my_models.end(); ++model_it) {
    
    bool found = false;
    
    const std::string key = model_it->first;
    ParameterList input;
    const Teuchos::ParameterEntry& entry = model_it->second;
    const ParameterList& plist = Teuchos::getValue<Teuchos::ParameterList>(entry);

    #ifdef HAVE_STOKHOS
    if (plist.isType<double>("Value") && plist.isType<double>("UQ") 
                           && plist.isParameter("Expansion")
                           && (typeid(EvalT)==typeid(panzer::Traits::SGResidual) || 
                               typeid(EvalT)==typeid(panzer::Traits::SGJacobian)) ) {
      { // at IP
	input.set("Name", key);
	input.set("Value", plist.get<double>("Value"));
	input.set("UQ", plist.get<double>("UQ"));
	input.set("Expansion", plist.get<Teuchos::RCP<Stokhos::OrthogPolyExpansion<int,double> > >("Expansion"));
	input.set("Data Layout", ir->dl_scalar);
	RCP< Evaluator<panzer::Traits> > e = 
	  rcp(new user_app::ConstantModel<EvalT,panzer::Traits>(input));
	evaluators->push_back(e);
      }
      
      for (std::vector<Teuchos::RCP<const panzer::PureBasis> >::const_iterator basis_itr = bases.begin();
	   basis_itr != bases.end(); ++basis_itr) { // at BASIS
	input.set("Name", key);
	input.set("Value", plist.get<double>("Value"));
	input.set("UQ", plist.get<double>("UQ"));
	input.set("Expansion", plist.get<Teuchos::RCP<Stokhos::OrthogPolyExpansion<int,double> > >("Expansion"));
	Teuchos::RCP<const panzer::BasisIRLayout> basis = basisIRLayout(*basis_itr,*ir);
	input.set("Data Layout", basis->functional);
	RCP< Evaluator<panzer::Traits> > e = 
	  rcp(new user_app::ConstantModel<EvalT,panzer::Traits>(input));
	evaluators->push_back(e);
      }
      found = true;
    }
    else 
    #endif
    if (plist.isType<std::string>("Type")) {
      
      if (plist.get<std::string>("Type") == "Parameter") {
	{ // at IP
	  RCP< Evaluator<panzer::Traits> > e = 
	    rcp(new panzer::Parameter<EvalT,panzer::Traits>(key,ir->dl_scalar,plist.get<double>("Value"),*global_data->pl));
	  evaluators->push_back(e);
	}
	
	for (std::vector<Teuchos::RCP<const panzer::PureBasis> >::const_iterator basis_itr = bases.begin();
	   basis_itr != bases.end(); ++basis_itr) { // at BASIS
	  Teuchos::RCP<const panzer::BasisIRLayout> basis = basisIRLayout(*basis_itr,*ir);
	  RCP< Evaluator<panzer::Traits> > e = 
	    rcp(new panzer::Parameter<EvalT,panzer::Traits>(key,basis->functional,plist.get<double>("Value"),*global_data->pl));
	  evaluators->push_back(e);
	}
	
	found = true;
      }
  
    }
    else if (plist.isType<double>("Value")) {
      { // at IP
	input.set("Name", key);
	input.set("Value", plist.get<double>("Value"));
	input.set("Data Layout", ir->dl_scalar);
	RCP< Evaluator<panzer::Traits> > e = 
	  rcp(new user_app::ConstantModel<EvalT,panzer::Traits>(input));
	evaluators->push_back(e);
      }
      // at BASIS
      for (std::vector<Teuchos::RCP<const panzer::PureBasis> >::const_iterator basis_itr = bases.begin();
	   basis_itr != bases.end(); ++basis_itr) {
	input.set("Name", key);
	input.set("Value", plist.get<double>("Value"));
	Teuchos::RCP<const panzer::BasisIRLayout> basis = basisIRLayout(*basis_itr,*ir);
	input.set("Data Layout", basis->functional);
	RCP< Evaluator<panzer::Traits> > e = 
	  rcp(new user_app::ConstantModel<EvalT,panzer::Traits>(input));
	evaluators->push_back(e);
      }
      found = true;
    }

    if (plist.isType<std::string>("Value")) {
    
      const std::string value = plist.get<std::string>("Value");

      if (key == "Global Statistics") {
	if (typeid(EvalT) == typeid(panzer::Traits::Residual)) {
	  input.set("Comm", user_data.get<Teuchos::RCP<const Teuchos::Comm<int> > >("Comm"));
	  input.set("Names", value);
	  input.set("IR", ir);
	  input.set("Global Data", global_data);
	  RCP< panzer::GlobalStatistics<EvalT,panzer::Traits> > e = 
	    rcp(new panzer::GlobalStatistics<EvalT,panzer::Traits>(input));
	  evaluators->push_back(e);
	  
	  // Require certain fields be evaluated
	  fm.template requireField<EvalT>(e->getRequiredFieldTag());
	}
	found = true;
      }

    }

    if (key == "Volume Integral") {

        {
           ParameterList input;
	   input.set("Name", "Unit Value");
	   input.set("Value", 1.0);
	   input.set("Data Layout", ir->dl_scalar);
	   RCP< Evaluator<panzer::Traits> > e = 
   	     rcp(new user_app::ConstantModel<EvalT,panzer::Traits>(input));
   	   evaluators->push_back(e);
        }

        {
           ParameterList input;
	   input.set("Integral Name", "Volume_Integral");
	   input.set("Integrand Name", "Unit Value");
	   input.set("IR", ir);

	   RCP< Evaluator<panzer::Traits> > e = 
   	     rcp(new panzer::Integrator_Scalar<EvalT,panzer::Traits>(input));
   	   evaluators->push_back(e);
        }

	found = true;
    }

    if (key == "Coordinates") {
      std::string dim_str[3] = {"X","Y","Z"};
      panzer::CellData cell_data(ir->workset_size,ir->topology);
      panzer::PureBasis basis("HGrad",1,cell_data);

      for(int i=0;i<basis.dimension();i++) {
        ParameterList input;
        input.set("Field Name", "COORD"+dim_str[i]);
        input.set("Data Layout", basis.functional);
        input.set("Dimension", i);

        RCP< Evaluator<panzer::Traits> > e = 
          rcp(new panzer::CoordinatesEvaluator<EvalT,panzer::Traits>(input));
        evaluators->push_back(e);
      }

      found = true;
    }


    if (!found) {
      std::stringstream msg;
      msg << "ClosureModelFactory failed to build evaluator for key \"" << key 
	  << "\"\nin model \"" << model_id 
	  << "\".  Please correct the type or add support to the \nfactory." <<std::endl;
      TEUCHOS_TEST_FOR_EXCEPTION(!found, std::logic_error, msg.str());
    }

  }

  return evaluators;
}
Teuchos::RCP< std::vector< Teuchos::RCP<PHX::Evaluator<panzer::Traits> > > > 
user_app::MyModelFactory<EvalT>::
buildClosureModels(const std::string& model_id,
		   const Teuchos::ParameterList& models,
		   const panzer::FieldLayoutLibrary& fl,
		   const Teuchos::RCP<panzer::IntegrationRule>& ir, 
		   const Teuchos::ParameterList& default_params,
		   const Teuchos::ParameterList& user_data,
                   const Teuchos::RCP<panzer::GlobalData>& global_data,
		   PHX::FieldManager<panzer::Traits>& fm) const
{

  using std::string;
  using std::vector;
  using Teuchos::RCP;
  using Teuchos::rcp;
  using Teuchos::ParameterList;
  using PHX::Evaluator;

  RCP< vector< RCP<Evaluator<panzer::Traits> > > > evaluators = 
    rcp(new vector< RCP<Evaluator<panzer::Traits> > > );

  if (!models.isSublist(model_id)) {
    std::stringstream msg;
    msg << "Falied to find requested model, \"" << model_id 
	<< "\", for equation set:\n" << std::endl;
    TEUCHOS_TEST_FOR_EXCEPTION(!models.isSublist(model_id), std::logic_error, msg.str());
  }

  std::vector<Teuchos::RCP<const panzer::PureBasis> > bases;
  fl.uniqueBases(bases);

  const ParameterList& my_models = models.sublist(model_id);

  for (ParameterList::ConstIterator model_it = my_models.begin(); 
       model_it != my_models.end(); ++model_it) {
    
    bool found = false;
    
    const std::string key = model_it->first;
    ParameterList input;
    const Teuchos::ParameterEntry& entry = model_it->second;
    const ParameterList& plist = Teuchos::getValue<Teuchos::ParameterList>(entry);
    
    if (plist.isType<double>("Value")) {
      { // at IP
	input.set("Name", key);
	input.set("Value", plist.get<double>("Value"));
	input.set("Data Layout", ir->dl_scalar);
	RCP< Evaluator<panzer::Traits> > e = 
	  rcp(new panzer::Constant<EvalT,panzer::Traits>(input));
	evaluators->push_back(e);
      }
      for (std::vector<Teuchos::RCP<const panzer::PureBasis> >::const_iterator basis_itr = bases.begin();
	   basis_itr != bases.end(); ++basis_itr) { // at BASIS
	input.set("Name", key);
	input.set("Value", plist.get<double>("Value"));
	Teuchos::RCP<const panzer::BasisIRLayout> basis = basisIRLayout(*basis_itr,*ir);
	input.set("Data Layout", basis->functional);
	RCP< Evaluator<panzer::Traits> > e = 
	  rcp(new panzer::Constant<EvalT,panzer::Traits>(input));
	evaluators->push_back(e);
      }
      found = true;
    }

    if (plist.isType<std::string>("Value")) {
    
      const std::string value = plist.get<std::string>("Value");

      if (key == "Global Statistics") {
	if (typeid(EvalT) == typeid(panzer::Traits::Residual)) {
	  input.set("Comm", user_data.get<Teuchos::RCP<const Teuchos::Comm<int> > >("Comm"));
	  input.set("Names", value);
	  input.set("IR", ir);
	  input.set("Global Data", global_data);
	  RCP< panzer::GlobalStatistics<EvalT,panzer::Traits> > e = 
	    rcp(new panzer::GlobalStatistics<EvalT,panzer::Traits>(input));
	  evaluators->push_back(e);
	  
	  // Require certain fields be evaluated
	  fm.template requireField<EvalT>(e->getRequiredFieldTag());
	}
	found = true;
      }



    }

    if (!found) {
      std::stringstream msg;
      msg << "ClosureModelFactory failed to build evaluator for key \"" << key 
	  << "\"\nin model \"" << model_id 
	  << "\".  Please correct the type or add support to the \nfactory." <<std::endl;
      TEUCHOS_TEST_FOR_EXCEPTION(!found, std::logic_error, msg.str());
    }

  }

  return evaluators;
}
Teuchos::RCP< std::vector< Teuchos::RCP<PHX::Evaluator<panzer::Traits> > > > 
Example::ModelFactory<EvalT>::
buildClosureModels(const std::string& model_id,
		   const Teuchos::ParameterList& models, 
		   const panzer::FieldLayoutLibrary& fl,
		   const Teuchos::RCP<panzer::IntegrationRule>& ir,
		   const Teuchos::ParameterList& default_params,
		   const Teuchos::ParameterList& user_data,
		   const Teuchos::RCP<panzer::GlobalData>& global_data,
		   PHX::FieldManager<panzer::Traits>& fm) const
{
  using std::string;
  using std::vector;
  using Teuchos::RCP;
  using Teuchos::rcp;
  using Teuchos::ParameterList;
  using PHX::Evaluator;

  RCP< vector< RCP<Evaluator<panzer::Traits> > > > evaluators = 
    rcp(new vector< RCP<Evaluator<panzer::Traits> > > );

  if (!models.isSublist(model_id)) {
    models.print(std::cout);
    std::stringstream msg;
    msg << "Falied to find requested model, \"" << model_id 
	<< "\", for equation set:\n" << std::endl;
    TEUCHOS_TEST_FOR_EXCEPTION(!models.isSublist(model_id), std::logic_error, msg.str());
  }

  std::vector<Teuchos::RCP<const panzer::PureBasis> > bases;
  fl.uniqueBases(bases);

  const ParameterList& my_models = models.sublist(model_id);

  for (ParameterList::ConstIterator model_it = my_models.begin(); 
       model_it != my_models.end(); ++model_it) {
    
    bool found = false;
    
    const std::string key = model_it->first;
    ParameterList input;
    const Teuchos::ParameterEntry& entry = model_it->second;
    const ParameterList& plist = Teuchos::getValue<Teuchos::ParameterList>(entry);

    if (plist.isType<double>("Value")) {
      { // at IP
	input.set("Name", key);
	input.set("Value", plist.get<double>("Value"));
	input.set("Data Layout", ir->dl_scalar);
	RCP< Evaluator<panzer::Traits> > e = 
	  rcp(new panzer::Constant<EvalT,panzer::Traits>(input));
	evaluators->push_back(e);
      }
      
      for (std::vector<Teuchos::RCP<const panzer::PureBasis> >::const_iterator basis_itr = bases.begin();
	   basis_itr != bases.end(); ++basis_itr) { // at BASIS
	input.set("Name", key);
	input.set("Value", plist.get<double>("Value"));
	Teuchos::RCP<const panzer::BasisIRLayout> basis = basisIRLayout(*basis_itr,*ir);
	input.set("Data Layout", basis->functional);
	RCP< Evaluator<panzer::Traits> > e = 
	  rcp(new panzer::Constant<EvalT,panzer::Traits>(input));
	evaluators->push_back(e);
      }
      found = true;
    }

    if (plist.isType<std::string>("Type")) {
      const std::string type = plist.get<std::string>("Type");
      if (type == "SIMPLE SOURCE") {
	RCP<Evaluator<panzer::Traits> > e = rcp(new Example::SimpleSource<EvalT,panzer::Traits>(key, *ir));
	evaluators->push_back(e);
        found = true;
      } else if (type == "EXACT") {
        RCP<Evaluator<panzer::Traits> > e = rcp(new Example::Solution<EvalT,panzer::Traits>(key, *ir));
        evaluators->push_back(e);
        found = true;
      } else if (type == "EXACT nonlinear Robin") {
        RCP<Evaluator<panzer::Traits> > e = rcp(new Example::Solution<EvalT,panzer::Traits>(key, *ir, false));
        evaluators->push_back(e);
        found = true;
      } else if (type == "ERROR_CALC") {
        {
          std::vector<std::string> values(2);
          values[0] = plist.get<std::string>("Field A");
          values[1] = plist.get<std::string>("Field B");
  
          std::vector<double> scalars(2); 
          scalars[0] = 1.0; 
          scalars[1] = -1.0;
  
          Teuchos::ParameterList p;
          p.set("Sum Name", key + "_DIFF");
          p.set<RCP<std::vector<std::string> > >("Values Names", Teuchos::rcpFromRef(values));
          p.set<RCP<const std::vector<double> > >("Scalars", Teuchos::rcpFromRef(scalars));
          p.set("Data Layout", ir->dl_scalar);
  
          RCP<Evaluator<panzer::Traits> > e = rcp(new panzer::Sum<EvalT,panzer::Traits>(p));
          evaluators->push_back(e);
        }
        {
          std::vector<std::string> values(2);
          values[0] = key + "_DIFF";
          values[1] = key + "_DIFF";
  
          Teuchos::ParameterList p;
          p.set("Product Name",key);
          p.set<RCP<std::vector<std::string> > >("Values Names",Teuchos::rcpFromRef(values));
          p.set("Data Layout",ir->dl_scalar);
  
          RCP<Evaluator<panzer::Traits> > e = rcp(new panzer::Product<EvalT,panzer::Traits>(p));
          evaluators->push_back(e);
        }
        found = true;
      }
    }

    if ( ! found) {
      std::stringstream msg;
      msg << "ClosureModelFactory failed to build evaluator for key \"" << key 
	  << "\"\nin model \"" << model_id 
	  << "\".  Please correct the type or add support to the \nfactory." <<std::endl;
      TEUCHOS_TEST_FOR_EXCEPTION(!found, std::logic_error, msg.str());
    }

  }

  return evaluators;
}