Hey 

I added some lines of code to the "do_integrate_difference"
function (from include/numerics/vectors.templates.h) to have 
TrilinosWrappers::MPI::Vector (input vector uh) ->
TrilinosWrappers::MPI::Vector (output difference vector)
support.

See attachment.

The changes in the code are slight but not trivial, 
so I'm not sure what is the best way to merge it with the current
version (explicit template instance/preprocessing statements/
or do it in another way).
If someone has an efficient idea please reply.

Best
UK

-- 
Dipl.-Ing. Uwe Köcher

Hamburg, Helmut Schmidt University
University of the German Federal Armed Forces

Email: [email protected]
Web:   http://www.hsu-hh.de/mb-mathe

/**
 * @file Integrate_Difference.tpl.cc
 * @author Uwe Koecher
 * @author deal.II authors
 * @date 2012-03-01
 *
 * @brief Re-Implementation of do_integrate_difference.
 */

/*    Copyright (C) 2007-2012 by the deal.II authors              */
/*                                                                */
/*    This file is subject to QPL and may not be  distributed     */
/*    without copyright and license information. Please refer     */
/*    to the file deal.II/doc/license.html for the  text  and     */
/*    further information on this license.                        */

#ifndef __Integrate_Difference_tpl_cc
#define __Integrate_Difference_tpl_cc

// PROJECT includes

// MPI includes
// #include <mpi.h>

// DEAL.II includes
#include <base/utilities.h>
#include <base/function.h>
#include <base/quadrature.h>

#include <lac/vector.h>

#include <fe/mapping.h>
#include <fe/fe_values.h>

#include <lac/trilinos_vector.h>
#include <lac/constraint_matrix.h>

#include <deal.II/hp/dof_handler.h>
#include <deal.II/hp/fe_values.h>
#include <deal.II/hp/mapping_collection.h>
#include <deal.II/hp/q_collection.h>

#include <numerics/vectors.h>
using namespace dealii;

// C++ includes
#include <algorithm>
#include <cmath>
#include <limits>
#include <map>
#include <numeric>
#include <vector>
using namespace std;

#endif

