void ATO::ModalObjective<PHAL::AlbanyTraits::Residual, Traits>::
evaluateFields(typename Traits::EvalData workset)
{

  Albany::MDArray F    = (*workset.stateArrayPtr)[FName];
  Albany::MDArray dEdp = (*workset.stateArrayPtr)[dFdpName];
  Albany::MDArray topo = (*workset.stateArrayPtr)[topology->getName()];
  std::vector<int> dims;
  gradX.dimensions(dims);
  int size = dims.size();

  int numCells = dims[0];
  int numQPs = dims[1];
  int numDims = dims[2];
  int numNodes = topo.dimension(1);

  if( size == 4 ){
    for(int cell=0; cell<numCells; cell++){
      double dE = 0.0;
      double dmass_term = 0.;
      double dstiffness_term = 0.;
      for(int qp=0; qp<numQPs; qp++){
        double topoVal = 0.0;
        for(int node=0; node<numNodes; node++)
          topoVal += topo(cell,node)*BF(cell,node,qp);
        double P = topology->Penalize(functionIndex,topoVal);
        double dP = topology->dPenalize(functionIndex,topoVal);
        double dE = 0.0;
        double dmass_term = 0.;
        double dstiffness_term = 0.;
        for(int i=0; i<numDims; i++) {
          dmass_term += val_qp(cell,qp,i)*val_qp(cell,qp,i) * qp_weights(cell,qp);
          for(int j=0; j<numDims; j++)
            dstiffness_term += dP*gradX(cell,qp,i,j)*workConj(cell,qp,i,j)*qp_weights(cell,qp);
        }
        for(int node=0; node<numNodes; node++)
        dEdp(cell,node) = -(dstiffness_term - dmass_term*eigval(0))*BF(cell,node,qp);
      }
//tevhack        std::cout << "dEdp(" << cell << ") = " << dEdp(cell) << std::endl;
    }
  } else {
    TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameter,
      "Unexpected array dimensions in StiffnessObjective:" << size << std::endl);
  }

/*
  if( size == 3 ){
    for(int cell=0; cell<numCells; cell++){
      double dE = 0.0;
      double P = topology->Penalize(topo(cell));
      for(int qp=0; qp<numQPs; qp++) {
        for(int i=0; i<numDims; i++) {
          dE += val_qp(cell,qp,i) * val_qp(cell,qp,i);
        }
        for(int node=0; node<numNodes; node++)
          dEdp(cell,node) = dE/P*BF(cell,node,qp);
      }
      std::cout << "dEdp(" << cell << ") = " << dEdp(cell) << std::endl;
    }
  } else {
    TEUCHOS_TEST_FOR_EXCEPTION(
      true, 
      Teuchos::Exceptions::InvalidParameter,
      "Unexpected array dimensions in ModalObjective:" << size << std::endl
    );
  }
*/

  F(0) = -eigval(0);

}
void ATO::StiffnessObjective<PHAL::AlbanyTraits::Residual, Traits>::
evaluateFields(typename Traits::EvalData workset)
{

  if(m_excludeBlock) return;

  if( elementBlockName != workset.EBName ) return;

  int nTopos = topologies->size();

  Teuchos::Array<double> topoVals(nTopos);
  Albany::MDArray F = (*workset.stateArrayPtr)[FName];
  Teuchos::Array<Albany::MDArray> dEdp(nTopos), topo(nTopos);
  for(int itopo=0; itopo<nTopos; itopo++){
    dEdp[itopo] = (*workset.stateArrayPtr)[dFdpNames[itopo]];
    topo[itopo] = (*workset.stateArrayPtr)[(*topologies)[itopo]->getName()];
  }

 
  std::vector<int> dims;
  penaltyModel->getFieldDimensions(dims);
  int size = dims.size();

  double internalEnergy=0.0;

  int numCells = dims[0];
  int numQPs   = dims[1];
  int numDims  = dims[2];
  int numNodes = topo[0].dimension(1);

  double response;
  Teuchos::Array<double> dResponse(nTopos);
  
  for(int cell=0; cell<numCells; cell++){

    for(int itopo=0; itopo<nTopos; itopo++)
      for(int node=0; node<numNodes; node++) 
        dEdp[itopo](cell,node) = 0.0;

    for(int qp=0; qp<numQPs; qp++){

      // compute topology values at this qp
      for(int itopo=0; itopo<nTopos; itopo++){
        topoVals[itopo] = 0.0;
        for(int node=0; node<numNodes; node++)
          topoVals[itopo] += topo[itopo](cell,node)*BF(cell,node,qp);
      }

      penaltyModel->Evaluate(topoVals, topologies, cell, qp, response, dResponse);

      internalEnergy += response*qp_weights(cell,qp);

      // assemble
      for(int itopo=0; itopo<nTopos; itopo++)
        for(int node=0; node<numNodes; node++)
//          dEdp[itopo](cell,node) += dResponse[itopo]*BF(cell,node,qp)*qp_weights(cell,qp);
//        JR:  The negative sign is to make this a total derivative 
          dEdp[itopo](cell,node) -= dResponse[itopo]*BF(cell,node,qp)*qp_weights(cell,qp);
    }
  }
  F(0) += internalEnergy;
}