Esempio n. 1
0
void
MooseVariable::reinitAux()
{
  /* FIXME: this method is only for elemental auxiliary variables, so
   * we may want to rename it */
  _dof_map.dof_indices (_elem, _dof_indices, _var_num);
  if (_elem->n_dofs(_sys.number(), _var_num) > 0)
  {
    // FIXME: check if the following is equivalent with '_nodal_dof_index = _dof_indices[0];'?
    _nodal_dof_index = _elem->dof_number(_sys.number(), _var_num, 0);

    _nodal_u.resize(_dof_indices.size());
    const NumericVector<Real> & current_solution = *_sys.currentSolution();
    for (unsigned int i=0; i<_dof_indices.size(); i++)
      _nodal_u[i] = current_solution(_dof_indices[i]);

    _is_defined = true;
  }
  else
    _is_defined = false;
}
Esempio n. 2
0
void
MooseVariable::reinitAuxNeighbor()
{
  if (_neighbor)
  {
    _dof_map.dof_indices (_neighbor, _dof_indices_neighbor, _var_num);
    if (_neighbor->n_dofs(_sys.number(), _var_num) > 0)
    {
      _nodal_dof_index_neighbor = _neighbor->dof_number(_sys.number(), _var_num, 0);

      _nodal_u_neighbor.resize(_dof_indices_neighbor.size());
      const NumericVector<Real> & current_solution = *_sys.currentSolution();
      for (unsigned int i=0; i<_dof_indices_neighbor.size(); i++)
        _nodal_u_neighbor[i] = current_solution(_dof_indices_neighbor[i]);

      _is_defined_neighbor = true;
    }
    else
      _is_defined_neighbor = false;
  }
  else
    _is_defined_neighbor = false;
}
void Ants::begin(int *s, int *r) {
	int distance_max = INT_MIN;
	for (int i = 1; i < I->getM(); i++) {
		if (I->getK(0, i) > distance_max) {
			distance_max = I->getK(0, i);
		}
	}
	/* Initialization of the pheromone matrix. */
	/* Computation of the visibility matrix. */
	for (int i = 0; i < n; i++) {
		for (int j = i; j < n; j++) {
			if (i == j) {
				pheromone_green[i][j] = 0;
				pheromone_red[i][j] = 0;
				visibility_green[i][j] = 0;
				visibility_red[i][j] = 0;
			} else {
				pheromone_green[i][j] = initial_pheromone_value;
				pheromone_red[i][j] = initial_pheromone_value;

				double visibility;
				// |di - dj|
				visibility = abs(I->getJob(i).getD() - I->getJob(j).getD());
				if (visibility == 0)
					visibility = 1;
				// (1/|di-dj|)^psi
				visibility = pow(1 / visibility, psi);
				visibility_green[i][j] = visibility;
				// delta_ij
				visibility = I->getK(I->getJob(i).getK(), I->getJob(j).getK());
				if (visibility == 0)
					visibility = 1;
				// (1/delta_ij)^omega
				visibility = pow(1 / visibility, omega);
				// (1/delta_ij)^omega * sqrt(delta_0i * delta_0j)/delta_max
				if (distance_max != 0)
					visibility = visibility
							* (sqrt(
									I->getK(0, I->getJob(i).getK())
											* I->getK(0, I->getJob(j).getK()))
									/ distance_max);
				// [(1/delta_ij)^omega * sqrt(delta_0i * delta_0j)/delta_max]^chi
				visibility = pow(visibility, chi);
				// (1/|di-dj|)^psi * [(1/delta_ij)^omega * sqrt(delta_0i * delta_0j)/delta_max]^chi
				visibility_green[i][j] *= visibility;

				if (visibility_green[i][j] == 0)
					visibility_red[i][j] = 1;
				else
					visibility_red[i][j] = 1 - visibility_green[i][j];
			}
		}
	}
	for (int i = 0; i < n; i++) {
		for (int j = i + 1; j < n; j++) {
			pheromone_green[j][i] = pheromone_green[i][j];
			pheromone_red[j][i] = pheromone_red[i][j];
			visibility_green[j][i] = visibility_green[i][j];
			visibility_red[j][i] = visibility_red[i][j];
		}
	}

	srand(time(NULL));
	// tabu[0] == True: job 0 is tabu, should not be considered.
	bool tabu[n];
	int start;
	int end;
	char color;
	int edge_start[n - 1];
	int edge_end[n - 1];
	char edge_color[n - 1];
	int edge_best_ant_start[n - 1];
	int edge_best_ant_end[n - 1];
	char edge_best_ant_color[n - 1];
	double sum_green;
	double sum_red;
	double p_green[n];
	double p_red[n];
	double max;
	int max_i;
	char max_c;
	int *s_found;
	int *r_found;
	Solution current_solution(I);
	Solution best_ant(I);
	Solution best(I);
	Heuristics heuristics;
	Job jobs_jonhson[n];
	int bestT = INT_MAX;
	double deltaT = initial_pheromone_value;
	// We set the pointers of the differents solutions we will store
	s_found = current_solution.getS();
	r_found = current_solution.getR();
	for (int i = 0; i < iteration_number; i++) {
		for (int m = 0; m < ant_number; m++) {
			/* Construct solution */
			// Init tabu list at false
			for (int j = 0; j < n; j++) {
				tabu[j] = false;
			}
			// We choose a random job as start point.
			start = rand() % n;
			// The start job is tabu
			tabu[start] = true;
			// We construct a Hamiltonian path within the graph.
			for (int e = 0; e < n - 1; e++) {
				sum_green = sum_red = 0;
				// We get the proba to do classic P or roulette P
				// We do classic P
				if ((double) rand() / RAND_MAX > diversification_probability) {
					// We get the sum of (pheromone_startj)^alpha * (visibility_startj)^beta where j not in tabu.
					// For both green and red
					for (int j = 0; j < n; j++) {
						if (!tabu[j]) {
							sum_green += pow(pheromone_green[start][j], alpha)
									* pow(visibility_green[start][j], beta);
							sum_red += pow(pheromone_red[start][j], alpha)
									* pow(visibility_red[start][j], beta);
						}
					}
					// We compute the probability for each edge.
					for (int j = 0; j < n; j++) {
						if (!tabu[j]) {
							p_green[j] = pow(pheromone_green[start][j], alpha)
									* pow(visibility_green[start][j], beta)
									/ sum_green;
							p_red[j] = pow(pheromone_red[start][j], alpha)
									* pow(visibility_red[start][j], beta)
									/ sum_red;
						} else
							p_green[j] = p_red[j] = 0;
					}
					max = INT_MIN;
					// We search for the highest probability.
					for (int j = 0; j < n; j++) {
						if (p_green[j] > max && !tabu[j]) {
							max = p_green[j];
							max_i = j;
							max_c = 'g';
						}
						if (p_red[j] > max && !tabu[j]) {
							max = p_red[j];
							max_i = j;
							max_c = 'r';
						}
					}
					// Our edge is chosen
					end = max_i;
					color = max_c;
				}
				// We do roulette P
				else {
					int j = 0;
					double cumul = 0;
					// We get the first non-tabu node.
					while (tabu[j] && j < n) {
						j++;
						p_green[j] = p_red[j] = 0;
					}
					// And give its p the initial pheromone value.
					p_green[j] = pheromone_green[start][j];
					cumul = p_red[j] = p_green[j] + pheromone_red[start][j];
					int last_j = j;
					// We compute the cumul of pheromone value
					for (j = j + 1; j < n; j++) {
						if (!tabu[j]) {
							p_green[j] = p_red[last_j]
									+ pheromone_green[start][j];
							cumul = p_red[j] = p_green[j]
									+ pheromone_red[start][j];
							last_j = j;
						} else
							p_green[j] = p_red[j] = 0;
					}
					// We pull a random number between 0 and the cumul of pheromone.
					max = (double) rand() / RAND_MAX * cumul;
					j = -1;
					do {
						j++;
						if (!tabu[j]) {
							if (p_green[j] >= max) {
								end = j;
								color = 'g';
							} else if (p_red[j] >= max) {
								end = j;
								color = 'r';
							}
						}
					} while (tabu[j] || (p_green[j] < max && p_red[j] < max));
				}
				edge_start[e] = start;
				edge_end[e] = end;
				edge_color[e] = color;
				start = end;
				tabu[start] = true;
			}

			// Init r_found with 0.
			for (int j = 0; j < n * 2; j++) {
				r_found[j] = 0;
			}
			int r_i;
			int batch_size_i = 0;
			r_found[0] = 1;
			r_found[1] = edge_start[0];
			r_i = 2;
			// We form the array r from the edges found by the ant.
			// Also we do the local pheromone update.
			for (int e = 0; e < n - 1; e++) {
				// Add to existing batch.
				if (edge_color[e] == 'g') {
					r_found[batch_size_i]++;
				}
				// Make a new batch.
				else {
					r_found[r_i] = 1;
					batch_size_i = r_i;
					r_i++;
				}
				r_found[r_i] = edge_end[e];
				r_i++;

				// Local pheromone update
				if (edge_color[e] == 'g') {
					pheromone_green[edge_start[e]][edge_end[e]] = (1 - rho)
							* pheromone_green[edge_start[e]][edge_end[e]]
							+ rho * initial_pheromone_value;
					pheromone_green[edge_end[e]][edge_start[e]] =
							pheromone_green[edge_start[e]][edge_end[e]];
				} else {
					pheromone_red[edge_start[e]][edge_end[e]] = (1 - rho)
							* pheromone_red[edge_start[e]][edge_end[e]]
							+ rho * initial_pheromone_value;
					pheromone_red[edge_end[e]][edge_start[e]] =
							pheromone_red[edge_start[e]][edge_end[e]];
				}
			}
			/* Use of heuristics to form the rest of the solution */
			// Order the batches by increasing order of minimum due date.
			heuristics.MinimumDueDateBatch(r_found, I->getJobs(), n * 2);
			// For each batch we apply Jonhson.
			int k;
			int nb_done = 0;
			int j = 0;
			while (j < n * 2) {
				k = r_found[j];
				if (k == 0) {
					j = n * 2;
				} else {
					// We make a new list of jobs in order of array r_found.
					for (int l = 0; l < k; l++) {
						jobs_jonhson[nb_done + l] = I->getJob(
								r_found[j + 1 + l]);
					}
					heuristics.Jonhson(jobs_jonhson + nb_done, k,
							s_found + nb_done);
					nb_done += k;
					j += k + 1;
				}
			}
			// We apply the nearest neighbor for the jobs of the batches.
			heuristics.NearestNeighbor(I, r_found);

			// We keep the best ant.
			current_solution.refresh(true);
			if (current_solution.getT() < best_ant.getT()) {
				best_ant = current_solution;
				for (int j = 0; j < n - 1; j++) {
					edge_best_ant_start[j] = edge_start[j];
					edge_best_ant_end[j] = edge_end[j];
					edge_best_ant_color[j] = edge_color[j];
				}
			}
		} // end for ants

		/* Global pheromone update. */
		// We update the pheromone matrix with the % of amelioration of the solution on the edges, the ant visited.
		// We keep the best from the best ants.
		if (best_ant.getT() < best.getT()) {
			if (bestT != INT_MAX) {
				deltaT = bestT - best_ant.getT() / bestT;
			}
			for (int e = 0; e < n - 1; e++) {
				if (edge_best_ant_color[e] == 'g') {
					pheromone_green[edge_best_ant_start[e]][edge_best_ant_end[e]] +=
							deltaT;
					pheromone_green[edge_best_ant_end[e]][edge_best_ant_start[e]] +=
							deltaT;
				} else {
					pheromone_red[edge_best_ant_start[e]][edge_best_ant_end[e]] +=
							deltaT;
					pheromone_red[edge_best_ant_end[e]][edge_best_ant_start[e]] +=
												deltaT;
				}
			}
			best = best_ant;
		}

	} // end for interations
	// We copy the best found solution into the return arrays.
	for (int j = 0; j < n * 2; j++) {
		if (j < n)
			s[j] = best.getS()[j];
		r[j] = best.getR()[j];
	}
}
Esempio n. 4
0
void
MooseVariable::computeNeighborValuesFace()
{
  bool is_transient = _subproblem.isTransient();
  unsigned int nqp = _qrule_neighbor->n_points();

  _u_neighbor.resize(nqp);
  _grad_u_neighbor.resize(nqp);

  if (_need_second_neighbor)
    _second_u_neighbor.resize(nqp);

  if (is_transient)
  {
    if (_need_u_old_neighbor)
      _u_old_neighbor.resize(nqp);

    if (_need_u_older_neighbor)
      _u_older_neighbor.resize(nqp);

    if (_need_grad_old_neighbor)
      _grad_u_old_neighbor.resize(nqp);

    if (_need_grad_older_neighbor)
      _grad_u_older_neighbor.resize(nqp);

    if (_need_second_old_neighbor)
      _second_u_old_neighbor.resize(nqp);

    if (_need_second_older_neighbor)
      _second_u_older_neighbor.resize(nqp);
  }

  for (unsigned int i = 0; i < nqp; ++i)
  {
    _u_neighbor[i] = 0;
    _grad_u_neighbor[i] = 0;

    if (_need_second_neighbor)
      _second_u_neighbor[i] = 0;

    if (_subproblem.isTransient())
    {
      if (_need_u_old_neighbor)
        _u_old_neighbor[i] = 0;

      if (_need_u_older_neighbor)
        _u_older_neighbor[i] = 0;

      if (_need_grad_old_neighbor)
        _grad_u_old_neighbor[i] = 0;

      if (_need_grad_older_neighbor)
        _grad_u_older_neighbor[i] = 0;

      if (_need_second_old_neighbor)
        _second_u_old_neighbor[i] = 0;

      if (_need_second_older_neighbor)
        _second_u_older_neighbor[i] = 0;
    }
  }

  unsigned int num_dofs = _dof_indices_neighbor.size();

  const NumericVector<Real> & current_solution = *_sys.currentSolution();
  const NumericVector<Real> & solution_old     = _sys.solutionOld();
  const NumericVector<Real> & solution_older   = _sys.solutionOlder();

  dof_id_type idx;
  Real soln_local;
  Real soln_old_local=0;
  Real soln_older_local=0;

  Real phi_local;
  RealGradient dphi_local;
  RealTensor d2phi_local;

  for (unsigned int i=0; i < num_dofs; ++i)
  {
    idx = _dof_indices_neighbor[i];
    soln_local = current_solution(idx);

    if (is_transient)
    {
      if (_need_u_old_neighbor || _need_grad_old_neighbor || _need_second_old_neighbor)
        soln_old_local = solution_old(idx);

      if (_need_u_older_neighbor || _need_grad_older_neighbor || _need_second_older_neighbor)
        soln_older_local = solution_older(idx);
    }

    for (unsigned int qp=0; qp < nqp; ++qp)
    {
      phi_local = _phi_face_neighbor[i][qp];
      dphi_local = _grad_phi_face_neighbor[i][qp];

      if (_need_second_neighbor || _need_second_old_neighbor || _need_second_older_neighbor)
        d2phi_local = (*_second_phi_face_neighbor)[i][qp];

      _u_neighbor[qp]      += phi_local * soln_local;
      _grad_u_neighbor[qp] += dphi_local * soln_local;

      if (_need_second_neighbor)
        _second_u_neighbor[qp] += d2phi_local * soln_local;

      if (is_transient)
      {
        if (_need_u_old_neighbor)
          _u_old_neighbor[qp]        += phi_local * soln_old_local;

        if (_need_u_older_neighbor)
          _u_older_neighbor[qp]      += phi_local * soln_older_local;

        if (_need_grad_old_neighbor)
          _grad_u_old_neighbor[qp]   += dphi_local * soln_old_local;

        if (_need_grad_older_neighbor)
          _grad_u_older_neighbor[qp]   += dphi_local * soln_older_local;

        if (_need_second_old_neighbor)
          _second_u_old_neighbor[qp] += d2phi_local * soln_old_local;

        if (_need_second_older_neighbor)
          _second_u_older_neighbor[qp] += d2phi_local * soln_older_local;
      }
    }
  }
}
Esempio n. 5
0
void
MooseVariable::computeElemValuesFace()
{
  bool is_transient = _subproblem.isTransient();
  unsigned int nqp = _qrule_face->n_points();
  _u.resize(nqp);
  _grad_u.resize(nqp);

  if (_need_second)
    _second_u.resize(nqp);

  if (is_transient)
  {
    _u_dot.resize(nqp);
    _du_dot_du.resize(nqp);

    if (_need_u_old)
      _u_old.resize(nqp);

    if (_need_u_older)
      _u_older.resize(nqp);

    if (_need_grad_old)
      _grad_u_old.resize(nqp);

    if (_need_grad_older)
      _grad_u_older.resize(nqp);

    if (_need_second_old)
      _second_u_old.resize(nqp);

    if (_need_second_older)
      _second_u_older.resize(nqp);
  }

  for (unsigned int i = 0; i < nqp; ++i)
  {
    _u[i] = 0;
    _grad_u[i] = 0;

    if (_subproblem.isTransient())
    {
      _u_dot[i] = 0;
      _du_dot_du[i] = 0;

      if (_need_u_old)
        _u_old[i] = 0;

      if (_need_u_older)
        _u_older[i] = 0;

      if (_need_grad_old)
        _grad_u_old[i] = 0;

      if (_need_grad_older)
        _grad_u_older[i] = 0;

      if (_need_second)
        _second_u[i] = 0;

      if (_need_second_old)
        _second_u_old[i] = 0;

      if (_need_second_older)
        _second_u_older[i] = 0;
    }
  }

  unsigned int num_dofs = _dof_indices.size();

  const NumericVector<Real> & current_solution = *_sys.currentSolution();
  const NumericVector<Real> & solution_old     = _sys.solutionOld();
  const NumericVector<Real> & solution_older   = _sys.solutionOlder();
  const NumericVector<Real> & u_dot            = _sys.solutionUDot();
  const Real & du_dot_du                       = _sys.duDotDu();

  dof_id_type idx;
  Real soln_local;
  Real soln_old_local = 0;
  Real soln_older_local = 0;
  Real u_dot_local = 0;

  Real phi_local;
  RealGradient dphi_local;
  RealTensor d2phi_local;

  for (unsigned int i=0; i < num_dofs; ++i)
  {
    idx = _dof_indices[i];
    soln_local = current_solution(idx);

    if (is_transient)
    {
      if (_need_u_old || _need_grad_old || _need_second_old)
        soln_old_local = solution_old(idx);

      if (_need_u_older || _need_grad_older || _need_second_older)
        soln_older_local = solution_older(idx);

      u_dot_local = u_dot(idx);
    }

    for (unsigned int qp=0; qp < nqp; ++qp)
    {
      phi_local = _phi_face[i][qp];
      dphi_local = _grad_phi_face[i][qp];

      if (_need_second || _need_second_old || _need_second_older)
        d2phi_local = (*_second_phi_face)[i][qp];

      _u[qp]      += phi_local * soln_local;
      _grad_u[qp] += dphi_local * soln_local;

      if (_need_second)
        _second_u[qp] += d2phi_local * soln_local;

      if (is_transient)
      {
        _u_dot[qp]        += phi_local * u_dot_local;
        _du_dot_du[qp]    = du_dot_du;

        if (_need_u_old)
          _u_old[qp]        += phi_local * soln_old_local;

        if (_need_u_older)
          _u_older[qp]      += phi_local * soln_older_local;

        if (_need_grad_old)
          _grad_u_old[qp]   += dphi_local * soln_old_local;

        if (_need_grad_older)
          _grad_u_older[qp] += dphi_local * soln_older_local;

        if (_need_second_old)
          _second_u_old[qp] += d2phi_local * soln_old_local;

        if (_need_second_older)
          _second_u_older[qp] += d2phi_local * soln_older_local;
      }
    }
  }
}
Esempio n. 6
0
void
MooseVariable::computeElemValues()
{

  bool is_transient = _subproblem.isTransient();
  unsigned int nqp = _qrule->n_points();

  _u.resize(nqp);
  _grad_u.resize(nqp);

  if (_need_second)
    _second_u.resize(nqp);

  if (is_transient)
  {
    _u_dot.resize(nqp);
    _du_dot_du.resize(nqp);

    if (_need_u_old)
      _u_old.resize(nqp);

    if (_need_u_older)
      _u_older.resize(nqp);

    if (_need_grad_old)
      _grad_u_old.resize(nqp);

    if (_need_grad_older)
      _grad_u_older.resize(nqp);

    if (_need_second_old)
      _second_u_old.resize(nqp);

    if (_need_second_older)
      _second_u_older.resize(nqp);
  }

  for (unsigned int i = 0; i < nqp; ++i)
  {
    _u[i] = 0;
    _grad_u[i] = 0;

    if (_need_second)
      _second_u[i] = 0;

    if (is_transient)
    {
      _u_dot[i] = 0;
      _du_dot_du[i] = 0;

      if (_need_u_old)
        _u_old[i] = 0;

      if (_need_u_older)
        _u_older[i] = 0;

      if (_need_grad_old)
        _grad_u_old[i] = 0;

      if (_need_grad_older)
        _grad_u_older[i] = 0;

      if (_need_second_old)
        _second_u_old[i] = 0;

      if (_need_second_older)
        _second_u_older[i] = 0;
    }
  }

  unsigned int num_dofs = _dof_indices.size();

  const NumericVector<Real> & current_solution = *_sys.currentSolution();
  const NumericVector<Real> & solution_old     = _sys.solutionOld();
  const NumericVector<Real> & solution_older   = _sys.solutionOlder();
  const NumericVector<Real> & u_dot            = _sys.solutionUDot();
  const Real & du_dot_du                       = _sys.duDotDu();

  dof_id_type idx = 0;
  Real soln_local = 0;
  Real soln_old_local = 0;
  Real soln_older_local = 0;
  Real u_dot_local = 0;

  Real phi_local = 0;
  const RealGradient * dphi_qp = NULL;
  const RealTensor * d2phi_local = NULL;

  RealGradient * grad_u_qp = NULL;

  RealGradient * grad_u_old_qp = NULL;
  RealGradient * grad_u_older_qp = NULL;

  RealTensor * second_u_qp = NULL;

  RealTensor * second_u_old_qp = NULL;
  RealTensor * second_u_older_qp = NULL;

  for (unsigned int i=0; i < num_dofs; i++)
  {
    idx = _dof_indices[i];
    soln_local = current_solution(idx);

    if (is_transient)
    {
      if (_need_u_old || _need_grad_old || _need_second_old)
        soln_old_local = solution_old(idx);

      if (_need_u_older || _need_grad_older || _need_second_older)
        soln_older_local = solution_older(idx);

      u_dot_local        = u_dot(idx);
    }

    for (unsigned int qp=0; qp < nqp; qp++)
    {
      phi_local = _phi[i][qp];
      dphi_qp = &_grad_phi[i][qp];

      grad_u_qp = &_grad_u[qp];

      if (is_transient)
      {
        if (_need_grad_old)
          grad_u_old_qp = &_grad_u_old[qp];

        if (_need_grad_older)
          grad_u_older_qp = &_grad_u_older[qp];
      }

      if (_need_second || _need_second_old || _need_second_older)
      {
        d2phi_local = &(*_second_phi)[i][qp];

        if (_need_second)
          second_u_qp = &_second_u[qp];

        if (is_transient)
        {
          if (_need_second_old)
            second_u_old_qp = &_second_u_old[qp];

          if (_need_second_older)
            second_u_older_qp = &_second_u_older[qp];
        }
      }

      _u[qp] += phi_local * soln_local;

      grad_u_qp->add_scaled(*dphi_qp, soln_local);

      if (_need_second)
        second_u_qp->add_scaled(*d2phi_local, soln_local);

      if (is_transient)
      {
        _u_dot[qp]        += phi_local * u_dot_local;
        _du_dot_du[qp]    = du_dot_du;

        if (_need_u_old)
          _u_old[qp]        += phi_local * soln_old_local;

        if (_need_u_older)
          _u_older[qp]      += phi_local * soln_older_local;

        if (_need_grad_old)
          grad_u_old_qp->add_scaled(*dphi_qp, soln_old_local);

        if (_need_grad_older)
          grad_u_older_qp->add_scaled(*dphi_qp, soln_older_local);

        if (_need_second_old)
          second_u_old_qp->add_scaled(*d2phi_local, soln_old_local);

        if (_need_second_older)
          second_u_older_qp->add_scaled(*d2phi_local, soln_older_local);
      }
    }
  }
}
Esempio n. 7
0
// FIXME: this and computeElemeValues() could be refactored to reuse most of
//        the common code, instead of duplicating it.
void
MooseVariable::computePerturbedElemValues(unsigned int perturbation_idx, Real perturbation_scale, Real& perturbation)
{

  bool is_transient = _subproblem.isTransient();
  unsigned int nqp = _qrule->n_points();

  _u_bak = _u;
  _grad_u_bak = _grad_u;
  _u.resize(nqp);
  _grad_u.resize(nqp);

  if (_need_second)
    _second_u_bak = _second_u;
    _second_u.resize(nqp);

  if (is_transient)
  {
    _u_dot_bak = _u_dot;
    _u_dot.resize(nqp);
    _du_dot_du_bak = _du_dot_du;
    _du_dot_du.resize(nqp);

    if (_need_u_old)
      _u_old_bak = _u_old;
      _u_old.resize(nqp);

    if (_need_u_older)
      _u_older_bak = _u_older;
      _u_older.resize(nqp);

    if (_need_grad_old)
      _grad_u_old_bak = _grad_u_old;
      _grad_u_old.resize(nqp);

    if (_need_grad_older)
      _grad_u_older_bak = _grad_u_older;
      _grad_u_older.resize(nqp);

    if (_need_second_old)
      _second_u_old_bak = _second_u_old;
      _second_u_old.resize(nqp);

    if (_need_second_older)
      _second_u_older_bak = _second_u_older;
      _second_u_older.resize(nqp);
  }

  for (unsigned int i = 0; i < nqp; ++i)
  {
    _u[i] = 0;
    _grad_u[i] = 0;

    if (_need_second)
      _second_u[i] = 0;

    if (is_transient)
    {
      _u_dot[i] = 0;
      _du_dot_du[i] = 0;

      if (_need_u_old)
        _u_old[i] = 0;

      if (_need_u_older)
        _u_older[i] = 0;

      if (_need_grad_old)
        _grad_u_old[i] = 0;

      if (_need_grad_older)
        _grad_u_older[i] = 0;

      if (_need_second_old)
        _second_u_old[i] = 0;

      if (_need_second_older)
        _second_u_older[i] = 0;
    }
  }

  unsigned int num_dofs = _dof_indices.size();

  const NumericVector<Real> & current_solution = *_sys.currentSolution();
  const NumericVector<Real> & solution_old     = _sys.solutionOld();
  const NumericVector<Real> & solution_older   = _sys.solutionOlder();
  const NumericVector<Real> & u_dot            = _sys.solutionUDot();
  const Real & du_dot_du                       = _sys.duDotDu();

  dof_id_type idx = 0;
  Real soln_local = 0;
  Real soln_old_local = 0;
  Real soln_older_local = 0;
  Real u_dot_local = 0;

  Real phi_local = 0;
  const RealGradient * dphi_qp = NULL;
  const RealTensor * d2phi_local = NULL;

  RealGradient * grad_u_qp = NULL;

  RealGradient * grad_u_old_qp = NULL;
  RealGradient * grad_u_older_qp = NULL;

  RealTensor * second_u_qp = NULL;

  RealTensor * second_u_old_qp = NULL;
  RealTensor * second_u_older_qp = NULL;

  for (unsigned int i=0; i < num_dofs; i++)
  {
    idx = _dof_indices[i];
    soln_local = current_solution(idx);
    if (i == perturbation_idx) {
      // Compute the size of the perturbation.
      // For the PETSc DS differencing method we use the magnitude of the variable at the "node"
      // to determine the differencing parameters.  The WP method could use the element L2 norm of
      // the variable  instead.
      perturbation = soln_local;
      // HACK: the use of fabs() and < assume Real is double or similar. Otherwise need to use PetscAbsScalar, PetscRealPart, etc.
      if (fabs(perturbation) < 1.0e-16) perturbation = (perturbation < 0. ? -1.0: 1.0)*0.1;
      perturbation *= perturbation_scale;
      soln_local += perturbation;
    }
    if (is_transient)
    {
      if (_need_u_old || _need_grad_old || _need_second_old)
        soln_old_local = solution_old(idx);

      if (_need_u_older || _need_grad_older || _need_second_older)
        soln_older_local = solution_older(idx);

      u_dot_local        = u_dot(idx);
    }

    for (unsigned int qp=0; qp < nqp; qp++)
    {
      phi_local = _phi[i][qp];
      dphi_qp = &_grad_phi[i][qp];

      grad_u_qp = &_grad_u[qp];

      if (is_transient)
      {
        if (_need_grad_old)
          grad_u_old_qp = &_grad_u_old[qp];

        if (_need_grad_older)
          grad_u_older_qp = &_grad_u_older[qp];
      }

      if (_need_second || _need_second_old || _need_second_older)
      {
        d2phi_local = &(*_second_phi)[i][qp];

        if (_need_second)
          second_u_qp = &_second_u[qp];

        if (is_transient)
        {
          if (_need_second_old)
            second_u_old_qp = &_second_u_old[qp];

          if (_need_second_older)
            second_u_older_qp = &_second_u_older[qp];
        }
      }

      _u[qp]     += phi_local * soln_local;

      grad_u_qp->add_scaled(*dphi_qp, soln_local);

      if (_need_second)
        second_u_qp->add_scaled(*d2phi_local, soln_local);

      if (is_transient)
      {
        _u_dot[qp]        += phi_local * u_dot_local;
        _du_dot_du[qp]    = du_dot_du;

        if (_need_u_old)
          _u_old[qp]        += phi_local * soln_old_local;

        if (_need_u_older)
          _u_older[qp]      += phi_local * soln_older_local;

        if (_need_grad_old)
          grad_u_old_qp->add_scaled(*dphi_qp, soln_old_local);

        if (_need_grad_older)
          grad_u_older_qp->add_scaled(*dphi_qp, soln_older_local);

        if (_need_second_old)
          second_u_old_qp->add_scaled(*d2phi_local, soln_old_local);

        if (_need_second_older)
          second_u_older_qp->add_scaled(*d2phi_local, soln_older_local);
      }
    }
  }
}