namespace DTMpp {

////////////////////////////////////////////////////////////////////////////////
namespace internal {
using namespace VectorTools;

template<int dim, class InVector, class OutVector, class DH, int spacedim>
void do_integrate_difference(
	const dealii::hp::MappingCollection<dim,spacedim> &mapping,
	const DH                 &dof,
	const InVector           &fe_function,
	const Function<spacedim> &exact_solution,
	OutVector                &difference,
	const dealii::hp::QCollection<dim> &hp_quad,
	const NormType &norm,
	const Function<spacedim> *weight,
	const double             _exponent) {

	const unsigned int n_components(dof.get_fe().n_components());
	const bool fe_is_system(n_components != 1);

	if (weight != NULL) {
		Assert(
			(weight->n_components==1) || (weight->n_components==n_components),
			ExcDimensionMismatch(weight->n_components, n_components)
		);
	}

// 	difference.reinit(dof.get_tria().n_active_cells());

	// Create difference vector with Epetra_Map
	// (compute difference + integrate on each cell and
	// save this into a difference vector);
	// Each process saves the locally owned cell result.
#ifdef HAVE_MPI
	Epetra_MpiComm epetra_comm(MPI_COMM_WORLD);
#else
	Epetra_SerialComm epetra_comm;
#endif

	const unsigned int n_global_active_cells(
		dynamic_cast<const dealii::parallel::distributed::Triangulation<dim> *>(
		&(dof.get_tria()))->n_global_active_cells());

	const unsigned int n_locally_owned_active_cells(
		dynamic_cast<const dealii::parallel::distributed::Triangulation<dim> *>(
		&(dof.get_tria()))->n_locally_owned_active_cells());

	Epetra_Map diff_map(n_global_active_cells, n_locally_owned_active_cells, 0,
		epetra_comm);

	difference.reinit(diff_map, false);

	IndexSet global_index_set;
	std::vector<int> global_index_vector(n_locally_owned_active_cells);
	diff_map.MyGlobalElements(&(*global_index_vector.begin()));

	double exponent(_exponent);
	switch (norm) {
	case L2_norm:
	case H1_seminorm:
	case H1_norm:
		exponent = 2.;
		break;

	case L1_norm:
		exponent = 1.;
		break;

	default:
		break;
	}

	UpdateFlags update_flags = UpdateFlags(
		update_quadrature_points | update_JxW_values);

	switch (norm) {
	case H1_seminorm:
	case W1p_seminorm:
	case W1infty_seminorm:
		update_flags |= UpdateFlags(update_gradients);
		if (spacedim == dim+1)
			update_flags |= UpdateFlags(update_normal_vectors);
		break;

	case H1_norm:
	case W1p_norm:
	case W1infty_norm:
		update_flags |= UpdateFlags(update_gradients);
		if (spacedim == dim+1)
			update_flags |= UpdateFlags(update_normal_vectors);
		// no break!
	default:
		update_flags |= UpdateFlags(update_values);
		break;
	}

	dealii::hp::FECollection<dim,spacedim> fe_collection (dof.get_fe());
	dealii::hp::FEValues<dim,spacedim> x_fe_values(
		mapping, fe_collection, hp_quad, update_flags);

	const unsigned int max_n_q_points = hp_quad.max_n_quadrature_points();

	std::vector< dealii::Vector<double> >
		function_values(
			max_n_q_points,
			dealii::Vector<double>(n_components)
		);
	std::vector<std::vector<Tensor<1,spacedim> > >
		function_grads(
			max_n_q_points,
			std::vector<Tensor<1,spacedim> >(n_components)
		);

	// tmp vector when we use the Function<spacedim> functions for
	// scalar functions
	std::vector<double> tmp_values(
			max_n_q_points
		);
	std::vector<Tensor<1,spacedim> > tmp_gradients(
			max_n_q_points
		);

	std::vector<double>
		weight_values(
			max_n_q_points
		);
	std::vector<dealii::Vector<double> >
		weight_vectors(
			max_n_q_points,
			dealii::Vector<double>(n_components)
		);

	std::vector<dealii::Vector<double> >
		psi_values(
			max_n_q_points,
			 dealii::Vector<double>(n_components)
		);
	std::vector<std::vector<Tensor<1,spacedim> > >
		psi_grads(
			max_n_q_points,
			std::vector<Tensor<1,spacedim> >(n_components)
		);
	std::vector<double>
		psi_scalar(
			max_n_q_points
		);

	// loop over all cells
	typename DH::active_cell_iterator cell(dof.begin_active());
	typename DH::active_cell_iterator endc(dof.end());

	for (unsigned int index(0); cell != endc; cell++)
	if (cell->is_locally_owned()) {
		double diff(0);
		x_fe_values.reinit(cell);

		const dealii::FEValues<dim, spacedim> &fe_values(
			x_fe_values.get_present_fe_values());
		const unsigned int n_q_points(fe_values.n_quadrature_points);

		// resize all out scratch arrays to the number of
		// quadrature points we use for the present cell
	    function_values.resize(
			n_q_points,
			dealii::Vector<double>(n_components));
	    function_grads.resize(
			n_q_points,
			std::vector<Tensor<1,spacedim> >(n_components));

		tmp_values.resize(
			n_q_points);
	    tmp_gradients.resize(
			n_q_points);

		weight_values.resize(
			n_q_points);
		weight_vectors.resize(
			n_q_points,
			dealii::Vector<double>(n_components));

	    psi_values.resize(
			n_q_points,
			dealii::Vector<double>(n_components));
	    psi_grads.resize(
			n_q_points,
			std::vector<Tensor<1,spacedim> >(n_components));
	    psi_scalar.resize(
			n_q_points);

		if (weight != NULL) {
			if (weight->n_components>1) {
				weight->vector_value_list(
					fe_values.get_quadrature_points(), weight_vectors);
			}
			else {
				weight->value_list(
					fe_values.get_quadrature_points(), weight_values);

				for (unsigned int q(0); q < n_q_points; q++) {
					weight_vectors[q] = weight_values[q];
				}
			}
		}
	    else {
			for (unsigned int q(0); q < n_q_points; q++) {
				weight_vectors[q] = 1.;
			}
		}

		if (update_flags & update_values) {
			// first compute the exact solution
			// (vectors) at the quadrature points
			// try to do this as efficient as
			// possible by avoiding a second
			// virtual function call in case
			// the function really has only
			// one component
			if (fe_is_system) {
				exact_solution.vector_value_list(
					fe_values.get_quadrature_points(), psi_values);
			}
			else {
				exact_solution.value_list(
					fe_values.get_quadrature_points(), tmp_values);

				for (unsigned int q(0); q < n_q_points; q++) {
					psi_values[q](0) = tmp_values[q];
				}
			}

			// then subtract finite element
			// fe_function
			fe_values.get_function_values(fe_function, function_values);
			for (unsigned int q(0); q < n_q_points; q++) {
				psi_values[q] -= function_values[q];
			}
		}

		// Do the same for gradients, if required
		if (update_flags & update_gradients) {
			// try to be a little clever
			// to avoid recursive virtual
			// function calls when calling
			// gradient_list for functions
			// that are really scalar
			// functions
			if (fe_is_system) {
				exact_solution.vector_gradient_list(
					fe_values.get_quadrature_points(), psi_grads);
			}
			else {
				exact_solution.gradient_list(
					fe_values.get_quadrature_points(), tmp_gradients);

				for (unsigned int q(0); q < n_q_points; q++) {
					psi_grads[q][0] = tmp_gradients[q];
				}
			}

			// then subtract finite element function_grads. We
			// need to be careful in the codimension
			// one case, since there we only have tangential gradients
			// in the finite element function, not the full
			// gradient. This is taken care of, by subtracting the
			// normal component of the gradient from the exact function.
			fe_values.get_function_grads(fe_function, function_grads);

			if (update_flags & update_normal_vectors) {
				for (unsigned int c(0); c < n_components; c++)
				for (unsigned int q(0); q < n_q_points; q++) {
					psi_grads[q][c] -= (function_grads[q][c] +
						(psi_grads[q][c] * // (f.n) n
						fe_values.normal_vector(q)) *
						fe_values.normal_vector(q));
				}
			}
			else {
				for (unsigned int c(0); c < n_components; c++)
				for (unsigned int q(0); q < n_q_points; q++) {
					psi_grads[q][c] -= function_grads[q][c];
				}
			}
		}

		switch (norm) {
		case mean:
			std::fill_n(psi_scalar.begin(), n_q_points, 0.0);

			// Compute values in quadrature points
			for (unsigned int c(0); c < n_components; c++)
			for (unsigned int q(0); q < n_q_points; q++) {
				psi_scalar[q] += psi_values[q](c) * weight_vectors[q](c);
			}

			// Integrate
			diff = std::inner_product(psi_scalar.begin(), psi_scalar.end(),
				fe_values.get_JxW_values().begin(), 0.0);

			break;

		case Lp_norm:
		case L1_norm:
		case W1p_norm:
			std::fill_n(psi_scalar.begin(), n_q_points, 0.0);

			// Compute values in quadrature points
			for (unsigned int c(0); c < n_components; c++)
			for (unsigned int q(0); q < n_q_points; q++) {
				psi_scalar[q] +=
					std::pow(psi_values[q](c)*psi_values[q](c), exponent/2.)
					* weight_vectors[q](c);
			}

			// Integrate
			diff = std::inner_product(psi_scalar.begin(), psi_scalar.end(),
				fe_values.get_JxW_values().begin(), 0.0);

			// Compute the root only,
			// if no derivative values are added later
			if (!(update_flags & update_gradients)) {
				diff = std::pow(diff, 1./exponent);
			}
			break;

		case L2_norm:
		case H1_norm:
			std::fill_n(psi_scalar.begin(), n_q_points, 0.0);

			// Compute values in quadrature points
			for (unsigned int c(0); c < n_components; c++)
			for (unsigned int q(0); q < n_q_points; q++) {
				psi_scalar[q] += psi_values[q](c)*psi_values[q](c)
					* weight_vectors[q](c);
			}

			// Integrate
			diff = std::inner_product(psi_scalar.begin(), psi_scalar.end(),
				fe_values.get_JxW_values().begin(), 0.0);

			// Compute the root only,
			// if no derivative values are added later
			if (norm == L2_norm) {
				diff = std::sqrt(diff);
			}

			break;

		case Linfty_norm:
		case W1infty_norm:
			std::fill_n(psi_scalar.begin(), n_q_points, 0.0);

			// Compute values in quadrature points
			for (unsigned int c(0); c < n_components; c++)
			for (unsigned int q(0); q < n_q_points; q++) {
				double newval =
					std::fabs(psi_values[q](c)) * weight_vectors[q](c);

				if (psi_scalar[q] < newval) {
					psi_scalar[q] = newval;
				}
			}

			// Maximum on one cell
			diff = *std::max_element(psi_scalar.begin(), psi_scalar.end());

			break;

		case H1_seminorm:
		case W1p_seminorm:
		case W1infty_seminorm:
			break;

		default:
			Assert(false, ExcNotImplemented());
			break;
		}

		switch (norm) {
		case W1p_seminorm:
		case W1p_norm:
			std::fill_n(psi_scalar.begin(), n_q_points, 0.0);

			// Compute values in quadrature points
			for (unsigned int c(0); c < n_components; c++)
			for (unsigned int q(0); q < n_q_points; q++) {
				psi_scalar[q] +=
					std::pow(psi_grads[q][c] * psi_grads[q][c], exponent/2.)
					* weight_vectors[q](c);
			}

			diff += std::inner_product(psi_scalar.begin(), psi_scalar.end(),
				fe_values.get_JxW_values().begin(), 0.0);

			diff = std::pow(diff, 1./exponent);
			break;

		case H1_seminorm:
		case H1_norm:
			// take square of integrand
			std::fill_n(psi_scalar.begin(), n_q_points, 0.0);

			// Compute values in quadrature points
			for (unsigned int c(0); c < n_components; c++)
			for (unsigned int q(0); q < n_q_points; q++) {
				psi_scalar[q] +=
				(psi_grads[q][c] * psi_grads[q][c]) * weight_vectors[q](c);
			}

			// add seminorm to L_2 norm or to zero
			diff += std::inner_product(psi_scalar.begin(), psi_scalar.end(),
				fe_values.get_JxW_values().begin(), 0.0);

			diff = std::sqrt(diff);
			break;

		case W1infty_seminorm:
		case W1infty_norm:
			Assert(false, ExcNotImplemented());
// 			std::fill_n (psi_scalar.begin(), n_q_points, 0.0);
//
// 			// Compute values in quadrature points
// 			for (unsigned int c(0); c < n_components; c++)
// 			for (unsigned int q(0); q < n_q_points; q++) {
// 				double t = 0.;
// 				for (unsigned int d(0); d < dim; d++) {
// 					t = std::max(t,std::fabs(psi_grads[q][c][d])
// 						* weight_vectors[q](c));
// 				}
//
// 				psi_scalar[q] = std::max(psi_scalar[q],t);
// 			}
//
// 			for (unsigned int i(0); i < psi_scalar.size(); i++) {
// 				diff = std::max(diff, psi_scalar[i]);
// 			}
// 			break;

		default:
			break;
		}

		// append result of this cell to the end of the vector
		Assert(numbers::is_finite(diff), ExcNumberNotFinite());
		difference(global_index_vector[index++]) = diff;
	} // if cell locally owned
// 	else {
// 		// the cell is a ghost cell or is artificial. write
// 		// a zero into the corresponding value of the returned vector
// 		difference(index) = 0;
// 	}

	// everything is done, communicate results
	difference.compress();
} // end integrate difference
} // namespace internal

} // namespace DTMpp
_______________________________________________
dealii mailing list http://poisson.dealii.org/mailman/listinfo/dealii

Reply via email to