This program was contributed by Katharina Kormann and Martin
Kronbichler.
-The algorithm for the matrix-vector product is built upon the preprint "A generic interface for parallel cell-based finite element operator application" by Martin Kronbichler and Katharina Kormann, Uppsala
-University, October 2011, and the paper "Parallel finite element operator application: Graph partitioning and coloring" by Katharina Kormann and Martin Kronbichler in: Proceedings of the 7th IEEE International Conference on e-Science, 2011.
-</i>
+The algorithm for the matrix-vector product is built upon the article <a
+href="http://dx.doi.org/10.1016/j.compfluid.2012.04.012">A generic interface
+for parallel cell-based finite element operator application</a> by Martin
+Kronbichler and Katharina Kormann, Computers and Fluids, 2012, and the paper
+"Parallel finite element operator application: Graph partitioning and
+coloring" by Katharina Kormann and Martin Kronbichler in: Proceedings of
+the 7th IEEE International Conference on e-Science, 2011. </i>
<a name="Intro"></a>
<i>p</i> is the number of shape functions in each coordinate
direction), or $p^{2d}$ to $d p^{d+1}$ in general.
+Implementing a matrix-free and cell-based finite element operator requires a
+somewhat different design compared to the usual matrix assembly codes shown in
+previous tutorial programs. The data structures for doing this are the
+MatrixFree class that collects all data and issues a (parallel) loop over all
+cells and the FEEvaluation class that evaluates finite element basis functions
+by making use of the tensor product structure.
+
The implementation of the matrix-free matrix-vector product shown in this
tutorial is slower than a matrix-vector product using a sparse matrix for
*/
struct ParallelForInteger
{
+ /**
+ * Destructor. Made virtual to ensure that derived classes also
+ * have virtual destructors.
+ */
+ virtual ~ParallelForInteger ();
+
/**
* This function runs the for loop over the
* given range <tt>[lower,upper)</tt>,
#endif
+ inline
+ ParallelForInteger::~ParallelForInteger ()
+ {}
+
+
inline
void
ParallelForInteger::apply_parallel (const std::size_t begin,
Number &
operator [] (const TableIndices<rank> &indices);
- /**
- * Access to an element according
- * to unrolled index. The
- * function
- * <tt>s.access_raw_entry(i)</tt>
- * does the same as
- * <tt>s[s.unrolled_to_component_indices(i)]</tt>,
- * but more efficiently.
- */
+ /**
+ * Access to an element according
+ * to unrolled index. The
+ * function
+ * <tt>s.access_raw_entry(i)</tt>
+ * does the same as
+ * <tt>s[s.unrolled_to_component_indices(i)]</tt>,
+ * but more efficiently.
+ */
Number
access_raw_entry (const unsigned int unrolled_index) const;
- /**
- * Access to an element according
- * to unrolled index. The
- * function
- * <tt>s.access_raw_entry(i)</tt>
- * does the same as
- * <tt>s[s.unrolled_to_component_indices(i)]</tt>,
- * but more efficiently.
- */
+ /**
+ * Access to an element according
+ * to unrolled index. The
+ * function
+ * <tt>s.access_raw_entry(i)</tt>
+ * does the same as
+ * <tt>s[s.unrolled_to_component_indices(i)]</tt>,
+ * but more efficiently.
+ */
Number &
access_raw_entry (const unsigned int unrolled_index);
T
fixed_power (const T t);
+ /**
+ * Calculate a fixed power of an integer
+ * number by a template expression where
+ * both the number <code>a</code> and the
+ * power <code>N</code> are compile-time
+ * constants. This gives compile-time
+ * knowledge of the result of the power
+ * operation.
+ *
+ * Use this function as in
+ * <code>fixed_int_power@<a,N@>::value</code>.
+ */
+ template <int a, int N>
+ struct fixed_int_power
+ {
+ static const int value = a * fixed_int_power<a,N-1>::value;
+ };
+
+ /**
+ * Base case for the power operation with
+ * <code>N=0</code>, which gives the result
+ * 1.
+ */
+ template <int a>
+ struct fixed_int_power<a,0>
+ {
+ static const int value = 1;
+ };
+
/**
* Optimized replacement for
* <tt>std::lower_bound</tt> for
*/
unsigned int get_degree () const;
+ /**
+ * Return the numbering of the underlying
+ * polynomial space compared to
+ * lexicographic ordering of the basis
+ * functions. Returns
+ * POLY::get_numbering().
+ */
+ std::vector<unsigned int> get_poly_space_numbering() const;
+
+ /**
+ * Return the inverse numbering of the
+ * underlying polynomial space. Returns
+ * POLY::get_numbering_inverse().
+ */
+ std::vector<unsigned int> get_poly_space_numbering_inverse() const;
+
/**
* Return the value of the
* <tt>i</tt>th shape function at
this->compute_2nd (mapping, cell, offset, mapping_data, fe_data, data);
}
+
+
+namespace internal
+{
+ template <class POLY>
+ inline
+ std::vector<unsigned int>
+ get_poly_space_numbering (const POLY&)
+ {
+ Assert (false, ExcNotImplemented());
+ return std::vector<unsigned int>();
+ }
+
+ template <class POLY>
+ inline
+ std::vector<unsigned int>
+ get_poly_space_numbering_inverse (const POLY&)
+ {
+ Assert (false, ExcNotImplemented());
+ return std::vector<unsigned int>();
+ }
+
+ template <int dim>
+ inline
+ std::vector<unsigned int>
+ get_poly_space_numbering (const TensorProductPolynomials<dim> &poly)
+ {
+ return poly.get_numbering();
+ }
+
+ template <int dim>
+ inline
+ std::vector<unsigned int>
+ get_poly_space_numbering_inverse (const TensorProductPolynomials<dim> &poly)
+ {
+ return poly.get_numbering_inverse();
+ }
+}
+
+
+
+template <class POLY, int dim, int spacedim>
+std::vector<unsigned int>
+FE_Poly<POLY,dim,spacedim>::get_poly_space_numbering () const
+{
+ return internal::get_poly_space_numbering (poly_space);
+}
+
+
+
+
+template <class POLY, int dim, int spacedim>
+std::vector<unsigned int>
+FE_Poly<POLY,dim,spacedim>::get_poly_space_numbering_inverse () const
+{
+ return internal::get_poly_space_numbering_inverse (poly_space);
+}
+
+
+
DEAL_II_NAMESPACE_CLOSE
const std::vector<unsigned int> &lexicographic_inv,
const ConstraintMatrix &constraints,
const unsigned int cell_number,
- internal::ConstraintValues<double>&constraint_values,
+ ConstraintValues<double>&constraint_values,
bool &cell_at_boundary);
/**
*/
void assign_ghosts(const std::vector<unsigned int> &boundary_cells);
+ /**
+ * Reorganizes cells for serial
+ * (non-thread-parallelized) such that
+ * boundary cells are places in the
+ * middle. This way, computations and
+ * communication can be overlapped. Should
+ * only be called by one DoFInfo object when
+ * used on a system of several DoFHandlers.
+ */
+ void compute_renumber_serial (const std::vector<unsigned int> &boundary_cells,
+ const SizeInfo &size_info,
+ std::vector<unsigned int> &renumbering);
+
+ /**
+ * Reorganizes cells in the hp case without
+ * parallelism such that all cells with the
+ * same FE index are placed
+ * consecutively. Should only be called by one
+ * DoFInfo object when used on a system of
+ * several DoFHandlers.
+ */
+ void compute_renumber_hp_serial (SizeInfo &size_info,
+ std::vector<unsigned int> &renumbering,
+ std::vector<unsigned int> &irregular_cells);
+
+ /**
+ * Computes the initial renumbering of cells
+ * such that all cells with ghosts are put
+ * first. This is the first step before
+ * building the thread graph and used to
+ * overlap computations and communication.
+ */
+ void compute_renumber_parallel (const std::vector<unsigned int> &boundary_cells,
+ SizeInfo &size_info,
+ std::vector<unsigned int> &renumbering);
+
/**
* This method reorders the way cells are gone
* through based on a given renumbering of the
- * cells. It also takes @p n_vectors cells
- * together and interprets them as one cell
- * only, as is needed for vectorization.
+ * cells. It also takes @p
+ * vectorization_length cells together and
+ * interprets them as one cell only, as is
+ * needed for vectorization.
*/
void reorder_cells (const SizeInfo &size_info,
const std::vector<unsigned int> &renumbering,
const std::vector<unsigned int> &constraint_pool_row_index,
const std::vector<unsigned int> &irregular_cells,
- const unsigned int n_vectors);
+ const unsigned int vectorization_length);
/**
* This helper function determines a block
const SizeInfo &size_info) const;
/**
- * Returns the memory consumption in bytes of
- * this class.
+ * Prints a representation of the
+ * indices in the class to the given
+ * output stream.
*/
template <typename Number>
- void print (const CompressedMatrix<Number> &constraint_pool,
- std::ostream &out) const;
+ void print (const std::vector<Number> &constraint_pool_data,
+ const std::vector<unsigned int> &constraint_pool_row_index,
+ std::ostream &out) const;
/**
* Stores the rowstart indices of the
* reading from or writing to a vector. The
* second number stores the index of the
* constraint weights, stored in the variable
- * constraint_pool.
+ * constraint_pool_data.
*/
std::vector<std::pair<unsigned short,unsigned short> > constraint_indicator;
{
namespace MatrixFreeFunctions
{
- namespace internal
- {
+
/**
* A struct that takes entries describing
* a constraint and puts them into a
unsigned short
insert_entries (const std::vector<std::pair<unsigned int,double> > &entries);
- CompressedMatrix<Number> constraint_pool;
+ std::vector<Number> constraint_pool_data;
+ std::vector<unsigned int> constraint_pool_row_index;
std::vector<std::pair<unsigned int, unsigned int> > pool_locations;
std::vector<std::pair<Number,unsigned int> > constraint_entries;
std::vector<unsigned int> constraint_indices;
:
hashes (1.)
{
- constraint_pool.row_index.push_back (0);
+ constraint_pool_row_index.push_back (0);
}
template <typename Number>
// If constraint has to be added, which will
// be its no.
- test.second = constraint_pool.row_index.size()-1;
+ test.second = constraint_pool_row_index.size()-1;
// Hash value larger than all the ones
// before. We need to add it.
while(is_same == true)
{
if(one_constraint.size()!=
- (constraint_pool.row_length(pos->second)))
+ (constraint_pool_row_index[pos->second+1]-
+ constraint_pool_row_index[pos->second]))
// The constraints have different length, and
// hence different.
is_same = false;
for (unsigned int q=0; q<one_constraint.size(); ++q)
// check whether or not all weights are the
// same.
- if (std::fabs(constraint_pool.data[constraint_pool.
- row_index[pos->second]+q]-
+ if (std::fabs(constraint_pool_data[constraint_pool_row_index
+ [pos->second]+q]-
one_constraint[q])>hashes.scaling)
{
is_same = false;
// Remember hash value and location of
// constraint.
- constraint_pool.data.insert_back(one_constraint.begin(),
- one_constraint.end());
- constraint_pool.complete_last_row();
+ constraint_pool_data.insert (constraint_pool_data.end(),
+ one_constraint.begin(),
+ one_constraint.end());
+ constraint_pool_row_index.push_back (constraint_pool_data.size());
// Add the location of constraint in pool.
insert_position = test.second;
ExcInternalError());
return static_cast<unsigned short>(insert_position);
}
- } // end of namespace internal
const std::vector<unsigned int> &lexicographic_inv,
const ConstraintMatrix &constraints,
const unsigned int cell_number,
- internal::ConstraintValues<double> &constraint_values,
+ ConstraintValues<double> &constraint_values,
bool &cell_at_boundary)
{
Assert (vector_partitioner.get() !=0, ExcInternalError());
for (unsigned int j=0; j<row_length_indicators(cell_number); ++j)
{
n_dofs += blb[j].first;
- n_dofs += constraint_values.constraint_pool.row_length(blb[j].second);
+ n_dofs += constraint_values.constraint_pool_row_index[blb[j].second+1]
+ - constraint_values.constraint_pool_row_index[blb[j].second];
}
n_dofs += constraint_iterator.first;
AssertDimension(n_dofs, row_length_indices(cell_number));
std::vector<unsigned int> new_ghosts;
ghost_dofs.swap(new_ghosts);
+
// set the ghost indices now. need to cast
// away constness here, but that is uncritical
// since we reset the Partitioner in the same
+ void
+ DoFInfo::compute_renumber_serial (const std::vector<unsigned int> &boundary_cells,
+ const SizeInfo &size_info,
+ std::vector<unsigned int> &renumbering)
+ {
+ std::vector<unsigned int> reverse_numbering (size_info.n_active_cells,
+ numbers::invalid_unsigned_int);
+ const unsigned int n_boundary_cells = boundary_cells.size();
+ for (unsigned int j=0; j<n_boundary_cells; ++j)
+ reverse_numbering[boundary_cells[j]] =
+ j + size_info.vectorization_length*size_info.boundary_cells_start;
+ unsigned int counter = 0;
+ unsigned int j = 0;
+ while (counter < size_info.n_active_cells &&
+ counter < size_info.vectorization_length * size_info.boundary_cells_start)
+ {
+ if (reverse_numbering[j] == numbers::invalid_unsigned_int)
+ reverse_numbering[j] = counter++;
+ j++;
+ }
+ counter = std::min (size_info.vectorization_length*
+ size_info.boundary_cells_start+n_boundary_cells,
+ size_info.n_active_cells);
+ if (counter < size_info.n_active_cells)
+ {
+ for ( ; j<size_info.n_active_cells; ++j)
+ if (reverse_numbering[j] == numbers::invalid_unsigned_int)
+ reverse_numbering[j] = counter++;
+ }
+ AssertDimension (counter, size_info.n_active_cells);
+ renumbering = Utilities::invert_permutation (reverse_numbering);
+ }
+
+
+
+ void
+ DoFInfo::compute_renumber_hp_serial (SizeInfo &size_info,
+ std::vector<unsigned int> &renumbering,
+ std::vector<unsigned int> &irregular_cells)
+ {
+ const unsigned int n_active_cells = size_info.n_active_cells;
+ const unsigned int vectorization_length = size_info.vectorization_length;
+ irregular_cells.resize (0);
+ irregular_cells.resize (size_info.n_macro_cells+3*max_fe_index);
+ std::vector<std::vector<unsigned int> > renumbering_fe_index;
+ renumbering_fe_index.resize(max_fe_index);
+ unsigned int counter,n_macro_cells_before = 0;
+ const unsigned int
+ start_bound = std::min (size_info.n_active_cells,
+ size_info.boundary_cells_start*vectorization_length),
+ end_bound = std::min (size_info.n_active_cells,
+ size_info.boundary_cells_end*vectorization_length);
+ for(counter=0; counter<start_bound; counter++)
+ {
+ renumbering_fe_index[cell_active_fe_index[renumbering[counter]]].
+ push_back(renumbering[counter]);
+ }
+ counter = 0;
+ for (unsigned int j=0;j<max_fe_index;j++)
+ {
+ for(unsigned int jj=0;jj<renumbering_fe_index[j].size();jj++)
+ renumbering[counter++] = renumbering_fe_index[j][jj];
+ irregular_cells[renumbering_fe_index[j].size()/vectorization_length+
+ n_macro_cells_before] =
+ renumbering_fe_index[j].size()%vectorization_length;
+ n_macro_cells_before += (renumbering_fe_index[j].size()+vectorization_length-1)/
+ vectorization_length;
+ renumbering_fe_index[j].resize(0);
+ }
+ unsigned int new_boundary_start = n_macro_cells_before;
+ for(counter = start_bound; counter < end_bound; counter++)
+ {
+ renumbering_fe_index[cell_active_fe_index[renumbering[counter]]].
+ push_back(renumbering[counter]);
+ }
+ counter = start_bound;
+ for (unsigned int j=0;j<max_fe_index;j++)
+ {
+ for(unsigned int jj=0;jj<renumbering_fe_index[j].size();jj++)
+ renumbering[counter++] = renumbering_fe_index[j][jj];
+ irregular_cells[renumbering_fe_index[j].size()/vectorization_length+
+ n_macro_cells_before] =
+ renumbering_fe_index[j].size()%vectorization_length;
+ n_macro_cells_before += (renumbering_fe_index[j].size()+vectorization_length-1)/
+ vectorization_length;
+ renumbering_fe_index[j].resize(0);
+ }
+ unsigned int new_boundary_end = n_macro_cells_before;
+ for(counter=end_bound; counter<n_active_cells; counter++)
+ {
+ renumbering_fe_index[cell_active_fe_index[renumbering[counter]]].
+ push_back(renumbering[counter]);
+ }
+ counter = end_bound;
+ for (unsigned int j=0;j<max_fe_index;j++)
+ {
+ for(unsigned int jj=0;jj<renumbering_fe_index[j].size();jj++)
+ renumbering[counter++] = renumbering_fe_index[j][jj];
+ irregular_cells[renumbering_fe_index[j].size()/vectorization_length+
+ n_macro_cells_before] =
+ renumbering_fe_index[j].size()%vectorization_length;
+ n_macro_cells_before += (renumbering_fe_index[j].size()+vectorization_length-1)/
+ vectorization_length;
+ }
+ AssertIndexRange (n_macro_cells_before,
+ size_info.n_macro_cells + 3*max_fe_index+1);
+ irregular_cells.resize (n_macro_cells_before);
+ size_info.n_macro_cells = n_macro_cells_before;
+ size_info.boundary_cells_start = new_boundary_start;
+ size_info.boundary_cells_end = new_boundary_end;
+ }
+
+
+
+ void
+ DoFInfo::compute_renumber_parallel (const std::vector<unsigned int> &boundary_cells,
+ SizeInfo &size_info,
+ std::vector<unsigned int> &renumbering)
+ {
+ std::vector<unsigned int> reverse_numbering (size_info.n_active_cells,
+ numbers::invalid_unsigned_int);
+ const unsigned int n_boundary_cells = boundary_cells.size();
+ for (unsigned int j=0; j<n_boundary_cells; ++j)
+ reverse_numbering[boundary_cells[j]] = j;
+ unsigned int counter = n_boundary_cells;
+ for (unsigned int j=0; j<size_info.n_active_cells; ++j)
+ if (reverse_numbering[j] == numbers::invalid_unsigned_int)
+ reverse_numbering[j] = counter++;
+
+ size_info.boundary_cells_end = (size_info.boundary_cells_end -
+ size_info.boundary_cells_start);
+ size_info.boundary_cells_start = 0;
+
+ AssertDimension (counter, size_info.n_active_cells);
+ renumbering = Utilities::invert_permutation (reverse_numbering);
+ }
+
+
+
void
DoFInfo::reorder_cells (const SizeInfo &size_info,
const std::vector<unsigned int> &renumbering,
const std::vector<unsigned int> &constraint_pool_row_index,
const std::vector<unsigned int> &irregular_cells,
- const unsigned int n_vectors)
+ const unsigned int vectorization_length)
{
// first reorder the active fe index.
if (cell_active_fe_index.size() > 0)
{
std::vector<unsigned int> new_active_fe_index;
new_active_fe_index.reserve (size_info.n_macro_cells);
- std::vector<unsigned int> fe_indices(n_vectors);
+ std::vector<unsigned int> fe_indices(vectorization_length);
unsigned int position_cell = 0;
for (unsigned int cell=0; cell<size_info.n_macro_cells; ++cell)
{
const unsigned int n_comp = (irregular_cells[cell] > 0 ?
- irregular_cells[cell] : n_vectors);
+ irregular_cells[cell] : vectorization_length);
for (unsigned int j=0; j<n_comp; ++j)
fe_indices[j]=cell_active_fe_index[renumbering[position_cell+j]];
// first dof index 0 for all vectors, then dof
// index 1 for all vectors, and so on. This
// involves some extra resorting.
- std::vector<const unsigned int*> glob_indices (n_vectors);
- std::vector<const unsigned int*> plain_glob_indices (n_vectors);
+ std::vector<const unsigned int*> glob_indices (vectorization_length);
+ std::vector<const unsigned int*> plain_glob_indices (vectorization_length);
std::vector<const std::pair<unsigned short,unsigned short>*>
- constr_ind(n_vectors), constr_end(n_vectors);
- std::vector<unsigned int> index(n_vectors);
+ constr_ind(vectorization_length), constr_end(vectorization_length);
+ std::vector<unsigned int> index(vectorization_length);
for (unsigned int i=0; i<size_info.n_macro_cells; ++i)
{
const unsigned int dofs_mcell =
dofs_per_cell[cell_active_fe_index.size() == 0 ? 0 :
- cell_active_fe_index[i]] * n_vectors;
+ cell_active_fe_index[i]] * vectorization_length;
new_row_starts[i] =
std_cxx1x::tuple<unsigned int,unsigned int,unsigned int>
(new_dof_indices.size(), new_constraint_indicator.size(),
irregular_cells[i]);
const unsigned int n_comp = (irregular_cells[i]>0 ?
- irregular_cells[i] : n_vectors);
+ irregular_cells[i] : vectorization_length);
for (unsigned int j=0; j<n_comp; ++j)
{
unsigned int m_ind_local = 0, m_index = 0;
while (m_ind_local < dofs_mcell)
- for (unsigned int j=0; j<n_vectors; ++j)
+ for (unsigned int j=0; j<vectorization_length; ++j)
{
// last cell: nothing to do
if (j >= n_comp)
// if there are too few degrees of freedom per
// cell, need to increase the block size
+ const unsigned int minimum_parallel_grain_size = 500;
if (dofs_per_cell[0] * task_info.block_size <
- internal::minimum_parallel_grain_size)
- task_info.block_size = (internal::minimum_parallel_grain_size /
+ minimum_parallel_grain_size)
+ task_info.block_size = (minimum_parallel_grain_size /
dofs_per_cell[0] + 1);
}
if (task_info.block_size > size_info.n_macro_cells)
if (size_info.n_macro_cells == 0)
return;
- const std::size_t n_vectors = size_info.n_vectors;
- Assert (n_vectors > 0, ExcInternalError());
+ const std::size_t vectorization_length = size_info.vectorization_length;
+ Assert (vectorization_length > 0, ExcInternalError());
guess_block_size (size_info, task_info);
std::vector<std::vector<unsigned int> > renumbering_fe_index;
renumbering_fe_index.resize(max_fe_index);
unsigned int counter,n_macro_cells_before = 0;
- for(counter=0;counter<start_nonboundary*n_vectors;
+ for(counter=0;counter<start_nonboundary*vectorization_length;
counter++)
{
renumbering_fe_index[cell_active_fe_index[renumbering[counter]]].
{
for(unsigned int jj=0;jj<renumbering_fe_index[j].size();jj++)
renumbering[counter++] = renumbering_fe_index[j][jj];
- irregular_cells[renumbering_fe_index[j].size()/n_vectors+
+ irregular_cells[renumbering_fe_index[j].size()/vectorization_length+
n_macro_cells_before] =
- renumbering_fe_index[j].size()%n_vectors;
- n_macro_cells_before += (renumbering_fe_index[j].size()+n_vectors-1)/
- n_vectors;
+ renumbering_fe_index[j].size()%vectorization_length;
+ n_macro_cells_before += (renumbering_fe_index[j].size()+vectorization_length-1)/
+ vectorization_length;
renumbering_fe_index[j].resize(0);
}
unsigned int new_boundary_end = n_macro_cells_before;
- for(counter=start_nonboundary*n_vectors;
+ for(counter=start_nonboundary*vectorization_length;
counter<size_info.n_active_cells; counter++)
{
renumbering_fe_index[cell_active_fe_index[renumbering[counter]]].
push_back(renumbering[counter]);
}
- counter = start_nonboundary * n_vectors;
+ counter = start_nonboundary * vectorization_length;
for (unsigned int j=0;j<max_fe_index;j++)
{
for(unsigned int jj=0;jj<renumbering_fe_index[j].size();jj++)
renumbering[counter++] = renumbering_fe_index[j][jj];
- irregular_cells[renumbering_fe_index[j].size()/n_vectors+
+ irregular_cells[renumbering_fe_index[j].size()/vectorization_length+
n_macro_cells_before] =
- renumbering_fe_index[j].size()%n_vectors;
- n_macro_cells_before += (renumbering_fe_index[j].size()+n_vectors-1)/
- n_vectors;
+ renumbering_fe_index[j].size()%vectorization_length;
+ n_macro_cells_before += (renumbering_fe_index[j].size()+vectorization_length-1)/
+ vectorization_length;
}
AssertIndexRange (n_macro_cells_before,
size_info.n_macro_cells + 2*max_fe_index+1);
size_info.n_macro_cells);
std::vector<bool> color_finder;
+ // this performs a classical breath-first
+ // search in the connectivity graph of the
+ // cell chunks
while(work)
{
// put all cells up to begin_inner_cells into
// Color the cells within each partition
- task_info.partition_color_blocks.row_index.resize(partition+1);
+ task_info.partition_color_blocks_row_index.resize(partition+1);
unsigned int color_counter = 0, index_counter = 0;
for(unsigned int part=0; part<partition; part++)
{
- task_info.partition_color_blocks.row_index[part] = index_counter;
+ task_info.partition_color_blocks_row_index[part] = index_counter;
unsigned int max_color = 0;
for (unsigned int k=partition_blocks[part]; k<partition_blocks[part+1];
k++)
// the number the larger the partition)
for(unsigned int color=0; color<=max_color; color++)
{
- task_info.partition_color_blocks.data.push_back(color_counter);
+ task_info.partition_color_blocks_data.push_back(color_counter);
index_counter++;
for (unsigned int k=partition_blocks[part];
k<partition_blocks[part+1]; k++)
}
}
}
- task_info.partition_color_blocks.data.push_back(task_info.n_blocks);
- task_info.partition_color_blocks.row_index[partition] = index_counter;
+ task_info.partition_color_blocks_data.push_back(task_info.n_blocks);
+ task_info.partition_color_blocks_row_index[partition] = index_counter;
AssertDimension (color_counter, task_info.n_blocks);
partition_list = renumbering;
++mcell)
{
unsigned int n_comp = (irregular_cells[mcell]>0)
- ?irregular_cells[mcell]:size_info.n_vectors;
+ ?irregular_cells[mcell]:size_info.vectorization_length;
block_start[block+1] += n_comp;
++counter;
}
task_info.odds = (partition)>>1;
task_info.n_blocked_workers = task_info.odds-
(task_info.odds+task_info.evens+1)%2;
- task_info.n_workers = task_info.partition_color_blocks.data.size()-1-
+ task_info.n_workers = task_info.partition_color_blocks_data.size()-1-
task_info.n_blocked_workers;
}
if (size_info.n_macro_cells == 0)
return;
- const std::size_t n_vectors = size_info.n_vectors;
- Assert (n_vectors > 0, ExcInternalError());
+ const std::size_t vectorization_length = size_info.vectorization_length;
+ Assert (vectorization_length > 0, ExcInternalError());
guess_block_size (size_info, task_info);
task_info.block_size_last = size_info.n_macro_cells-
(task_info.block_size*(task_info.n_blocks-1));
task_info.position_short_block = task_info.n_blocks-1;
- unsigned int cluster_size = task_info.block_size*n_vectors;
+ unsigned int cluster_size = task_info.block_size*vectorization_length;
// create the connectivity graph without
// internal blocking
make_connectivity_graph (size_info, task_info, renumbering,irregular_cells,
false, connectivity);
- // Create cell-block partitioning.
+ // Create cell-block partitioning.
- // For each block of cells, this variable
- // saves to which partitions the block
- // belongs. Initialize all to n_macro_cells to
- // mark them as not yet assigned a partition.
+ // For each block of cells, this variable
+ // saves to which partitions the block
+ // belongs. Initialize all to n_macro_cells to
+ // mark them as not yet assigned a partition.
std::vector<unsigned int> cell_partition (size_info.n_active_cells,
size_info.n_active_cells);
std::vector<unsigned int> neighbor_list;
std::vector<unsigned int> neighbor_neighbor_list;
- // In element j of this variable, one puts the
- // old number of the block that should be the
- // jth block in the new numeration.
+ // In element j of this variable, one puts the
+ // old number of the block that should be the
+ // jth block in the new numeration.
std::vector<unsigned int> partition_list(size_info.n_active_cells,0);
std::vector<unsigned int> partition_partition_list(size_info.n_active_cells,0);
- // This vector points to the start of each
- // partition.
+ // This vector points to the start of each
+ // partition.
std::vector<unsigned int> partition_size(2,0);
unsigned int partition = 0,start_up=0,counter=0;
- unsigned int start_nonboundary = n_vectors * size_info.boundary_cells_end;
+ unsigned int start_nonboundary = vectorization_length * size_info.boundary_cells_end;
if (start_nonboundary > size_info.n_active_cells)
start_nonboundary = size_info.n_active_cells;
bool work = true;
unsigned int remainder = cluster_size;
+
+ // this performs a classical breath-first
+ // search in the connectivity graph of the
+ // cells under the restriction that the size
+ // of the partitions should be a multiple of
+ // the given block size
while (work)
{
- // put the cells with neighbors on remote MPI
- // processes up front
+ // put the cells with neighbors on remote MPI
+ // processes up front
if(start_nonboundary>0)
{
for(unsigned int cell=0; cell<start_nonboundary; ++cell)
// adjust end of boundary cells to the
// remainder
- size_info.boundary_cells_end += (remainder+n_vectors-1)/n_vectors;
+ size_info.boundary_cells_end += (remainder+vectorization_length-1)/vectorization_length;
}
else
{
// mark them as not yet assigned a partition.
std::vector<unsigned int> cell_partition_l2(size_info.n_active_cells,
size_info.n_active_cells);
- task_info.partition_color_blocks.row_index.resize(partition+1,0);
- task_info.partition_color_blocks.data.resize(1,0);
+ task_info.partition_color_blocks_row_index.resize(partition+1,0);
+ task_info.partition_color_blocks_data.resize(1,0);
start_up = 0;
counter = 0;
for (unsigned int j=0; j<max_fe_index; j++)
{
remaining_per_macro_cell[j] =
- renumbering_fe_index[j].size()%n_vectors;
+ renumbering_fe_index[j].size()%vectorization_length;
if(remaining_per_macro_cell[j] != 0)
filled = false;
missing_macros += ((renumbering_fe_index[j].size()+
- n_vectors-1)/n_vectors);
+ vectorization_length-1)/vectorization_length);
}
}
else
{
remaining_per_macro_cell.resize(1);
remaining_per_macro_cell[0] = partition_counter%
- n_vectors;
- missing_macros = partition_counter/n_vectors;
+ vectorization_length;
+ missing_macros = partition_counter/vectorization_length;
if(remaining_per_macro_cell[0] != 0)
{
filled = false;
missing_macros--;
remaining_per_macro_cell[this_index]++;
if (remaining_per_macro_cell[this_index]
- == n_vectors)
+ == vectorization_length)
{
remaining_per_macro_cell[this_index] = 0;
}
size(); jj++)
renumbering[cell++] =
renumbering_fe_index[j][jj];
- if(renumbering_fe_index[j].size()%n_vectors != 0)
+ if(renumbering_fe_index[j].size()%vectorization_length != 0)
irregular_cells[renumbering_fe_index[j].size()/
- n_vectors+
+ vectorization_length+
n_macro_cells_before] =
- renumbering_fe_index[j].size()%n_vectors;
+ renumbering_fe_index[j].size()%vectorization_length;
n_macro_cells_before += (renumbering_fe_index[j].
- size()+n_vectors-1)/
- n_vectors;
+ size()+vectorization_length-1)/
+ vectorization_length;
renumbering_fe_index[j].resize(0);
}
}
else
{
- n_macro_cells_before += partition_counter/n_vectors;
- if(partition_counter%n_vectors != 0)
+ n_macro_cells_before += partition_counter/vectorization_length;
+ if(partition_counter%vectorization_length != 0)
{
irregular_cells[n_macro_cells_before] =
- partition_counter%n_vectors;
+ partition_counter%vectorization_length;
n_macro_cells_before++;
}
}
}
- task_info.partition_color_blocks.data.
+ task_info.partition_color_blocks_data.
push_back(n_macro_cells_before);
partition_l2++;
}
neighbor_list = neighbor_neighbor_list;
neighbor_neighbor_list.resize(0);
}
- task_info.partition_color_blocks.row_index[part+1] =
- task_info.partition_color_blocks.row_index[part] + partition_l2;
+ task_info.partition_color_blocks_row_index[part+1] =
+ task_info.partition_color_blocks_row_index[part] + partition_l2;
}
}
if(size_info.boundary_cells_end>0)
- size_info.boundary_cells_end = task_info.partition_color_blocks.
- data[task_info.partition_color_blocks.row_index[1]];
+ size_info.boundary_cells_end = task_info.partition_color_blocks_data
+ [task_info.partition_color_blocks_row_index[1]];
if (hp_bool == false)
renumbering.swap(partition_partition_list);
for(unsigned int part=0;part<partition;part++)
{
task_info.partition_evens[part] =
- (task_info.partition_color_blocks.row_index[part+1]-
- task_info.partition_color_blocks.row_index[part]+1)/2;
+ (task_info.partition_color_blocks_row_index[part+1]-
+ task_info.partition_color_blocks_row_index[part]+1)/2;
task_info.partition_odds[part] =
- (task_info.partition_color_blocks.row_index[part+1]-
- task_info.partition_color_blocks.row_index[part])/2;
+ (task_info.partition_color_blocks_row_index[part+1]-
+ task_info.partition_color_blocks_row_index[part])/2;
task_info.partition_n_blocked_workers[part] =
task_info.partition_odds[part]-(task_info.partition_odds[part]+
task_info.partition_evens[part]+1)%2;
++mcell)
{
unsigned int n_comp = (irregular_cells[mcell]>0)
- ?irregular_cells[mcell]:size_info.n_vectors;
+ ?irregular_cells[mcell]:size_info.vectorization_length;
for (unsigned int cell = cell_start; cell < cell_start+n_comp;
++cell)
{
++mcell)
{
unsigned int n_comp = (irregular_cells[mcell]>0)
- ?irregular_cells[mcell]:size_info.n_vectors;
+ ?irregular_cells[mcell]:size_info.vectorization_length;
for (unsigned int cell = cell_start; cell < cell_start+n_comp;
++cell)
{
const SizeInfo &size_info) const
{
out << " Memory row starts indices: ";
- size_info.print_mem (out, (row_starts.capacity()*
- sizeof(std_cxx1x::tuple<unsigned int,
- unsigned int, unsigned int>)));
+ size_info.print_memory_statistics
+ (out, (row_starts.capacity()*sizeof(std_cxx1x::tuple<unsigned int,
+ unsigned int, unsigned int>)));
out << " Memory dof indices: ";
- size_info.print_mem (out, MemoryConsumption::memory_consumption (dof_indices));
+ size_info.print_memory_statistics
+ (out, MemoryConsumption::memory_consumption (dof_indices));
out << " Memory constraint indicators: ";
- size_info.print_mem (out, MemoryConsumption::memory_consumption (constraint_indicator));
+ size_info.print_memory_statistics
+ (out, MemoryConsumption::memory_consumption (constraint_indicator));
out << " Memory plain indices: ";
- size_info.print_mem (out, MemoryConsumption::memory_consumption (row_starts_plain_indices)+
- MemoryConsumption::memory_consumption (plain_dof_indices));
+ size_info.print_memory_statistics
+ (out, MemoryConsumption::memory_consumption (row_starts_plain_indices)+
+ MemoryConsumption::memory_consumption (plain_dof_indices));
out << " Memory vector partitioner: ";
- size_info.print_mem (out, MemoryConsumption::memory_consumption (*vector_partitioner));
+ size_info.print_memory_statistics
+ (out, MemoryConsumption::memory_consumption (*vector_partitioner));
}
template <typename Number>
void
- DoFInfo::print (const CompressedMatrix<Number> &constraint_pool,
- std::ostream &out) const
+ DoFInfo::print (const std::vector<Number> &constraint_pool_data,
+ const std::vector<unsigned int> &constraint_pool_row_index,
+ std::ostream &out) const
{
const unsigned int n_rows = row_starts.size() - 1;
for (unsigned int row=0 ; row<n_rows ; ++row)
}
out << "[ ";
- for(unsigned int k=constraint_pool.row_index[con_it->second];
- k<constraint_pool.row_index[con_it->second+1];
+ for(unsigned int k=constraint_pool_row_index[con_it->second];
+ k<constraint_pool_row_index[con_it->second+1];
k++,index++)
{
Assert (glob_indices+index != end_row, ExcInternalError());
out << glob_indices[index] << "/"
- << constraint_pool.data[k];
- if (k<constraint_pool.row_index[con_it->second+1]-1)
+ << constraint_pool_data[k];
+ if (k<constraint_pool_row_index[con_it->second+1]-1)
out << " ";
}
out << "] ";
/**
* This is the base class for the FEEvaluation classes. This class is a base
* class and needs usually not be called in user code. Use one of the derived
- * classes instead. It implements access functions to vectors for the @p
- * read_dof_values, @p set_dof_values, and @p distributed_local_to_global
- * functions, as well as the @p reinit method.
+ * classes FEEvaluationGeneral, FEEvaluation or FEEvaluationGL instead. It
+ * implements a reinit method that is used to set pointers so that operations
+ * on quadrature points can be performed quickly, access functions to vectors
+ * for the @p read_dof_values, @p set_dof_values, and @p
+ * distributed_local_to_global functions, as well as methods to access values
+ * and gradients of finite element functions.
*
* This class has five template arguments:
*
class FEEvaluationBase
{
public:
- typedef VectorizedArray<Number> vector_t;
- static const std::size_t n_vectors =
- VectorizedArray<Number>::n_array_elements;
+ typedef Tensor<1,n_components,VectorizedArray<Number> > value_type;
+ typedef Tensor<1,n_components,Tensor<1,dim,VectorizedArray<Number> > > gradient_type;
+ static const unsigned int dimension = dim;
static const unsigned int dofs_per_cell = dofs_per_cell_;
static const unsigned int n_q_points = n_q_points_;
/**
- * Constructor. Takes all data stored in
- * MatrixFree. If applied to problems with
- * more than one finite element or more than
- * one quadrature formula selected during
- * construction of @p matrix_free, @p
- * fe_no and @p quad_no allow to select the
- * appropriate components.
+ * @name 1: General operations
*/
- FEEvaluationBase (const MatrixFree<dim,Number> &matrix_free,
- const unsigned int fe_no = 0,
- const unsigned int quad_no = 0);
-
+ //@{
/**
* Initializes the operation pointer to the
* current cell. Unlike the FEValues::reinit
* index which belongs to the current cell as
* specified in @p reinit. Note that
* MappingInfo has different fields for
- * Cartesian cells, cells with linear mapping
+ * Cartesian cells, cells with affine mapping
* and with general mappings, so in order to
* access the correct data, this interface
* must be used together with get_cell_type.
unsigned int get_cell_data_number() const;
/**
- * Returns the type of the cell the @p reinit
- * function has been called for. 0 means
- * Cartesian cells (which allows for
- * considerable data compression), 1 means
- * cells with linear mappings, and 2 means
- * general cells without any compressed
- * storage applied.
+ * Returns the type of the cell the @p
+ * reinit function has been called
+ * for. Valid values are @p cartesian
+ * for Cartesian cells (which allows
+ * for considerable data compression),
+ * @p affine for cells with affine
+ * mappings, and @p general for
+ * general cells without any
+ * compressed storage applied.
*/
- unsigned int get_cell_type() const;
+ internal::MatrixFreeFunctions::CellType get_cell_type() const;
- /**
- * Returns a read-only pointer to the first
- * field of function values on quadrature
- * points. First come the function values on
- * all quadrature points for the first
- * component, then all values for the second
- * component, and so on. This is related to
- * the internal data structures used in this
- * class. The raw data after a call to @p
- * evaluate only contains unit cell
- * operations, so possible transformations,
- * quadrature weights etc. must be applied
- * manually. In general, it is safer to use
- * the get_value() function instead, which
- * does all the transformation internally.
- */
- const vector_t * begin_values () const;
-
- /**
- * Returns a read and write pointer to the
- * first field of function values on
- * quadrature points. First come the function
- * values on all quadrature points for the
- * first component, then all values for the
- * second component, and so on. This is
- * related to the internal data structures
- * used in this class. The raw data after a
- * call to @p evaluate only contains unit
- * cell operations, so possible
- * transformations, quadrature weights
- * etc. must be applied manually. In general,
- * it is safer to use the get_value() function
- * instead, which does all the transformation
- * internally.
- */
- vector_t * begin_values ();
+ //@}
/**
- * Returns a read-only pointer to the first
- * field of function gradients on quadrature
- * points. First comes the x-component of the
- * gradient for the first component on all
- * quadrature points, then the y-component,
- * and so on. Next comes the x-component of
- * the second component, and so on. This is
- * related to the internal data structures
- * used in this class. The raw data after a
- * call to @p evaluate only contains unit
- * cell operations, so possible
- * transformations, quadrature weights
- * etc. must be applied manually. In general,
- * it is safer to use the get_gradient() function
- * instead, which does all the transformation
- * internally.
+ * @name 2: Reading from and writing to vectors
*/
- const vector_t * begin_gradients () const;
-
- /**
- * Returns a read and write pointer to the
- * first field of function gradients on
- * quadrature points. First comes the
- * x-component of the gradient for the first
- * component on all quadrature points, then
- * the y-component, and so on. Next comes the
- * x-component of the second component, and so
- * on. This is related to the internal data
- * structures used in this class. The raw data
- * after a call to @p evaluate only
- * contains unit cell operations, so possible
- * transformations, quadrature weights
- * etc. must be applied manually. In general,
- * it is safer to use the get_gradient()
- * function instead, which does all the
- * transformation internally.
- */
- vector_t * begin_gradients ();
-
- /**
- * Returns a read-only pointer to the first
- * field of function hessians on quadrature
- * points. First comes the xx-component of the
- * hessian for the first component on all
- * quadrature points, then the yy-component,
- * zz-component in (3D), then the
- * xy-component, and so on. Next comes the
- * xx-component of the second component, and
- * so on. This is related to the internal data
- * structures used in this class. The raw data
- * after a call to @p evaluate only
- * contains unit cell operations, so possible
- * transformations, quadrature weights
- * etc. must be applied manually. In general,
- * it is safer to use the get_laplacian() or
- * get_hessian() functions instead, which does
- * all the transformation internally.
- */
- const vector_t * begin_hessians () const;
-
- /**
- * Returns a read and write pointer to the
- * first field of function hessians on
- * quadrature points. First comes the
- * xx-component of the hessian for the first
- * component on all quadrature points, then
- * the yy-component, zz-component in (3D),
- * then the xy-component, and so on. Next
- * comes the xx-component of the second
- * component, and so on. This is related to
- * the internal data structures used in this
- * class. The raw data after a call to @p
- * evaluate only contains unit cell
- * operations, so possible transformations,
- * quadrature weights etc. must be applied
- * manually. In general, it is safer to use
- * the get_laplacian() or get_hessian()
- * functions instead, which does all the
- * transformation internally.
- */
- vector_t * begin_hessians ();
-
+ //@{
/**
* For the vector @p src, read out the values
* on the degrees of freedom of the current
template<typename VectorType>
void set_dof_values (VectorType * dst_data[]) const;
+ //@}
+
+ /**
+ * @name 3: Data access
+ */
+ //@{
/**
* Returns the value stored for the local
* degree of freedom with index @p dof. If the
* corresponds to the value of the integrated
* function with the test function of the
* given index.
+ *
+ * Note that the derived class
+ * FEEvaluationAccess overloads this operation
+ * with specializations for the scalar case
+ * (n_components == 1) and for the
+ * vector-valued case (n_components == dim).
*/
- Tensor<1,n_components,vector_t>
- get_dof_value (unsigned int dof) const;
+ value_type get_dof_value (const unsigned int dof) const;
/**
* Write a value to the field containing the
* degrees of freedom with component @p
- * dof. Access to the same field as through @p
- * get_dof_value.
+ * dof. Writes to the same field as is
+ * accessed through @p
+ * get_dof_value. Therefore, the original data
+ * that was read from a vector is overwritten
+ * as soon as a value is submitted.
+ *
+ * Note that the derived class
+ * FEEvaluationAccess overloads this operation
+ * with specializations for the scalar case
+ * (n_components == 1) and for the
+ * vector-valued case (n_components == dim).
*/
- void submit_dof_value (Tensor<1,n_components,vector_t> val_in,
- unsigned int dof);
+ void submit_dof_value (const value_type val_in,
+ const unsigned int dof);
/**
* Returns the value of a finite
* when vectorization is enabled,
* values from several cells are
* grouped together.
+ *
+ * Note that the derived class
+ * FEEvaluationAccess overloads this operation
+ * with specializations for the scalar case
+ * (n_components == 1) and for the
+ * vector-valued case (n_components == dim).
*/
- Tensor<1,n_components,vector_t>
- get_value (unsigned int q_point) const;
+ value_type get_value (const unsigned int q_point) const;
/**
* Write a value to the field containing the
* called, this specifies the value which is
* tested by all basis function on the current
* cell and integrated over.
+ *
+ * Note that the derived class
+ * FEEvaluationAccess overloads this operation
+ * with specializations for the scalar case
+ * (n_components == 1) and for the
+ * vector-valued case (n_components == dim).
*/
- void submit_value (Tensor<1,n_components,vector_t> val_in,
- unsigned int q_point);
+ void submit_value (const value_type val_in,
+ const unsigned int q_point);
/**
* Returns the gradient of a finite element
* evaluate(...,true,...), or the value
* that has been stored there with a call to
* @p submit_gradient.
+ *
+ * Note that the derived class
+ * FEEvaluationAccess overloads this operation
+ * with specializations for the scalar case
+ * (n_components == 1) and for the
+ * vector-valued case (n_components == dim).
*/
- Tensor<1,n_components,Tensor<1,dim,vector_t> >
- get_gradient (unsigned int q_point) const;
+ gradient_type get_gradient (const unsigned int q_point) const;
/**
* Write a gradient to the field containing
* this specifies the gradient which is tested
* by all basis function gradients on the
* current cell and integrated over.
+ *
+ * Note that the derived class
+ * FEEvaluationAccess overloads this operation
+ * with specializations for the scalar case
+ * (n_components == 1) and for the
+ * vector-valued case (n_components == dim).
*/
- void submit_gradient(Tensor<1,n_components,Tensor<1,dim,vector_t> >grad_in,
- unsigned int q_point);
+ void submit_gradient(const gradient_type grad_in,
+ const unsigned int q_point);
/**
* Returns the Hessian of a finite element
* diagonal or even the trace of the Hessian,
* the Laplacian, is needed, use the other
* functions below.
+ *
+ * Note that the derived class
+ * FEEvaluationAccess overloads this operation
+ * with specializations for the scalar case
+ * (n_components == 1) and for the
+ * vector-valued case (n_components == dim).
*/
- Tensor<1,n_components,Tensor<2,dim,vector_t> >
- get_hessian (unsigned int q_point) const;
+ Tensor<1,n_components,Tensor<2,dim,VectorizedArray<Number> > >
+ get_hessian (const unsigned int q_point) const;
/**
* Returns the diagonal of the Hessian of a
* finite element function at quadrature point
* number @p q_point after a call to @p
* evaluate(...,true).
+ *
+ * Note that the derived class
+ * FEEvaluationAccess overloads this operation
+ * with specializations for the scalar case
+ * (n_components == 1) and for the
+ * vector-valued case (n_components == dim).
*/
- Tensor<1,n_components,Tensor<1,dim,vector_t> >
- get_hessian_diagonal (unsigned int q_point) const;
+ gradient_type get_hessian_diagonal (const unsigned int q_point) const;
/**
- * Returns the Laplacian of a finite element
- * function at quadrature point number @p
- * q_point after a call to @p
- * evaluate(...,true).
+ * Returns the Laplacian (i.e., the trace of
+ * the Hessian) of a finite element function
+ * at quadrature point number @p q_point after
+ * a call to @p evaluate(...,true). Compared
+ * to the case when computing the full
+ * Hessian, some operations can be saved when
+ * only the Laplacian is requested.
+ *
+ * Note that the derived class
+ * FEEvaluationAccess overloads this operation
+ * with specializations for the scalar case
+ * (n_components == 1) and for the
+ * vector-valued case (n_components == dim).
*/
- Tensor<1,n_components,vector_t>
- get_laplacian (unsigned int q_point) const;
+ value_type get_laplacian (const unsigned int q_point) const;
/**
* Takes values on quadrature points,
* enabled, the integral values of several
* cells are represented together.
*/
- Tensor<1,n_components,vector_t>
- integrate_value ();
+ value_type integrate_value () const;
+
+ //@}
+
+protected:
/**
- * Stores a reference to the underlying data.
+ * Constructor. Made protected to prevent
+ * users from directly using this class. Takes
+ * all data stored in MatrixFree. If applied
+ * to problems with more than one finite
+ * element or more than one quadrature formula
+ * selected during construction of @p
+ * matrix_free, @p fe_no and @p quad_no allow
+ * to select the appropriate components.
*/
- const MatrixFree<dim,Number> &matrix_info;
+ FEEvaluationBase (const MatrixFree<dim,Number> &matrix_free,
+ const unsigned int fe_no = 0,
+ const unsigned int quad_no = 0);
/**
- * Stores a reference to the underlying DoF
- * indices and constraint description for the
- * component specified at construction. Also
- * contained in matrix_info, but it simplifies
- * code if we store a reference to it.
+ * Internal data fields that store the
+ * values. Since all array lengths are known
+ * at compile time and since they are rarely
+ * more than a few kilobytes, allocate them on
+ * the stack. This makes it possible to
+ * cheaply set up a FEEvaluation object and
+ * write thread-safe programs by letting each
+ * thread own a private object of this type.
+ *
+ * This field stores the values for local
+ * degrees of freedom (e.g. after reading out
+ * from a vector but before applying unit cell
+ * transformations or before distributing them
+ * into a result vector). The methods
+ * get_dof_value() and submit_dof_value()
+ * read from or write to this field.
*/
- const internal::MatrixFreeFunctions::DoFInfo &dof_info;
+ VectorizedArray<Number> values_dofs[n_components][dofs_per_cell>0?dofs_per_cell:1];
/**
- * Stores the constraints weights that
- * supplement DoFInfo. Also contained in
- * matrix_info, but it simplifies code if we
- * store a reference to it.
+ * This field stores the values of the finite
+ * element function on quadrature points after
+ * applying unit cell transformations or
+ * before integrating. The methods get_value()
+ * and submit_value() access this field.
*/
- const internal::MatrixFreeFunctions::CompressedMatrix<Number> &constraint_pool;
+ VectorizedArray<Number> values_quad[n_components][n_q_points>0?n_q_points:1];
/**
- * Stores a reference to the underlying
- * transformation data from unit to real cells
- * for the given quadrature formula specified
- * at construction. Also contained in
- * matrix_info, but it simplifies code if we
- * store a reference to it.
+ * This field stores the gradients of the
+ * finite element function on quadrature
+ * points after applying unit cell
+ * transformations or before integrating. The
+ * methods get_gradient() and
+ * submit_gradient() (as well as some
+ * specializations like
+ * get_symmetric_gradient() or
+ * get_divergence()) access this field.
*/
- const internal::MatrixFreeFunctions::MappingInfo<dim,Number> &mapping_info;
+ VectorizedArray<Number> gradients_quad[n_components][dim][n_q_points>0?n_q_points:1];
+
+ /**
+ * This field stores the Hessians of the
+ * finite element function on quadrature
+ * points after applying unit cell
+ * transformations. The methods get_hessian(),
+ * get_laplacian(), get_hessian_diagonal()
+ * access this field.
+ */
+ VectorizedArray<Number> hessians_quad[n_components][(dim*(dim+1))/2][n_q_points>0?n_q_points:1];
+
+ /**
+ * Stores the number of the quadrature formula
+ * of the present cell.
+ */
+ const unsigned int quad_no;
+
+ /**
+ * Stores the number of components in the
+ * finite element as detected in the
+ * MatrixFree storage class for comparison
+ * with the template argument.
+ */
+ const unsigned int n_fe_components;
/**
* Stores the active fe index for this class
*/
const unsigned int active_quad_index;
+ /**
+ * Stores a reference to the underlying data.
+ */
+ const MatrixFree<dim,Number> &matrix_info;
+
+ /**
+ * Stores a reference to the underlying DoF
+ * indices and constraint description for the
+ * component specified at construction. Also
+ * contained in matrix_info, but it simplifies
+ * code if we store a reference to it.
+ */
+ const internal::MatrixFreeFunctions::DoFInfo &dof_info;
+
+ /**
+ * Stores a reference to the underlying
+ * transformation data from unit to real cells
+ * for the given quadrature formula specified
+ * at construction. Also contained in
+ * matrix_info, but it simplifies code if we
+ * store a reference to it.
+ */
+ const internal::MatrixFreeFunctions::MappingInfo<dim,Number> &mapping_info;
+
/**
* Stores a reference to the unit cell data,
* i.e., values, gradients and Hessians in 1D
* matrix_info, but it simplifies code if we
* store a reference to it.
*/
- const internal::MatrixFreeFunctions::FEEvaluationData<Number> &data;
+ const internal::MatrixFreeFunctions::ShapeInfo<Number> &data;
-protected:
/**
- * Internal data fields that store the
- * values. Since all array lengths are known
- * at compile time and since they are rarely
- * more than a few kilobytes, allocate them on
- * the stack. This makes it possible to
- * cheaply set up a FEEvaluation object and
- * write thread-safe programs by letting each
- * thread own a private object of this type.
+ * After a call to reinit(), stores the number
+ * of the cell we are currently working with.
*/
- vector_t values_dofs[n_components][dofs_per_cell>0?dofs_per_cell:1];
- vector_t values_quad[n_components][n_q_points>0?n_q_points:1];
- vector_t gradients_quad[n_components][dim][n_q_points>0?n_q_points:1];
- vector_t hessians_quad[n_components][(dim*(dim+1))/2][n_q_points>0?n_q_points:1];
+ unsigned int cell;
/**
- * Stores the indices of the current cell.
+ * Stores the type of the cell we are
+ * currently working with after a call to
+ * reinit(). Valid values are @p cartesian, @p
+ * affine and @p general, which have different
+ * implications on how the Jacobian
+ * transformations are stored internally in
+ * MappingInfo.
+ */
+ internal::MatrixFreeFunctions::CellType cell_type;
+
+ /**
+ * The stride to access the correct data in
+ * MappingInfo.
*/
- const unsigned int quad_no;
- const unsigned int n_fe_components;
- unsigned int cell;
- unsigned int cell_type;
unsigned int cell_data_number;
+
+ /**
+ * Stores whether the present cell chunk used
+ * in vectorization is not completely filled
+ * up with physical cells. E.g. if
+ * vectorization dictates that four cells
+ * should be worked with but only three
+ * physical cells are left, this flag will be
+ * set to true, otherwise to false. Mainly
+ * used for internal checking when reading
+ * from vectors or writing to vectors.
+ */
bool at_irregular_cell;
+
+ /**
+ * If the present cell chunk for vectorization
+ * is not completely filled up with data, this
+ * field stores how many physical cells are
+ * underlying. Is between 1 and
+ * VectorizedArray<Number>::n_array_elements-1
+ * (inclusive).
+ */
unsigned int n_irreg_components_filled;
/**
* to a useful value if on a Cartesian cell,
* otherwise zero.
*/
- const Tensor<1,dim,vector_t> * cartesian;
+ const Tensor<1,dim,VectorizedArray<Number> > * cartesian_data;
/**
* A pointer to the Jacobian information of
* the present cell. Only set to a useful
* value if on a non-Cartesian cell.
*/
- const Tensor<2,dim,vector_t> * jacobian;
+ const Tensor<2,dim,VectorizedArray<Number> > * jacobian;
/**
* A pointer to the Jacobian determinant of
* the Jacobian determinant times the
* quadrature weight.
*/
- const vector_t * J_value;
+ const VectorizedArray<Number> * J_value;
/**
* A pointer to the quadrature weights of the
* underlying quadrature formula.
*/
- const vector_t * quadrature_weights;
+ const VectorizedArray<Number> * quadrature_weights;
/**
* A pointer to the quadrature points on the
* present cell.
*/
- const Point<dim,vector_t> * quadrature_points;
+ const Point<dim,VectorizedArray<Number> > * quadrature_points;
/**
* A pointer to the diagonal part of the
* cell. Only set to a useful value if on a
* general cell with non-constant Jacobian.
*/
- const Tensor<2,dim,vector_t> * jacobian_grad;
+ const Tensor<2,dim,VectorizedArray<Number> > * jacobian_grad;
/**
* A pointer to the upper diagonal part of the
* set to a useful value if on a general cell
* with non-constant Jacobian.
*/
- const Tensor<1,(dim>1?dim*(dim-1)/2:1),Tensor<1,dim,vector_t> > * jacobian_grad_upper;
+ const Tensor<1,(dim>1?dim*(dim-1)/2:1),Tensor<1,dim,VectorizedArray<Number> > > * jacobian_grad_upper;
/**
- * Debug information to track whether we
- * uninitialized fields are accessed.
+ * Debug information to track whether dof
+ * values have been initialized before
+ * accessed. Used to control exceptions when
+ * uninitialized data is used.
*/
bool dof_values_initialized;
+
+ /**
+ * Debug information to track whether values
+ * on quadrature points have been initialized
+ * before accessed. Used to control exceptions
+ * when uninitialized data is used.
+ */
bool values_quad_initialized;
+
+ /**
+ * Debug information to track whether
+ * gradients on quadrature points have been
+ * initialized before accessed. Used to
+ * control exceptions when uninitialized data
+ * is used.
+ */
bool gradients_quad_initialized;
+
+ /**
+ * Debug information to track whether
+ * Hessians on quadrature points have been
+ * initialized before accessed. Used to
+ * control exceptions when uninitialized data
+ * is used.
+ */
bool hessians_quad_initialized;
+
+ /**
+ * Debug information to track whether values
+ * on quadrature points have been submitted
+ * for integration before the integration is
+ * actually stared. Used to control exceptions
+ * when uninitialized data is used.
+ */
bool values_quad_submitted;
+
+ /**
+ * Debug information to track whether
+ * gradients on quadrature points have been
+ * submitted for integration before the
+ * integration is actually stared. Used to
+ * control exceptions when uninitialized data
+ * is used.
+ */
bool gradients_quad_submitted;
};
class FEEvaluationAccess :
public FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>
{
- public:
- typedef VectorizedArray<Number> vector_t;
- typedef Tensor<1,n_components,vector_t> value_type;
- typedef Tensor<1,n_components,Tensor<1,dim,vector_t> > gradient_type;
- static const std::size_t n_vectors = VectorizedArray<Number>::n_array_elements;
+public:
+ typedef Tensor<1,n_components,VectorizedArray<Number> > value_type;
+ typedef Tensor<1,n_components,Tensor<1,dim,VectorizedArray<Number> > > gradient_type;
+ static const unsigned int dimension = dim;
static const unsigned int dofs_per_cell = dofs_per_cell_;
static const unsigned int n_q_points = n_q_points_;
typedef FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,
Number> BaseClass;
+protected:
/**
- * Constructor. Takes all data stored in
- * MatrixFree. If applied to problems with
- * more than one finite element or more than
- * one quadrature formula selected during
- * construction of @p matrix_free, @p
- * fe_no and @p quad_no allow to select the
- * appropriate components.
+ * Constructor. Made protected to prevent
+ * initialization in user code. Takes all data
+ * stored in MatrixFree. If applied to
+ * problems with more than one finite element
+ * or more than one quadrature formula
+ * selected during construction of @p
+ * matrix_free, @p fe_no and @p quad_no allow
+ * to select the appropriate components.
*/
FEEvaluationAccess (const MatrixFree<dim,Number> &matrix_free,
- const unsigned int fe_no = 0,
- const unsigned int quad_no = 0);
+ const unsigned int fe_no = 0,
+ const unsigned int quad_no = 0);
};
public FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,1,Number>
{
public:
- typedef Number number_type;
- typedef VectorizedArray<Number> vector_t;
- typedef VectorizedArray<Number> value_type;
- typedef Tensor<1,dim,vector_t> gradient_type;
- static const unsigned int dimension = dim;
- static const std::size_t n_vectors = VectorizedArray<Number>::n_array_elements;
- static const unsigned int dofs_per_cell = dofs_per_cell_;
- static const unsigned int n_q_points = n_q_points_;
+ typedef VectorizedArray<Number> value_type;
+ typedef Tensor<1,dim,VectorizedArray<Number> > gradient_type;
+ static const unsigned int dimension = dim;
+ static const unsigned int dofs_per_cell = dofs_per_cell_;
+ static const unsigned int n_q_points = n_q_points_;
typedef FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,1,Number> BaseClass;
- /**
- * Constructor. Takes all data stored in
- * MatrixFree. If applied to problems with
- * more than one finite element or more than
- * one quadrature formula selected during
- * construction of @p matrix_free, @p
- * fe_no and @p quad_no allow to select the
- * appropriate components.
- */
- FEEvaluationAccess (const MatrixFree<dim,Number> &matrix_free,
- const unsigned int fe_no = 0,
- const unsigned int quad_no = 0);
-
/**
* Returns the value stored for the local
* degree of freedom with index @p dof. If the
* function with the test function of the
* given index.
*/
- vector_t
- get_dof_value (unsigned int dof) const;
+ value_type get_dof_value (const unsigned int dof) const;
/**
* Write a value to the field containing the
* dof. Access to the same field as through @p
* get_dof_value.
*/
- void submit_dof_value (vector_t val_in,
- unsigned int dof);
+ void submit_dof_value (const value_type val_in,
+ const unsigned int dof);
/**
* Returns the value of a finite element
* vectorization is enabled, values from
* several cells are grouped together.
*/
- vector_t
- get_value (unsigned int q_point) const;
+ value_type get_value (const unsigned int q_point) const;
/**
* Write a value to the field
* by all basis function on the
* current cell and integrated over.
*/
- void submit_value (vector_t val_in,
- unsigned int q_point);
+ void submit_value (const value_type val_in,
+ const unsigned int q_point);
/**
* Returns the gradient of a finite
* there with a call to @p
* submit_gradient.
*/
- gradient_type
- get_gradient (unsigned int q_point) const;
+ gradient_type get_gradient (const unsigned int q_point) const;
/**
* Write a gradient to the field
* gradients on the current cell and
* integrated over.
*/
- void submit_gradient(gradient_type grad_in,
- unsigned int q_point);
+ void submit_gradient(const gradient_type grad_in,
+ const unsigned int q_point);
/**
* Returns the Hessian of a finite
* Laplacian, are needed, use the
* respective functions below.
*/
- Tensor<2,dim,vector_t>
+ Tensor<2,dim,VectorizedArray<Number> >
get_hessian (unsigned int q_point) const;
/**
* after a call to @p
* evaluate(...,true).
*/
- gradient_type
- get_hessian_diagonal (unsigned int q_point) const;
+ gradient_type get_hessian_diagonal (const unsigned int q_point) const;
/**
* Returns the Laplacian of a finite
* point number @p q_point after a
* call to @p evaluate(...,true).
*/
- value_type
- get_laplacian (unsigned int q_point) const;
+ value_type get_laplacian (const unsigned int q_point) const;
/**
* Takes values on quadrature points,
* enabled, the integral values of several
* cells are represented together.
*/
- value_type
- integrate_value ();
+ value_type integrate_value () const;
+
+protected:
+ /**
+ * Constructor. Made protected to avoid
+ * initialization in user code. Takes all data
+ * stored in MatrixFree. If applied to
+ * problems with more than one finite element
+ * or more than one quadrature formula
+ * selected during construction of @p
+ * matrix_free, @p fe_no and @p quad_no allow
+ * to select the appropriate components.
+ */
+ FEEvaluationAccess (const MatrixFree<dim,Number> &matrix_free,
+ const unsigned int fe_no = 0,
+ const unsigned int quad_no = 0);
};
public FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,dim,Number>
{
public:
- typedef VectorizedArray<Number> vector_t;
- typedef Tensor<1,dim,vector_t> value_type;
- typedef Tensor<2,dim,vector_t> gradient_type;
- typedef SymmetricTensor<2,dim,vector_t> sym_gradient_type;
- typedef Tensor<1,dim==2?1:dim,vector_t> curl_type;
-
- static const std::size_t n_vectors = VectorizedArray<Number>::n_array_elements;
+ typedef Tensor<1,dim,VectorizedArray<Number> > value_type;
+ typedef Tensor<2,dim,VectorizedArray<Number> > gradient_type;
+ static const unsigned int dimension = dim;
static const unsigned int dofs_per_cell = dofs_per_cell_;
static const unsigned int n_q_points = n_q_points_;
typedef FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,dim,Number> BaseClass;
- /**
- * Constructor. Takes all data stored in
- * MatrixFree. If applied to problems with
- * more than one finite element or more than
- * one quadrature formula selected during
- * construction of @p matrix_free, @p
- * fe_no and @p quad_no allow to select the
- * appropriate components.
- */
- FEEvaluationAccess (const MatrixFree<dim,Number> &matrix_free,
- const unsigned int fe_no = 0,
- const unsigned int quad_no = 0);
-
/**
* Returns the gradient of a finite element
* function at quadrature point number @p
* q_point after a call to @p
* evaluate(...,true,...).
*/
- gradient_type
- get_gradient (unsigned int q_point) const;
+ gradient_type get_gradient (const unsigned int q_point) const;
/**
* Returns the divergence of a vector-valued
* @p q_point after a call to @p
* evaluate(...,true,...).
*/
- vector_t
- get_divergence (unsigned int q_point) const;
+ VectorizedArray<Number> get_divergence (const unsigned int q_point) const;
/**
* Returns the symmetric gradient of a
* corresponds to <tt>0.5
* (grad+grad<sup>T</sup>)</tt>.
*/
- sym_gradient_type
- get_symmetric_gradient (unsigned int q_point) const;
+ SymmetricTensor<2,dim,VectorizedArray<Number> >
+ get_symmetric_gradient (const unsigned int q_point) const;
/**
* Returns the curl of the vector field,
* $nabla \times v$ after a call to @p
* evaluate(...,true,...).
*/
- curl_type
- get_curl (unsigned int q_point) const;
+ Tensor<1,dim==2?1:dim,VectorizedArray<Number> >
+ get_curl (const unsigned int q_point) const;
/**
* Returns the Hessian of a finite
* needed, use the respective
* functions.
*/
- Tensor<3,dim,vector_t>
- get_hessian (unsigned int q_point) const;
+ Tensor<3,dim,VectorizedArray<Number> >
+ get_hessian (const unsigned int q_point) const;
/**
* Returns the diagonal of the Hessian
* after a call to @p
* evaluate(...,true).
*/
- gradient_type
- get_hessian_diagonal (unsigned int q_point) const;
+ gradient_type get_hessian_diagonal (const unsigned int q_point) const;
/**
* Write a gradient to the field containing
* by all basis function gradients on the
* current cell and integrated over.
*/
- void submit_gradient(gradient_type grad_in,
- unsigned int q_point);
+ void submit_gradient(const gradient_type grad_in,
+ const unsigned int q_point);
/**
* Write a gradient to the field containing
* dimension-independent programming, this
* function can be used instead.
*/
- void submit_gradient(Tensor<1,dim,Tensor<1,dim,vector_t> > grad_in,
- unsigned int q_point);
+ void submit_gradient(const Tensor<1,dim,Tensor<1,dim,VectorizedArray<Number> > > grad_in,
+ const unsigned int q_point);
/**
* Write a gradient to the field containing
* by all basis function gradients on the
* current cell and integrated over.
*/
- void submit_symmetric_gradient(sym_gradient_type grad_in,
- unsigned int q_point);
+ void submit_symmetric_gradient(const SymmetricTensor<2,dim,VectorizedArray<Number> > grad_in,
+ const unsigned int q_point);
/**
* Write the components of a curl containing
* q_point. Access to the same data field as
* through @p get_gradient.
*/
- void submit_curl (curl_type curl_in,
- unsigned int q_point);
+ void submit_curl (const Tensor<1,dim==2?1:dim,VectorizedArray<Number> > curl_in,
+ const unsigned int q_point);
+
+protected:
+ /**
+ * Constructor. Made protected to avoid
+ * initialization in user code. Takes all data
+ * stored in MatrixFree. If applied to
+ * problems with more than one finite element
+ * or more than one quadrature formula
+ * selected during construction of @p
+ * matrix_free, @p fe_no and @p quad_no allow
+ * to select the appropriate components.
+ */
+ FEEvaluationAccess (const MatrixFree<dim,Number> &matrix_free,
+ const unsigned int fe_no = 0,
+ const unsigned int quad_no = 0);
};
*
* @param dim Dimension in which this class is to be used
*
- * @param n_dofs_1d Number of degrees of freedom of the FE in 1D, usually
- * fe_degree+1, for elements based on a tensor product
+ * @param fe_degree Degree of the tensor product finite element with
+ * fe_degree+1 degrees of freedom per coordinate direction
*
* @param n_q_points_1d Number of points in the quadrature formula in 1D,
- * usually chosen as fe_degree+1
+ * usually chosen as fe_degree+1
*
* @param n_components Number of vector components when solving a system of
* PDEs. If the same operation is applied to several
*
* @author Katharina Kormann and Martin Kronbichler, 2010, 2011
*/
-template <int dim, int n_dofs_1d, int n_q_points_1d=n_dofs_1d,
+template <int dim, int fe_degree, int n_q_points_1d=fe_degree+1,
int n_components=1, typename Number=double >
class FEEvaluationGeneral :
public FEEvaluationAccess<dim,
- (n_dofs_1d*(dim>1?n_dofs_1d:1)*(dim>2?n_dofs_1d:1)),
- (n_q_points_1d*(dim>1?n_q_points_1d:1)*(dim>2?n_q_points_1d:1)),
+ Utilities::fixed_int_power<fe_degree+1,dim>::value,
+ Utilities::fixed_int_power<n_q_points_1d,dim>::value,
n_components,Number>
{
public:
- typedef VectorizedArray<Number> vector_t;
- static const std::size_t n_vectors = VectorizedArray<Number>::n_array_elements;
- typedef FEEvaluationAccess<dim,(n_dofs_1d*(dim>1?n_dofs_1d:1)*
- (dim>2?n_dofs_1d:1)),
- (n_q_points_1d*(dim>1?n_q_points_1d:1)*(dim>2?n_q_points_1d:1)),
- n_components, Number> BaseClass;
+ typedef FEEvaluationAccess<dim,
+ Utilities::fixed_int_power<fe_degree+1,dim>::value,
+ Utilities::fixed_int_power<n_q_points_1d,dim>::value,
+ n_components, Number> BaseClass;
+ typedef typename BaseClass::value_type value_type;
+ typedef typename BaseClass::gradient_type gradient_type;
static const unsigned int dofs_per_cell = BaseClass::dofs_per_cell;
static const unsigned int n_q_points = BaseClass::n_q_points;
* appropriate components.
*/
FEEvaluationGeneral (const MatrixFree<dim,Number> &matrix_free,
- const unsigned int fe_no = 0,
- const unsigned int quad_no = 0);
+ const unsigned int fe_no = 0,
+ const unsigned int quad_no = 0);
/**
* Evaluates the function values, the
* @p get_gradient() or @p get_laplacian
* return useful information.
*/
- void evaluate (bool evaluate_val, bool evaluate_grad,
+ void evaluate (bool evaluate_val, bool evaluate_grad,
bool evaluate_hess=false);
/**
* Returns the q-th quadrature point stored in
* MappingInfo.
*/
- Point<dim,vector_t> quadrature_point (const unsigned int q_point) const;
+ Point<dim,VectorizedArray<Number> >
+ quadrature_point (const unsigned int q_point) const;
protected:
* some previous results or not.
*/
template <int direction, bool dof_to_quad, bool add>
- void apply_tensor_prod (const vector_t * shape_data,
- const vector_t in [],
- vector_t out []);
+ void apply_tensor_prod (const VectorizedArray<Number> * shape_data,
+ const VectorizedArray<Number> in [],
+ VectorizedArray<Number> out []);
};
*
* This class is a specialization of FEEvaluationGeneral designed for standard
* FE_Q or FE_DGQ elements and quadrature points symmetric around 0.5 (like
- * Gauss quadrature), and hence the most common situation.
+ * Gauss quadrature), and hence the most common situation. Note that many of
+ * the operations available through this class are inherited from the base
+ * class FEEvaluationBase, in particular reading from and writing to
+ * vectors. Also, the class inherits from FEEvaluationAccess that implements
+ * access to values, gradients and Hessians of the finite element function on
+ * quadrature points.
+ *
+ * This class assumes that shape functions of the FiniteElement under
+ * consideration do <em>not</em> depend on the actual shape of the cells in
+ * real space. Currently, other finite elements cannot be treated with the
+ * matrix-free concept.
*
* This class has five template arguments:
*
* @param dim Dimension in which this class is to be used
*
- * @param n_dofs_1d Number of degrees of freedom of the FE in 1D, usually
- * fe_degree+1, for elements based on a tensor product
+ * @param fe_degree Degree of the tensor product finite element with
+ * fe_degree+1 degrees of freedom per coordinate direction
*
* @param n_q_points_1d Number of points in the quadrature formula in 1D,
* usually chosen as fe_degree+1
*
* @author Katharina Kormann and Martin Kronbichler, 2010, 2011
*/
-template <int dim, int n_dofs_1d, int n_q_points_1d=n_dofs_1d,
+template <int dim, int fe_degree, int n_q_points_1d=fe_degree+1,
int n_components=1, typename Number=double >
class FEEvaluation :
- public FEEvaluationGeneral<dim,n_dofs_1d,n_q_points_1d,n_components,Number>
+ public FEEvaluationGeneral<dim,fe_degree,n_q_points_1d,n_components,Number>
{
public:
- typedef VectorizedArray<Number> vector_t;
- static const std::size_t n_vectors = VectorizedArray<Number>::n_array_elements;
- typedef FEEvaluationGeneral<dim,n_dofs_1d,n_q_points_1d,n_components,Number> BaseClass;
+ typedef FEEvaluationGeneral<dim,fe_degree,n_q_points_1d,n_components,Number> BaseClass;
+ typedef typename BaseClass::value_type value_type;
+ typedef typename BaseClass::gradient_type gradient_type;
static const unsigned int dofs_per_cell = BaseClass::dofs_per_cell;
static const unsigned int n_q_points = BaseClass::n_q_points;
* appropriate components.
*/
FEEvaluation (const MatrixFree<dim,Number> &matrix_free,
- const unsigned int fe_no = 0,
- const unsigned int quad_no = 0);
+ const unsigned int fe_no = 0,
+ const unsigned int quad_no = 0);
/**
* Evaluates the function values, the
* (unless these values have been set
* manually).
*/
- void evaluate (bool evaluate_val, bool evaluate_grad,
+ void evaluate (bool evaluate_val, bool evaluate_grad,
bool evaluate_hess=false);
/**
* not.
*/
template <int direction, bool dof_to_quad, bool add>
- void apply_values (const vector_t in [], vector_t out []);
+ void apply_values (const VectorizedArray<Number> in [],
+ VectorizedArray<Number> out []);
/**
* Internal function that applies the gradient
* not.
*/
template <int direction, bool dof_to_quad, bool add>
- void apply_gradients (const vector_t in [], vector_t out []);
+ void apply_gradients (const VectorizedArray<Number> in [],
+ VectorizedArray<Number> out []);
/**
* Internal function that applies the second
* content in the data fields or not.
*/
template <int direction, bool dof_to_quad, bool add>
- void apply_hessians (const vector_t in [], vector_t out []);
+ void apply_hessians (const VectorizedArray<Number> in [],
+ VectorizedArray<Number> out []);
};
* directions other than the gradient direction are again identity
* operations).
*
- * This class has five template arguments:
+ * This class has four template arguments:
*
* @param dim Dimension in which this class is to be used
*
- * @param n_dofs_1d Number of degrees of freedom of the FE in 1D, usually
- * fe_degree+1, for elements based on a tensor product
- *
- * @param n_q_points_1d Number of points in the quadrature formula in 1D,
- * usually chosen as fe_degree+1
+ * @param fe_degree Degree of the tensor product finite element with
+ * fe_degree+1 degrees of freedom per coordinate
+ * direction. The quadrature formula is tied to the choice of
+ * the element by setting n_q_points_1d = fe_degree+1, which
+ * gives a diagonal mass matrix
*
* @param n_components Number of vector components when solving a system of
* PDEs. If the same operation is applied to several
*
* @author Katharina Kormann and Martin Kronbichler, 2010, 2011
*/
-template <int dim, int n_points_1d, int n_components=1, typename Number=double >
+template <int dim, int fe_degree, int n_components=1, typename Number=double >
class FEEvaluationGL :
- public FEEvaluation<dim,n_points_1d,n_points_1d,n_components,Number>
+ public FEEvaluation<dim,fe_degree,fe_degree+1,n_components,Number>
{
public:
- typedef VectorizedArray<Number> vector_t;
- static const std::size_t n_vectors = VectorizedArray<Number>::n_array_elements;
- typedef FEEvaluation<dim,n_points_1d,n_points_1d,n_components,Number> BaseClass;
+ typedef FEEvaluation<dim,fe_degree,fe_degree+1,n_components,Number> BaseClass;
+ typedef typename BaseClass::value_type value_type;
+ typedef typename BaseClass::gradient_type gradient_type;
static const unsigned int dofs_per_cell = BaseClass::dofs_per_cell;
static const unsigned int n_q_points = BaseClass::n_q_points;
* appropriate components.
*/
FEEvaluationGL (const MatrixFree<dim,Number> &matrix_free,
- const unsigned int fe_no = 0,
- const unsigned int quad_no = 0);
+ const unsigned int fe_no = 0,
+ const unsigned int quad_no = 0);
/**
* Evaluates the function values, the
* (unless these values have been set
* manually).
*/
- void evaluate (bool evaluate_val, bool evaluate_grad,
+ void evaluate (bool evaluate_val, bool evaluate_grad,
bool evaluate_lapl=false);
/**
* some previous results or not.
*/
template <int direction, bool dof_to_quad, bool add>
- void apply_gradients (const vector_t in [], vector_t out []);
+ void apply_gradients (const VectorizedArray<Number> in [],
+ VectorizedArray<Number> out []);
};
const unsigned int fe_no_in,
const unsigned int quad_no_in)
:
+ quad_no (quad_no_in),
+ n_fe_components (data_in.get_dof_info(fe_no_in).n_components),
+ active_fe_index (data_in.get_dof_info(fe_no_in).fe_index_from_dofs_per_cell
+ (dofs_per_cell_ * n_fe_components)),
+ active_quad_index (data_in.get_mapping_info().
+ mapping_data_gen[quad_no_in].
+ quad_index_from_n_q_points(n_q_points_)),
matrix_info (data_in),
dof_info (data_in.get_dof_info(fe_no_in)),
- constraint_pool (data_in.get_constraint_pool()),
mapping_info (data_in.get_mapping_info()),
- active_fe_index (dof_info.fe_index_from_dofs_per_cell
- (dofs_per_cell_ * dof_info.n_components)),
- active_quad_index (mapping_info.
- mapping_data_gen[quad_no_in].
- quad_index_from_n_q_points(n_q_points_)),
- data (data_in.get_fe_evaluation
+ data (data_in.get_shape_info
(fe_no_in, quad_no_in, active_fe_index,
active_quad_index)),
- quad_no (quad_no_in),
- n_fe_components (dof_info.n_components),
cell (numbers::invalid_unsigned_int),
- cell_type (numbers::invalid_unsigned_int),
- cartesian (0),
+ cell_type (internal::MatrixFreeFunctions::undefined),
+ cell_data_number (0),
+ at_irregular_cell (false),
+ n_irreg_components_filled (0),
+ cartesian_data (0),
jacobian (0),
J_value (0),
quadrature_weights (mapping_info.mapping_data_gen[quad_no].
ExcNotInitialized());
Assert (matrix_info.mapping_initialized() == true,
ExcNotInitialized());
- AssertDimension (matrix_info.get_size_info().n_vectors, n_vectors);
+ AssertDimension (matrix_info.get_size_info().vectorization_length,
+ VectorizedArray<Number>::n_array_elements);
Assert (n_fe_components == 1 ||
n_components == n_fe_components,
ExcMessage ("The underlying FE is vector-valued. In this case, the "
&mapping_info.mapping_data_gen[quad_no].quadrature_points[index];
}
- if (cell_type == 0)
+ if (cell_type == internal::MatrixFreeFunctions::cartesian)
{
- cartesian = &mapping_info.cartesian[cell_data_number].first;
- J_value = &mapping_info.cartesian[cell_data_number].second;
+ cartesian_data = &mapping_info.cartesian_data[cell_data_number].first;
+ J_value = &mapping_info.cartesian_data[cell_data_number].second;
}
- else if (cell_type == 1)
+ else if (cell_type == internal::MatrixFreeFunctions::affine)
{
- jacobian = &mapping_info.linear[cell_data_number].first;
- J_value = &mapping_info.linear[cell_data_number].second;
+ jacobian = &mapping_info.affine_data[cell_data_number].first;
+ J_value = &mapping_info.affine_data[cell_data_number].second;
}
else
{
template <int dim, int dofs_per_cell_, int n_q_points_,
int n_components, typename Number>
inline
-unsigned int
+internal::MatrixFreeFunctions::CellType
FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
get_cell_type () const
{
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components, typename Number>
-inline
-const VectorizedArray<Number> *
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
-begin_values () const
-{
- Assert (values_quad_initialized || values_quad_submitted,
- ExcNotInitialized());
- return &values_quad[0][0];
-}
-
-
-
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components, typename Number>
-inline
-VectorizedArray<Number> *
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
-begin_values ()
-{
-#ifdef DEBUG
- values_quad_submitted = true;
-#endif
- return &values_quad[0][0];
-}
-
-
-
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components, typename Number>
-inline
-const VectorizedArray<Number> *
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
-begin_gradients () const
-{
- Assert (gradients_quad_initialized || gradients_quad_submitted,
- ExcNotInitialized());
- return &gradients_quad[0][0][0];
-}
-
-
-
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components, typename Number>
-inline
-VectorizedArray<Number> *
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
-begin_gradients ()
-{
-#ifdef DEBUG
- gradients_quad_submitted = true;
-#endif
- return &gradients_quad[0][0][0];
-}
-
-
-
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components, typename Number>
-inline
-const VectorizedArray<Number> *
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
-begin_hessians () const
-{
- Assert (hessians_quad_initialized, ExcNotInitialized());
- return &hessians_quad[0][0][0];
-}
-
-
-
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components, typename Number>
-inline
-VectorizedArray<Number> *
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
-begin_hessians ()
-{
- return &hessians_quad[0][0][0];
-}
-
-
-
namespace internal
{
// write access to generic vectors that have
// a different vector each)
if (n_fe_components == 1)
{
+ const unsigned int n_local_dofs =
+ VectorizedArray<Number>::n_array_elements * dofs_per_cell;
for (unsigned int comp=0; comp<n_components; ++comp)
internal::check_vector_compatibility (*src[comp], dof_info);
Number * local_src_number [n_components];
for (unsigned int comp=0; comp<n_components; ++comp)
value[comp] = 0;
const Number * data_val =
- constraint_pool.begin(indicators->second);
- const unsigned int row_length =
- constraint_pool.row_length(indicators->second);
- for (unsigned int k=0; k<row_length; ++k)
+ matrix_info.constraint_pool_begin(indicators->second);
+ const Number * end_pool =
+ matrix_info.constraint_pool_end(indicators->second);
+ for ( ; data_val != end_pool; ++data_val, ++dof_indices)
for (unsigned int comp=0; comp<n_components; ++comp)
value[comp] +=
- (internal::vector_access (*src[comp], dof_indices[k]) *
- data_val[k]);
- dof_indices += row_length;
+ (internal::vector_access (*src[comp], *dof_indices) *
+ (*data_val));
for (unsigned int comp=0; comp<n_components; ++comp)
local_src_number[comp][ind_local] = value[comp];
// get the dof values past the last
// constraint
- for(; ind_local<n_vectors*dofs_per_cell; ++dof_indices, ++ind_local)
+ for(; ind_local < n_local_dofs; ++dof_indices, ++ind_local)
{
for (unsigned int comp=0; comp<n_components; ++comp)
local_src_number[comp][ind_local] =
// no constraint at all: loop bounds are
// known, compiler can unroll without checks
AssertDimension (dof_info.end_indices(cell)-dof_indices,
- n_vectors*dofs_per_cell);
- for (unsigned int j=0; j<dofs_per_cell*n_vectors; ++j)
+ static_cast<int>(n_local_dofs));
+ for (unsigned int j=0; j<n_local_dofs; ++j)
for (unsigned int comp=0; comp<n_components; ++comp)
local_src_number[comp][j] =
internal::vector_access (*src[comp], dof_indices[j]);
// here we jump over all the components that
// are artificial
++ind_local;
- while (ind_local % n_vectors >= n_irreg_components_filled)
+ while (ind_local % VectorizedArray<Number>::n_array_elements
+ >= n_irreg_components_filled)
{
for (unsigned int comp=0; comp<n_components; ++comp)
local_src_number[comp][ind_local] = 0.;
for (unsigned int comp=0; comp<n_components; ++comp)
value[comp] = 0.;
const Number * data_val =
- constraint_pool.begin(indicators->second);
- const unsigned int row_length =
- constraint_pool.row_length(indicators->second);
- for (unsigned int k=0; k<row_length; ++k)
+ matrix_info.constraint_pool_begin(indicators->second);
+ const Number * end_pool =
+ matrix_info.constraint_pool_end(indicators->second);
+ for ( ; data_val != end_pool; ++data_val, ++dof_indices)
for (unsigned int comp=0; comp<n_components; ++comp)
value[comp] +=
- internal::vector_access (*src[comp], dof_indices[k]) * data_val[k];
- dof_indices += row_length;
+ internal::vector_access (*src[comp], *dof_indices) * (*data_val);
for (unsigned int comp=0; comp<n_components; ++comp)
local_src_number[comp][ind_local] = value[comp];
ind_local++;
- while (ind_local % n_vectors >= n_irreg_components_filled)
+ while (ind_local % VectorizedArray<Number>::n_array_elements
+ >= n_irreg_components_filled)
{
for (unsigned int comp=0; comp<n_components; ++comp)
local_src_number[comp][ind_local] = 0.;
++ind_local;
}
}
- for(; ind_local<n_vectors*dofs_per_cell; ++dof_indices)
+ for(; ind_local<n_local_dofs; ++dof_indices)
{
Assert (dof_indices != dof_info.end_indices(cell),
ExcInternalError());
local_src_number[comp][ind_local] =
internal::vector_access (*src[comp], *dof_indices);
++ind_local;
- while (ind_local % n_vectors >= n_irreg_components_filled)
+ while (ind_local % VectorizedArray<Number>::n_array_elements
+ >= n_irreg_components_filled)
{
for (unsigned int comp=0; comp<n_components; ++comp)
local_src_number[comp][ind_local] = 0.;
{
internal::check_vector_compatibility (*src[0], dof_info);
Assert (n_fe_components == n_components, ExcNotImplemented());
- const unsigned int total_dofs_per_cell =
- dofs_per_cell * n_vectors * n_components;
+ const unsigned int n_local_dofs =
+ dofs_per_cell*VectorizedArray<Number>::n_array_elements * n_components;
Number * local_src_number = reinterpret_cast<Number*>(values_dofs[0]);
if (at_irregular_cell == false)
{
// according to constraints
Number value = 0;
const Number * data_val =
- constraint_pool.begin(indicators->second);
- const unsigned int row_length =
- constraint_pool.row_length(indicators->second);
- for (unsigned int k=0; k<row_length; ++k)
+ matrix_info.constraint_pool_begin(indicators->second);
+ const Number * end_pool =
+ matrix_info.constraint_pool_end(indicators->second);
+ for ( ; data_val != end_pool; ++data_val, ++dof_indices)
value +=
- (internal::vector_access (*src[0], dof_indices[k]) *
- data_val[k]);
- dof_indices += row_length;
+ (internal::vector_access (*src[0], *dof_indices) *
+ (*data_val));
local_src_number[ind_local] = value;
ind_local++;
// get the dof values past the last
// constraint
- for(; ind_local<total_dofs_per_cell; ++dof_indices, ++ind_local)
+ for(; ind_local<n_local_dofs; ++dof_indices, ++ind_local)
local_src_number[ind_local] =
internal::vector_access (*src[0], *dof_indices);
Assert (dof_indices == dof_info.end_indices(cell),
// no constraint at all: loop bounds are
// known, compiler can unroll without checks
AssertDimension (dof_info.end_indices(cell)-dof_indices,
- static_cast<int>(total_dofs_per_cell));
- for (unsigned int j=0; j<total_dofs_per_cell; ++j)
+ static_cast<int>(n_local_dofs));
+ for (unsigned int j=0; j<n_local_dofs; ++j)
local_src_number[j] =
internal::vector_access (*src[0], dof_indices[j]);
}
// here we jump over all the components that
// are artificial
++ind_local;
- while (ind_local % n_vectors >= n_irreg_components_filled)
+ while (ind_local % VectorizedArray<Number>::n_array_elements
+ >= n_irreg_components_filled)
{
local_src_number[ind_local] = 0.;
++ind_local;
// according to constraint
Number value = 0;
const Number * data_val =
- constraint_pool.begin(indicators->second);
- const unsigned int row_length =
- constraint_pool.row_length(indicators->second);
- for (unsigned int k=0; k<row_length; ++k)
+ matrix_info.constraint_pool_begin(indicators->second);
+ const Number * end_pool =
+ matrix_info.constraint_pool_end(indicators->second);
+ for ( ; data_val != end_pool; ++data_val, ++dof_indices)
value +=
- internal::vector_access (*src[0], dof_indices[k]) * data_val[k];
- dof_indices += row_length;
+ internal::vector_access (*src[0], *dof_indices) * (*data_val);
local_src_number[ind_local] = value;
ind_local++;
- while (ind_local % n_vectors >= n_irreg_components_filled)
+ while (ind_local % VectorizedArray<Number>::n_array_elements
+ >= n_irreg_components_filled)
{
local_src_number[ind_local] = 0.;
++ind_local;
}
}
- for(; ind_local<total_dofs_per_cell; ++dof_indices)
+ for(; ind_local<n_local_dofs; ++dof_indices)
{
Assert (dof_indices != dof_info.end_indices(cell),
ExcInternalError());
local_src_number[ind_local] =
internal::vector_access (*src[0], *dof_indices);
++ind_local;
- while (ind_local % n_vectors >= n_irreg_components_filled)
+ while (ind_local % VectorizedArray<Number>::n_array_elements
+ >= n_irreg_components_filled)
{
local_src_number[ind_local] = 0.;
++ind_local;
// a different vector each)
if (n_fe_components == 1)
{
+ const unsigned int n_local_dofs =
+ VectorizedArray<Number>::n_array_elements * dofs_per_cell;
for (unsigned int comp=0; comp<n_components; ++comp)
internal::check_vector_compatibility (*src[comp], dof_info);
Number * local_src_number [n_components];
// many cells to fill all vectors
if (at_irregular_cell == false)
{
- for (unsigned int j=0; j<dofs_per_cell*n_vectors; ++j)
+ for (unsigned int j=0; j<n_local_dofs; ++j)
for (unsigned int comp=0; comp<n_components; ++comp)
local_src_number[comp][j] =
internal::vector_access (*src[comp], dof_indices[j]);
else
{
Assert (n_irreg_components_filled > 0, ExcInternalError());
- for(unsigned int ind_local=0; ind_local<n_vectors*dofs_per_cell;
+ for(unsigned int ind_local=0; ind_local<n_local_dofs;
++dof_indices)
{
// non-constrained case: copy the data from
local_src_number[comp][ind_local] =
internal::vector_access (*src[comp], *dof_indices);
++ind_local;
- while (ind_local % n_vectors >= n_irreg_components_filled)
+ while (ind_local % VectorizedArray<Number>::n_array_elements >= n_irreg_components_filled)
{
for (unsigned int comp=0; comp<n_components; ++comp)
local_src_number[comp][ind_local] = 0.;
{
internal::check_vector_compatibility (*src[0], dof_info);
Assert (n_fe_components == n_components, ExcNotImplemented());
- const unsigned int total_dofs_per_cell =
- dofs_per_cell * n_vectors * n_components;
+ const unsigned int n_local_dofs =
+ dofs_per_cell * VectorizedArray<Number>::n_array_elements * n_components;
Number * local_src_number = reinterpret_cast<Number*>(values_dofs[0]);
if (at_irregular_cell == false)
{
- for (unsigned int j=0; j<total_dofs_per_cell; ++j)
+ for (unsigned int j=0; j<n_local_dofs; ++j)
local_src_number[j] =
internal::vector_access (*src[0], dof_indices[j]);
}
else
{
Assert (n_irreg_components_filled > 0, ExcInternalError());
- for(unsigned int ind_local=0; ind_local<total_dofs_per_cell; ++dof_indices)
+ for(unsigned int ind_local=0; ind_local<n_local_dofs; ++dof_indices)
{
// non-constrained case: copy the data from
// the global vector, src, to the local one,
local_src_number[ind_local] =
internal::vector_access (*src[0], *dof_indices);
++ind_local;
- while (ind_local % n_vectors >= n_irreg_components_filled)
+ while (ind_local % VectorizedArray<Number>::n_array_elements >= n_irreg_components_filled)
{
local_src_number[ind_local] = 0.;
++ind_local;
// a different vector each)
if (n_fe_components == 1)
{
+ const unsigned int n_local_dofs =
+ VectorizedArray<Number>::n_array_elements * dofs_per_cell;
for (unsigned int comp=0; comp<n_components; ++comp)
internal::check_vector_compatibility (*dst[comp], dof_info);
// a linear combination of the global value
// according to constraint
const Number * data_val =
- constraint_pool.begin(indicators->second);
- const unsigned int row_length =
- constraint_pool.row_length(indicators->second);
- for (unsigned int k=0; k<row_length; ++k)
+ matrix_info.constraint_pool_begin(indicators->second);
+ const Number * end_pool =
+ matrix_info.constraint_pool_end(indicators->second);
+ for ( ; data_val != end_pool; ++data_val, ++dof_indices)
for (unsigned int comp=0; comp<n_components; ++comp)
- internal::vector_access (*dst[comp], dof_indices[k])
- += local_dst_number[comp][ind_local] * data_val[k];
- dof_indices += row_length;
+ internal::vector_access (*dst[comp], *dof_indices)
+ += local_dst_number[comp][ind_local] * (*data_val);
++ind_local;
}
// distribute values after the last constraint
// (values not constrained)
- for(; ind_local<dofs_per_cell*n_vectors; ++dof_indices, ++ind_local)
+ for(; ind_local<n_local_dofs; ++dof_indices, ++ind_local)
for (unsigned int comp=0; comp<n_components; ++comp)
internal::vector_access (*dst[comp], *dof_indices)
+= local_dst_number[comp][ind_local];
else
{
AssertDimension (dof_info.end_indices(cell)-dof_indices,
- n_vectors * dofs_per_cell);
- for (unsigned int j=0; j<dofs_per_cell*n_vectors; ++j)
+ static_cast<int>(n_local_dofs));
+ for (unsigned int j=0; j<n_local_dofs; ++j)
for (unsigned int comp=0; comp<n_components; ++comp)
internal::vector_access (*dst[comp], dof_indices[j])
+= local_dst_number[comp][j];
internal::vector_access (*dst[comp], dof_indices[j])
+= local_dst_number[comp][ind_local];
++ind_local;
- if (ind_local % n_vectors == n_irreg_components_filled)
- ind_local += n_vectors-n_irreg_components_filled;
+ if (ind_local % VectorizedArray<Number>::n_array_elements == n_irreg_components_filled)
+ ind_local += VectorizedArray<Number>::n_array_elements-n_irreg_components_filled;
}
dof_indices += indicators->first;
// constrained case: distribute according to
// the constraint
const Number * data_val =
- constraint_pool.begin(indicators->second);
- const unsigned int row_length =
- constraint_pool.row_length(indicators->second);
- for (unsigned int k=0; k<row_length; ++k)
+ matrix_info.constraint_pool_begin(indicators->second);
+ const Number * end_pool =
+ matrix_info.constraint_pool_end(indicators->second);
+ for ( ; data_val != end_pool; ++data_val, ++dof_indices)
{
for (unsigned int comp=0; comp<n_components; ++comp)
- internal::vector_access (*dst[comp], dof_indices[k])
- += local_dst_number[comp][ind_local] * data_val[k];
+ internal::vector_access (*dst[comp], *dof_indices)
+ += local_dst_number[comp][ind_local] * (*data_val);
}
- dof_indices += row_length;
++ind_local;
- if (ind_local % n_vectors == n_irreg_components_filled)
- ind_local += n_vectors-n_irreg_components_filled;
+ if (ind_local % VectorizedArray<Number>::n_array_elements ==
+ n_irreg_components_filled)
+ ind_local += VectorizedArray<Number>::n_array_elements-
+ n_irreg_components_filled;
}
- for(; ind_local<dofs_per_cell*n_vectors; ++dof_indices)
+ for(; ind_local<n_local_dofs; ++dof_indices)
{
Assert (dof_indices != dof_info.end_indices(cell),
ExcInternalError());
internal::vector_access (*dst[comp], *dof_indices)
+= local_dst_number[comp][ind_local];
++ind_local;
- if (ind_local % n_vectors == n_irreg_components_filled)
- ind_local += n_vectors-n_irreg_components_filled;
+ if (ind_local % VectorizedArray<Number>::n_array_elements ==
+ n_irreg_components_filled)
+ ind_local += VectorizedArray<Number>::n_array_elements-n_irreg_components_filled;
}
}
else
{
internal::check_vector_compatibility (*dst[0], dof_info);
Assert (n_fe_components == n_components, ExcNotImplemented());
- const unsigned int total_dofs_per_cell =
- dofs_per_cell * n_vectors * n_components;
+ const unsigned int n_local_dofs =
+ dofs_per_cell * VectorizedArray<Number>::n_array_elements * n_components;
const Number * local_dst_number =
reinterpret_cast<const Number*>(values_dofs[0]);
if (at_irregular_cell == false)
// a linear combination of the global value
// according to constraint
const Number * data_val =
- constraint_pool.begin(indicators->second);
- const unsigned int row_length =
- constraint_pool.row_length(indicators->second);
- for (unsigned int k=0; k<row_length; ++k)
- internal::vector_access (*dst[0], dof_indices[k])
- += local_dst_number[ind_local] * data_val[k];
- dof_indices += row_length;
+ matrix_info.constraint_pool_begin(indicators->second);
+ const Number * end_pool =
+ matrix_info.constraint_pool_end(indicators->second);
+ for ( ; data_val != end_pool; ++data_val, ++dof_indices)
+ internal::vector_access (*dst[0], *dof_indices)
+ += local_dst_number[ind_local] * (*data_val);
++ind_local;
}
// distribute values after the last constraint
// (values not constrained)
- for(; ind_local<total_dofs_per_cell; ++dof_indices, ++ind_local)
+ for(; ind_local<n_local_dofs; ++dof_indices, ++ind_local)
internal::vector_access (*dst[0], *dof_indices)
+= local_dst_number[ind_local];
}
else
{
AssertDimension (dof_info.end_indices(cell)-dof_indices,
- static_cast<int>(total_dofs_per_cell));
- for (unsigned int j=0; j<total_dofs_per_cell; ++j)
+ static_cast<int>(n_local_dofs));
+ for (unsigned int j=0; j<n_local_dofs; ++j)
internal::vector_access (*dst[0], dof_indices[j])
+= local_dst_number[j];
}
internal::vector_access (*dst[0], dof_indices[j])
+= local_dst_number[ind_local];
++ind_local;
- if (ind_local % n_vectors == n_irreg_components_filled)
- ind_local += n_vectors-n_irreg_components_filled;
+ if (ind_local % VectorizedArray<Number>::n_array_elements == n_irreg_components_filled)
+ ind_local += VectorizedArray<Number>::n_array_elements-n_irreg_components_filled;
}
dof_indices += indicators->first;
// constrained case: distribute according to
// the constraint
const Number * data_val =
- constraint_pool.begin(indicators->second);
- const unsigned int row_length =
- constraint_pool.row_length(indicators->second);
- for (unsigned int k=0; k<row_length; ++k)
+ matrix_info.constraint_pool_begin(indicators->second);
+ const Number * end_pool =
+ matrix_info.constraint_pool_end(indicators->second);
+ for ( ; data_val != end_pool; ++data_val, ++dof_indices)
{
- internal::vector_access (*dst[0], dof_indices[k])
- += local_dst_number[ind_local] * data_val[k];
+ internal::vector_access (*dst[0], *dof_indices)
+ += local_dst_number[ind_local] * (*data_val);
}
- dof_indices += row_length;
++ind_local;
- if (ind_local % n_vectors == n_irreg_components_filled)
- ind_local += n_vectors-n_irreg_components_filled;
+ if (ind_local % VectorizedArray<Number>::n_array_elements == n_irreg_components_filled)
+ ind_local += VectorizedArray<Number>::n_array_elements-n_irreg_components_filled;
}
- for(; ind_local<total_dofs_per_cell; ++dof_indices)
+ for(; ind_local<n_local_dofs; ++dof_indices)
{
Assert (dof_indices != dof_info.end_indices(cell),
ExcInternalError());
internal::vector_access (*dst[0], *dof_indices)
+= local_dst_number[ind_local];
++ind_local;
- if (ind_local % n_vectors == n_irreg_components_filled)
- ind_local += n_vectors-n_irreg_components_filled;
+ if (ind_local % VectorizedArray<Number>::n_array_elements == n_irreg_components_filled)
+ ind_local += VectorizedArray<Number>::n_array_elements-n_irreg_components_filled;
}
Assert (dof_indices == dof_info.end_indices(cell),
ExcInternalError());
if (n_fe_components == 1)
{
+ const unsigned int n_local_dofs =
+ VectorizedArray<Number>::n_array_elements * dofs_per_cell;
for (unsigned int comp=0; comp<n_components; ++comp)
AssertDimension (dst[comp]->size(),
dof_info.vector_partitioner->size());
// jump over constraints
const unsigned int row_length =
- constraint_pool.row_length(indicators->second);
+ matrix_info.constraint_pool_end(indicators->second)-
+ matrix_info.constraint_pool_begin(indicators->second);
dof_indices += row_length;
++ind_local;
}
// distribute values after the last constraint
// (values not constrained)
- for(; ind_local<dofs_per_cell*n_vectors; ++dof_indices, ++ind_local)
+ for(; ind_local<n_local_dofs; ++dof_indices, ++ind_local)
for (unsigned int comp=0; comp<n_components; ++comp)
internal::vector_access (*dst[comp], *dof_indices)
= local_dst_number[comp][ind_local];
else
{
AssertDimension (dof_info.end_indices(cell)-dof_indices,
- n_vectors * dofs_per_cell);
- for (unsigned int j=0; j<dofs_per_cell*n_vectors; ++j)
+ n_local_dofs);
+ for (unsigned int j=0; j<n_local_dofs; ++j)
for (unsigned int comp=0; comp<n_components; ++comp)
internal::vector_access (*dst[comp], dof_indices[j])
= local_dst_number[comp][j];
internal::vector_access (*dst[comp], dof_indices[j])
= local_dst_number[comp][ind_local];
++ind_local;
- if (ind_local % n_vectors == n_irreg_components_filled)
- ind_local += n_vectors-n_irreg_components_filled;
+ if (ind_local % VectorizedArray<Number>::n_array_elements == n_irreg_components_filled)
+ ind_local += VectorizedArray<Number>::n_array_elements-n_irreg_components_filled;
}
dof_indices += indicators->first;
// jump over constraint
const unsigned int row_length =
- constraint_pool.row_length(indicators->second);
+ matrix_info.constraint_pool_end(indicators->second)-
+ matrix_info.constraint_pool_begin(indicators->second);
dof_indices += row_length;
++ind_local;
- if (ind_local % n_vectors == n_irreg_components_filled)
- ind_local += n_vectors-n_irreg_components_filled;
+ if (ind_local % VectorizedArray<Number>::n_array_elements ==
+ n_irreg_components_filled)
+ ind_local += VectorizedArray<Number>::n_array_elements -
+ n_irreg_components_filled;
}
- for(; ind_local<dofs_per_cell*n_vectors; ++dof_indices)
+ for(; ind_local<n_local_dofs; ++dof_indices)
{
Assert (dof_indices != dof_info.end_indices(cell),
ExcInternalError());
internal::vector_access (*dst[comp], *dof_indices)
= local_dst_number[comp][ind_local];
++ind_local;
- if (ind_local % n_vectors == n_irreg_components_filled)
- ind_local += n_vectors-n_irreg_components_filled;
+ if (ind_local % VectorizedArray<Number>::n_array_elements == n_irreg_components_filled)
+ ind_local += VectorizedArray<Number>::n_array_elements-n_irreg_components_filled;
}
}
else
AssertDimension (dst[0]->size(),
dof_info.vector_partitioner->size());
Assert (n_fe_components == n_components, ExcNotImplemented());
- const unsigned int total_dofs_per_cell =
- dofs_per_cell * n_vectors * n_components;
+ const unsigned int n_local_dofs =
+ dofs_per_cell * VectorizedArray<Number>::n_array_elements * n_components;
const Number * local_dst_number =
reinterpret_cast<const Number*>(values_dofs[0]);
// jump over constraints
const unsigned int row_length =
- constraint_pool.row_length(indicators->second);
+ matrix_info.constraint_pool_end(indicators->second) -
+ matrix_info.constraint_pool_begin(indicators->second);
dof_indices += row_length;
++ind_local;
}
// distribute values after the last constraint
// (values not constrained)
- for(; ind_local<total_dofs_per_cell; ++dof_indices, ++ind_local)
+ for(; ind_local<n_local_dofs; ++dof_indices, ++ind_local)
internal::vector_access (*dst[0], *dof_indices)
= local_dst_number[ind_local];
}
else
{
AssertDimension (dof_info.end_indices(cell)-dof_indices,
- total_dofs_per_cell);
- for (unsigned int j=0; j<total_dofs_per_cell; ++j)
+ n_local_dofs);
+ for (unsigned int j=0; j<n_local_dofs; ++j)
internal::vector_access (*dst[0], dof_indices[j])
= local_dst_number[j];
}
internal::vector_access (*dst[0], dof_indices[j])
= local_dst_number[ind_local];
++ind_local;
- if (ind_local % n_vectors == n_irreg_components_filled)
- ind_local += n_vectors-n_irreg_components_filled;
+ if (ind_local % VectorizedArray<Number>::n_array_elements == n_irreg_components_filled)
+ ind_local += VectorizedArray<Number>::n_array_elements-n_irreg_components_filled;
}
dof_indices += indicators->first;
// jump over constraint
const unsigned int row_length =
- constraint_pool.row_length(indicators->second);
+ matrix_info.constraint_pool_end(indicators->second)-
+ matrix_info.constraint_pool_begin(indicators->second);
dof_indices += row_length;
++ind_local;
- if (ind_local % n_vectors == n_irreg_components_filled)
- ind_local += n_vectors-n_irreg_components_filled;
+ if (ind_local % VectorizedArray<Number>::n_array_elements == n_irreg_components_filled)
+ ind_local += VectorizedArray<Number>::n_array_elements-n_irreg_components_filled;
}
- for(; ind_local<total_dofs_per_cell; ++dof_indices)
+ for(; ind_local<n_local_dofs; ++dof_indices)
{
Assert (dof_indices != dof_info.end_indices(cell),
ExcInternalError());
internal::vector_access (*dst[0], *dof_indices)
= local_dst_number[ind_local];
++ind_local;
- if (ind_local % n_vectors == n_irreg_components_filled)
- ind_local += n_vectors-n_irreg_components_filled;
+ if (ind_local % VectorizedArray<Number>::n_array_elements == n_irreg_components_filled)
+ ind_local += VectorizedArray<Number>::n_array_elements-n_irreg_components_filled;
}
Assert (dof_indices == dof_info.end_indices (cell),
ExcInternalError());
inline
Tensor<1,n_components,VectorizedArray<Number> >
FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
-get_dof_value (unsigned int dof) const
+get_dof_value (const unsigned int dof) const
{
AssertIndexRange (dof, dofs_per_cell);
- Tensor<1,n_components,vector_t> return_value (false);
+ Tensor<1,n_components,VectorizedArray<Number> > return_value (false);
for(unsigned int comp=0;comp<n_components;comp++)
return_value[comp] = this->values_dofs[comp][dof];
return return_value;
inline
Tensor<1,n_components,VectorizedArray<Number> >
FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
-get_value (unsigned int q_point) const
+get_value (const unsigned int q_point) const
{
Assert (this->values_quad_initialized==true,
internal::ExcAccessToUninitializedField());
AssertIndexRange (q_point, n_q_points);
- Tensor<1,n_components,vector_t> return_value (false);
+ Tensor<1,n_components,VectorizedArray<Number> > return_value (false);
for(unsigned int comp=0;comp<n_components;comp++)
return_value[comp] = this->values_quad[comp][q_point];
return return_value;
inline
Tensor<1,n_components,Tensor<1,dim,VectorizedArray<Number> > >
FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
-get_gradient (unsigned int q_point) const
+get_gradient (const unsigned int q_point) const
{
Assert (this->gradients_quad_initialized==true,
internal::ExcAccessToUninitializedField());
AssertIndexRange (q_point, n_q_points);
- Tensor<1,n_components,Tensor<1,dim,vector_t> > grad_out (false);
+ Tensor<1,n_components,Tensor<1,dim,VectorizedArray<Number> > > grad_out (false);
// Cartesian cell
- if (this->cell_type == 0)
+ if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
{
for (unsigned int comp=0;comp<n_components;comp++)
for (unsigned int d=0; d<dim; ++d)
grad_out[comp][d] = (this->gradients_quad[comp][d][q_point] *
- cartesian[0][d]);
+ cartesian_data[0][d]);
}
// cell with general Jacobian
- else if (this->cell_type == 2)
+ else if (this->cell_type == internal::MatrixFreeFunctions::general)
{
for(unsigned int comp=0;comp<n_components;comp++)
{
}
// cell with general Jacobian, but constant
// within the cell
- else // if (this->cell_type == 1)
+ else // if (this->cell_type == internal::MatrixFreeFunctions::affine)
{
for(unsigned int comp=0;comp<n_components;comp++)
{
inline
Tensor<1,n_components,Tensor<2,dim,VectorizedArray<Number> > >
FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
-get_hessian (unsigned int q_point) const
+get_hessian (const unsigned int q_point) const
{
Assert (this->hessians_quad_initialized==true,
internal::ExcAccessToUninitializedField());
AssertIndexRange (q_point, n_q_points);
- Tensor<2,dim,vector_t> hessian_out [n_components];
+ Tensor<2,dim,VectorizedArray<Number> > hessian_out [n_components];
// Cartesian cell
- if (this->cell_type == 0)
+ if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
{
- const Tensor<1,dim,vector_t> &jac = cartesian[0];
+ const Tensor<1,dim,VectorizedArray<Number> > &jac = cartesian_data[0];
for (unsigned int comp=0;comp<n_components;comp++)
for (unsigned int d=0; d<dim; ++d)
{
}
}
// cell with general Jacobian
- else if (this->cell_type == 2)
+ else if (this->cell_type == internal::MatrixFreeFunctions::general)
{
Assert (this->mapping_info.second_derivatives_initialized == true,
ExcNotInitialized());
- const Tensor<2,dim,vector_t> & jac = jacobian[q_point];
- const Tensor<2,dim,vector_t> & jac_grad = jacobian_grad[q_point];
- const typename internal::MatrixFreeFunctions::MappingInfo<dim,Number>::tensorUT
+ const Tensor<2,dim,VectorizedArray<Number> > & jac = jacobian[q_point];
+ const Tensor<2,dim,VectorizedArray<Number> > & jac_grad = jacobian_grad[q_point];
+ const Tensor<1,(dim>1?dim*(dim-1)/2:1),
+ Tensor<1,dim,VectorizedArray<Number> > >
& jac_grad_UT = jacobian_grad_upper[q_point];
for(unsigned int comp=0;comp<n_components;comp++)
{
// compute laplacian before the gradient
// because it needs to access unscaled
// gradient data
- vector_t tmp[dim][dim];
+ VectorizedArray<Number> tmp[dim][dim];
// compute tmp = hess_unit(u) * J^T. do this
// manually because we do not store the lower
}
// cell with general Jacobian, but constant
// within the cell
- else // if (this->cell_type == 1)
+ else // if (this->cell_type == internal::MatrixFreeFunctions::affine)
{
- const Tensor<2,dim,vector_t> &jac = jacobian[0];
+ const Tensor<2,dim,VectorizedArray<Number> > &jac = jacobian[0];
for(unsigned int comp=0;comp<n_components;comp++)
{
// compute laplacian before the gradient
// because it needs to access unscaled
// gradient data
- vector_t tmp[dim][dim];
+ VectorizedArray<Number> tmp[dim][dim];
// compute tmp = hess_unit(u) * J^T. do this
// manually because we do not store the lower
hessian_out[comp][e][d] = hessian_out[comp][d][e];
}
}
- return Tensor<1,n_components,Tensor<2,dim,vector_t> >(hessian_out);
+ return Tensor<1,n_components,Tensor<2,dim,VectorizedArray<Number> > >(hessian_out);
}
inline
Tensor<1,n_components,Tensor<1,dim,VectorizedArray<Number> > >
FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
-get_hessian_diagonal (unsigned int q_point) const
+get_hessian_diagonal (const unsigned int q_point) const
{
Assert (this->hessians_quad_initialized==true,
internal::ExcAccessToUninitializedField());
AssertIndexRange (q_point, n_q_points);
- Tensor<1,n_components,Tensor<1,dim,vector_t> > hessian_out (false);
+ Tensor<1,n_components,Tensor<1,dim,VectorizedArray<Number> > > hessian_out (false);
// Cartesian cell
- if (this->cell_type == 0)
+ if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
{
- const Tensor<1,dim,vector_t> &jac = cartesian[0];
+ const Tensor<1,dim,VectorizedArray<Number> > &jac = cartesian_data[0];
for (unsigned int comp=0;comp<n_components;comp++)
for (unsigned int d=0; d<dim; ++d)
hessian_out[comp][d] = (this->hessians_quad[comp][d][q_point] *
jac[d] * jac[d]);
}
// cell with general Jacobian
- else if (this->cell_type == 2)
+ else if (this->cell_type == internal::MatrixFreeFunctions::general)
{
Assert (this->mapping_info.second_derivatives_initialized == true,
ExcNotInitialized());
- const Tensor<2,dim,vector_t> &jac = jacobian[q_point];
- const Tensor<2,dim,vector_t> &jac_grad = jacobian_grad[q_point];
+ const Tensor<2,dim,VectorizedArray<Number> > &jac = jacobian[q_point];
+ const Tensor<2,dim,VectorizedArray<Number> > &jac_grad = jacobian_grad[q_point];
for(unsigned int comp=0;comp<n_components;comp++)
{
// compute laplacian before the gradient
// because it needs to access unscaled
// gradient data
- vector_t tmp[dim][dim];
+ VectorizedArray<Number> tmp[dim][dim];
// compute tmp = hess_unit(u) * J^T. do this
// manually because we do not store the lower
}
// cell with general Jacobian, but constant
// within the cell
- else // if (this->cell_type == 1)
+ else // if (this->cell_type == internal::MatrixFreeFunctions::affine)
{
- const Tensor<2,dim,vector_t> & jac = jacobian[0];
+ const Tensor<2,dim,VectorizedArray<Number> > & jac = jacobian[0];
for(unsigned int comp=0;comp<n_components;comp++)
{
// compute laplacian before the gradient
// because it needs to access unscaled
// gradient data
- vector_t tmp[dim][dim];
+ VectorizedArray<Number> tmp[dim][dim];
// compute tmp = hess_unit(u) * J^T. do this
// manually because we do not store the lower
inline
Tensor<1,n_components,VectorizedArray<Number> >
FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
-get_laplacian (unsigned int q_point) const
+get_laplacian (const unsigned int q_point) const
{
Assert (this->hessians_quad_initialized==true,
internal::ExcAccessToUninitializedField());
AssertIndexRange (q_point, n_q_points);
- Tensor<1,n_components,vector_t> laplacian_out (false);
- const Tensor<1,n_components,Tensor<1,dim,vector_t> > hess_diag
+ Tensor<1,n_components,VectorizedArray<Number> > laplacian_out (false);
+ const Tensor<1,n_components,Tensor<1,dim,VectorizedArray<Number> > > hess_diag
= get_hessian_diagonal(q_point);
for (unsigned int comp=0; comp<n_components; ++comp)
{
inline
void
FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
-submit_dof_value (Tensor<1,n_components,VectorizedArray<Number> > val_in,
- unsigned int dof)
+submit_dof_value (const Tensor<1,n_components,VectorizedArray<Number> > val_in,
+ const unsigned int dof)
{
#ifdef DEBUG
this->dof_values_initialized = true;
inline
void
FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
-submit_value (Tensor<1,n_components,VectorizedArray<Number> > val_in,
- unsigned int q_point)
+submit_value (const Tensor<1,n_components,VectorizedArray<Number> > val_in,
+ const unsigned int q_point)
{
#ifdef DEBUG
Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
AssertIndexRange (q_point, n_q_points);
this->values_quad_submitted = true;
#endif
- if (this->cell_type == 2)
+ if (this->cell_type == internal::MatrixFreeFunctions::general)
{
- const vector_t JxW = J_value[q_point];
+ const VectorizedArray<Number> JxW = J_value[q_point];
for (unsigned int comp=0; comp<n_components; ++comp)
this->values_quad[comp][q_point] = val_in[comp] * JxW;
}
- else //if (this->cell_type < 2)
+ else //if (this->cell_type < internal::MatrixFreeFunctions::general)
{
- const vector_t JxW = J_value[0] * quadrature_weights[q_point];
+ const VectorizedArray<Number> JxW = J_value[0] * quadrature_weights[q_point];
for (unsigned int comp=0; comp<n_components; ++comp)
this->values_quad[comp][q_point] = val_in[comp] * JxW;
}
inline
void
FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
-submit_gradient (Tensor<1,n_components,
- Tensor<1,dim,VectorizedArray<Number> > > grad_in,
- unsigned int q_point)
+submit_gradient (const Tensor<1,n_components,
+ Tensor<1,dim,VectorizedArray<Number> > > grad_in,
+ const unsigned int q_point)
{
#ifdef DEBUG
Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
AssertIndexRange (q_point, n_q_points);
this->gradients_quad_submitted = true;
#endif
- if (this->cell_type == 0)
+ if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
{
- const vector_t JxW = J_value[0] * quadrature_weights[q_point];
+ const VectorizedArray<Number> JxW = J_value[0] * quadrature_weights[q_point];
for (unsigned int comp=0;comp<n_components;comp++)
for (unsigned int d=0; d<dim; ++d)
this->gradients_quad[comp][d][q_point] = (grad_in[comp][d] *
- cartesian[0][d] * JxW);
+ cartesian_data[0][d] * JxW);
}
- else if (this->cell_type == 2)
+ else if (this->cell_type == internal::MatrixFreeFunctions::general)
{
for (unsigned int comp=0; comp<n_components; ++comp)
for (unsigned int d=0; d<dim; ++d)
{
- vector_t new_val = jacobian[q_point][0][d] * grad_in[comp][0];
+ VectorizedArray<Number> new_val = jacobian[q_point][0][d] * grad_in[comp][0];
for (unsigned e=1; e<dim; ++e)
new_val += jacobian[q_point][e][d] * grad_in[comp][e];
this->gradients_quad[comp][d][q_point] = new_val * J_value[q_point];
}
}
- else //if (this->cell_type == 1)
+ else //if (this->cell_type == internal::MatrixFreeFunctions::affine)
{
- const vector_t JxW = J_value[0] * quadrature_weights[q_point];
+ const VectorizedArray<Number> JxW = J_value[0] * quadrature_weights[q_point];
for (unsigned int comp=0; comp<n_components; ++comp)
for (unsigned int d=0; d<dim; ++d)
{
- vector_t new_val = jacobian[0][0][d] * grad_in[comp][0];
+ VectorizedArray<Number> new_val = jacobian[0][0][d] * grad_in[comp][0];
for (unsigned e=1; e<dim; ++e)
new_val += jacobian[0][e][d] * grad_in[comp][e];
this->gradients_quad[comp][d][q_point] = new_val * JxW;
inline
Tensor<1,n_components,VectorizedArray<Number> >
FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
-integrate_value ()
+integrate_value () const
{
#ifdef DEBUG
Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
Assert (this->values_quad_submitted == true,
internal::ExcAccessToUninitializedField());
#endif
- Tensor<1,n_components,vector_t> return_value (false);
+ Tensor<1,n_components,VectorizedArray<Number> > return_value (false);
for (unsigned int comp=0; comp<n_components; ++comp)
return_value[comp] = this->values_quad[comp][0];
for (unsigned int q=0; q<n_q_points; ++q)
inline
VectorizedArray<Number>
FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>::
-get_dof_value (unsigned int dof) const
+get_dof_value (const unsigned int dof) const
{
AssertIndexRange (dof, dofs_per_cell);
return this->values_dofs[0][dof];
inline
VectorizedArray<Number>
FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>::
-get_value (unsigned int q_point) const
+get_value (const unsigned int q_point) const
{
Assert (this->values_quad_initialized==true,
internal::ExcAccessToUninitializedField());
inline
Tensor<1,dim,VectorizedArray<Number> >
FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>::
-get_gradient (unsigned int q_point) const
+get_gradient (const unsigned int q_point) const
{
// could use the base class gradient, but that
// involves too many inefficient
internal::ExcAccessToUninitializedField());
AssertIndexRange (q_point, n_q_points);
- Tensor<1,dim,vector_t> grad_out (false);
+ Tensor<1,dim,VectorizedArray<Number> > grad_out (false);
// Cartesian cell
- if (this->cell_type == 0)
+ if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
{
for (unsigned int d=0; d<dim; ++d)
grad_out[d] = (this->gradients_quad[0][d][q_point] *
- this->cartesian[0][d]);
+ this->cartesian_data[0][d]);
}
// cell with general Jacobian
- else if (this->cell_type == 2)
+ else if (this->cell_type == internal::MatrixFreeFunctions::general)
{
for (unsigned int d=0; d<dim; ++d)
{
}
// cell with general Jacobian, but constant
// within the cell
- else // if (this->cell_type == 1)
+ else // if (this->cell_type == internal::MatrixFreeFunctions::affine)
{
for (unsigned int d=0; d<dim; ++d)
{
inline
Tensor<2,dim,VectorizedArray<Number> >
FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>::
-get_hessian (unsigned int q_point) const
+get_hessian (const unsigned int q_point) const
{
return BaseClass::get_hessian(q_point)[0];
}
inline
Tensor<1,dim,VectorizedArray<Number> >
FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>::
-get_hessian_diagonal (unsigned int q_point) const
+get_hessian_diagonal (const unsigned int q_point) const
{
return BaseClass::get_hessian_diagonal(q_point)[0];
}
inline
VectorizedArray<Number>
FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>::
-get_laplacian (unsigned int q_point) const
+get_laplacian (const unsigned int q_point) const
{
return BaseClass::get_laplacian(q_point)[0];
}
inline
void
FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>::
-submit_dof_value (VectorizedArray<Number> val_in,
- unsigned int dof)
+submit_dof_value (const VectorizedArray<Number> val_in,
+ const unsigned int dof)
{
#ifdef DEBUG
this->dof_values_initialized = true;
inline
void
FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>::
-submit_value (VectorizedArray<Number> val_in,
- unsigned int q_point)
+submit_value (const VectorizedArray<Number> val_in,
+ const unsigned int q_point)
{
#ifdef DEBUG
Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
AssertIndexRange (q_point, n_q_points);
this->values_quad_submitted = true;
#endif
- if (this->cell_type == 2)
+ if (this->cell_type == internal::MatrixFreeFunctions::general)
{
- const vector_t JxW = this->J_value[q_point];
+ const VectorizedArray<Number> JxW = this->J_value[q_point];
this->values_quad[0][q_point] = val_in * JxW;
}
- else //if (this->cell_type < 2)
+ else //if (this->cell_type < internal::MatrixFreeFunctions::general)
{
- const vector_t JxW = this->J_value[0] * this->quadrature_weights[q_point];
+ const VectorizedArray<Number> JxW = this->J_value[0] * this->quadrature_weights[q_point];
this->values_quad[0][q_point] = val_in * JxW;
}
}
inline
void
FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>::
-submit_gradient (Tensor<1,dim,VectorizedArray<Number> > grad_in,
- unsigned int q_point)
+submit_gradient (const Tensor<1,dim,VectorizedArray<Number> > grad_in,
+ const unsigned int q_point)
{
#ifdef DEBUG
Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
AssertIndexRange (q_point, n_q_points);
this->gradients_quad_submitted = true;
#endif
- if (this->cell_type == 0)
+ if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
{
- const vector_t JxW = this->J_value[0] * this->quadrature_weights[q_point];
+ const VectorizedArray<Number> JxW = this->J_value[0] * this->quadrature_weights[q_point];
for (unsigned int d=0; d<dim; ++d)
this->gradients_quad[0][d][q_point] = (grad_in[d] *
- this->cartesian[0][d] * JxW);
+ this->cartesian_data[0][d] *
+ JxW);
}
- else if (this->cell_type == 2)
+ else if (this->cell_type == internal::MatrixFreeFunctions::general)
{
for (unsigned int d=0; d<dim; ++d)
{
- vector_t new_val = this->jacobian[q_point][0][d] * grad_in[0];
+ VectorizedArray<Number> new_val = this->jacobian[q_point][0][d] * grad_in[0];
for (unsigned e=1; e<dim; ++e)
new_val += this->jacobian[q_point][e][d] * grad_in[e];
this->gradients_quad[0][d][q_point] = new_val * this->J_value[q_point];
}
}
- else //if (this->cell_type == 1)
+ else //if (this->cell_type == internal::MatrixFreeFunctions::affine)
{
- const vector_t JxW = this->J_value[0] * this->quadrature_weights[q_point];
+ const VectorizedArray<Number> JxW = this->J_value[0] * this->quadrature_weights[q_point];
for (unsigned int d=0; d<dim; ++d)
{
- vector_t new_val = this->jacobian[0][0][d] * grad_in[0];
+ VectorizedArray<Number> new_val = this->jacobian[0][0][d] * grad_in[0];
for (unsigned e=1; e<dim; ++e)
new_val += this->jacobian[0][e][d] * grad_in[e];
this->gradients_quad[0][d][q_point] = new_val * JxW;
inline
VectorizedArray<Number>
FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>::
-integrate_value ()
+integrate_value () const
{
return BaseClass::integrate_value()[0];
}
inline
Tensor<2,dim,VectorizedArray<Number> >
FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>::
-get_gradient (unsigned int q_point) const
+get_gradient (const unsigned int q_point) const
{
return BaseClass::get_gradient (q_point);
}
inline
VectorizedArray<Number>
FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>::
-get_divergence (unsigned int q_point) const
+get_divergence (const unsigned int q_point) const
{
Assert (this->gradients_quad_initialized==true,
internal::ExcAccessToUninitializedField());
AssertIndexRange (q_point, n_q_points);
- vector_t divergence;
+ VectorizedArray<Number> divergence;
// Cartesian cell
- if (this->cell_type == 0)
+ if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
{
divergence = (this->gradients_quad[0][0][q_point] *
- this->cartesian[0][0]);
+ this->cartesian_data[0][0]);
for (unsigned int d=1; d<dim; ++d)
divergence += (this->gradients_quad[d][d][q_point] *
- this->cartesian[0][d]);
+ this->cartesian_data[0][d]);
}
// cell with general Jacobian
- else if (this->cell_type == 2)
+ else if (this->cell_type == internal::MatrixFreeFunctions::general)
{
divergence = (this->jacobian[q_point][0][0] *
this->gradients_quad[0][0][q_point]);
}
// cell with general Jacobian, but constant
// within the cell
- else // if (this->cell_type == 1)
+ else // if (this->cell_type == internal::MatrixFreeFunctions::affine)
{
divergence = (this->jacobian[0][0][0] *
this->gradients_quad[0][0][q_point]);
inline
SymmetricTensor<2,dim,VectorizedArray<Number> >
FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>::
-get_symmetric_gradient (unsigned int q_point) const
+get_symmetric_gradient (const unsigned int q_point) const
{
// copy from generic function into
// dim-specialization function
- const Tensor<2,dim,vector_t> grad = get_gradient(q_point);
- vector_t symmetrized [(dim*dim+dim)/2];
- vector_t half = make_vectorized_array (0.5);
+ const Tensor<2,dim,VectorizedArray<Number> > grad = get_gradient(q_point);
+ VectorizedArray<Number> symmetrized [(dim*dim+dim)/2];
+ VectorizedArray<Number> half = make_vectorized_array (0.5);
for (unsigned int d=0; d<dim; ++d)
symmetrized[d] = grad[d][d];
switch (dim)
default:
Assert (false, ExcNotImplemented());
}
- return SymmetricTensor<2,dim,vector_t> (symmetrized);
+ return SymmetricTensor<2,dim,VectorizedArray<Number> > (symmetrized);
}
template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
inline
-typename FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>::curl_type
+Tensor<1,dim==2?1:dim,VectorizedArray<Number> >
FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>::
-get_curl (unsigned int q_point) const
+get_curl (const unsigned int q_point) const
{
// copy from generic function into
// dim-specialization function
- const Tensor<2,dim,vector_t> grad = get_gradient(q_point);
- curl_type curl;
+ const Tensor<2,dim,VectorizedArray<Number> > grad = get_gradient(q_point);
+ Tensor<1,dim==2?1:dim,VectorizedArray<Number> > curl (false);
switch (dim)
{
case 1:
inline
Tensor<2,dim,VectorizedArray<Number> >
FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>::
-get_hessian_diagonal (unsigned int q_point) const
+get_hessian_diagonal (const unsigned int q_point) const
{
Assert (this->hessians_quad_initialized==true,
internal::ExcAccessToUninitializedField());
inline
Tensor<3,dim,VectorizedArray<Number> >
FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>::
-get_hessian (unsigned int q_point) const
+get_hessian (const unsigned int q_point) const
{
Assert (this->hessians_quad_initialized==true,
internal::ExcAccessToUninitializedField());
inline
void
FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>::
-submit_gradient (Tensor<2,dim,VectorizedArray<Number> > grad_in,
- unsigned int q_point)
+submit_gradient (const Tensor<2,dim,VectorizedArray<Number> > grad_in,
+ const unsigned int q_point)
{
BaseClass::submit_gradient (grad_in, q_point);
}
inline
void
FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>::
-submit_gradient (Tensor<1,dim,Tensor<1,dim,VectorizedArray<Number> > > grad_in,
- unsigned int q_point)
+submit_gradient (const Tensor<1,dim,Tensor<1,dim,VectorizedArray<Number> > > grad_in,
+ const unsigned int q_point)
{
BaseClass::submit_gradient(grad_in, q_point);
}
inline
void
FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>::
-submit_symmetric_gradient (SymmetricTensor<2,dim,VectorizedArray<Number> >
- sym_grad,
- unsigned int q_point)
+submit_symmetric_gradient (const SymmetricTensor<2,dim,VectorizedArray<Number> >
+ sym_grad,
+ const unsigned int q_point)
{
// could have used base class operator, but
// that involves some overhead which is
AssertIndexRange (q_point, n_q_points);
this->gradients_quad_submitted = true;
#endif
- if (this->cell_type == 0)
+ if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
{
- const vector_t JxW = this->J_value[0] * this->quadrature_weights[q_point];
+ const VectorizedArray<Number> JxW = this->J_value[0] * this->quadrature_weights[q_point];
for (unsigned int d=0; d<dim; ++d)
this->gradients_quad[d][d][q_point] = (sym_grad.access_raw_entry(d) *
JxW *
- this->cartesian[0][d]);
+ this->cartesian_data[0][d]);
for (unsigned int e=0, counter=dim; e<dim; ++e)
for (unsigned int d=e+1; d<dim; ++d, ++counter)
{
- const vector_t value = sym_grad.access_raw_entry(counter) * JxW;
+ const VectorizedArray<Number> value = sym_grad.access_raw_entry(counter) * JxW;
this->gradients_quad[e][d][q_point] = (value *
- this->cartesian[0][d]);
+ this->cartesian_data[0][d]);
this->gradients_quad[d][e][q_point] = (value *
- this->cartesian[0][e]);
+ this->cartesian_data[0][e]);
}
}
- else if (this->cell_type == 2)
+ else if (this->cell_type == internal::MatrixFreeFunctions::general)
{
- vector_t weighted [dim][dim];
+ VectorizedArray<Number> weighted [dim][dim];
{
- const vector_t JxW = this->J_value[q_point];
+ const VectorizedArray<Number> JxW = this->J_value[q_point];
for (unsigned int i=0; i<dim; ++i)
weighted[i][i] = sym_grad.access_raw_entry(i) * JxW;
for (unsigned int i=0, counter=dim; i<dim; ++i)
for (unsigned int j=i+1; j<dim; ++j, ++counter)
{
- const vector_t value = sym_grad.access_raw_entry(counter) * JxW;
+ const VectorizedArray<Number> value = sym_grad.access_raw_entry(counter) * JxW;
weighted[i][j] = value;
weighted[j][i] = value;
}
for (unsigned int comp=0; comp<dim; ++comp)
for (unsigned int d=0; d<dim; ++d)
{
- vector_t new_val = this->jacobian[q_point][0][d] * weighted[comp][0];
+ VectorizedArray<Number> new_val = this->jacobian[q_point][0][d] * weighted[comp][0];
for (unsigned e=1; e<dim; ++e)
new_val += this->jacobian[q_point][e][d] * weighted[comp][e];
this->gradients_quad[comp][d][q_point] = new_val;
}
}
- else //if (this->cell_type == 1)
+ else //if (this->cell_type == internal::MatrixFreeFunctions::affine)
{
- vector_t weighted [dim][dim];
+ VectorizedArray<Number> weighted [dim][dim];
{
- const vector_t JxW = (this->J_value[0] *
+ const VectorizedArray<Number> JxW = (this->J_value[0] *
this->quadrature_weights[q_point]);
for (unsigned int i=0; i<dim; ++i)
weighted[i][i] = sym_grad.access_raw_entry(i) * JxW;
for (unsigned int i=0, counter=dim; i<dim; ++i)
for (unsigned int j=i+1; j<dim; ++j, ++counter)
{
- const vector_t value = sym_grad.access_raw_entry(counter) * JxW;
+ const VectorizedArray<Number> value = sym_grad.access_raw_entry(counter) * JxW;
weighted[i][j] = value;
weighted[j][i] = value;
}
for (unsigned int comp=0; comp<dim; ++comp)
for (unsigned int d=0; d<dim; ++d)
{
- vector_t new_val = this->jacobian[q_point][0][d] * weighted[comp][0];
+ VectorizedArray<Number> new_val = this->jacobian[q_point][0][d] * weighted[comp][0];
for (unsigned e=1; e<dim; ++e)
new_val += this->jacobian[q_point][e][d] * weighted[comp][e];
this->gradients_quad[comp][d][q_point] = new_val;
inline
void
FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>::
-submit_curl (curl_type curl,
- unsigned int q_point)
+submit_curl (const Tensor<1,dim==2?1:dim,VectorizedArray<Number> > curl,
+ const unsigned int q_point)
{
- Tensor<2,dim,vector_t> grad;
+ Tensor<2,dim,VectorizedArray<Number> > grad;
switch (dim)
{
case 1:
/*----------------------- FEEvaluationGeneral -------------------------------*/
-template <int dim, int n_dofs_1d, int n_q_points_1d, int n_components,
+template <int dim, int fe_degree, int n_q_points_1d, int n_components,
typename Number>
inline
-FEEvaluationGeneral<dim,n_dofs_1d,n_q_points_1d,n_components,Number>::
+FEEvaluationGeneral<dim,fe_degree,n_q_points_1d,n_components,Number>::
FEEvaluationGeneral (const MatrixFree<dim,Number> &data_in,
const unsigned int fe_no,
const unsigned int quad_no_in)
"-------------------------------------------------------\n";
message += "Illegal arguments in constructor/wrong template arguments!\n";
message += " Called --> FEEvaluation<dim,";
- message += Utilities::int_to_string(n_dofs_1d) + ",";
+ message += Utilities::int_to_string(fe_degree) + ",";
message += Utilities::int_to_string(n_q_points_1d) + ",Number>(data, ";
message += Utilities::int_to_string(fe_no) + ", ";
message += Utilities::int_to_string(quad_no_in) + ")\n";
{
message += "Wrong vector component selection:\n";
message += " Did you mean FEEvaluation<dim,Number,";
- message += Utilities::int_to_string(n_dofs_1d) + ",";
+ message += Utilities::int_to_string(fe_degree) + ",";
message += Utilities::int_to_string(n_q_points_1d) + ">(data, ";
message += Utilities::int_to_string(proposed_dof_comp) + ", ";
message += Utilities::int_to_string(proposed_quad_comp) + ")?\n";
// ok, did not find the numbers specified by
// the template arguments in the given
// list. Suggest correct template arguments
- const unsigned int proposed_n_dofs_1d = static_cast<unsigned int>(std::pow(1.001*this->data.dofs_per_cell,1./dim));
+ const unsigned int proposed_fe_degree = static_cast<unsigned int>(std::pow(1.001*this->data.dofs_per_cell,1./dim))-1;
const unsigned int proposed_n_q_points_1d = static_cast<unsigned int>(std::pow(1.001*this->data.n_q_points,1./dim));
message += "Wrong template arguments:\n";
message += " Did you mean FEEvaluation<dim,";
- message += Utilities::int_to_string(proposed_n_dofs_1d) + ",";
+ message += Utilities::int_to_string(proposed_fe_degree) + ",";
message += Utilities::int_to_string(proposed_n_q_points_1d);
message += ",Number>(data, ";
message += Utilities::int_to_string(fe_no) + ", ";
message += Utilities::int_to_string(quad_no_in) + ")?\n";
std::string correct_pos;
- if (proposed_n_dofs_1d != n_dofs_1d)
+ if (proposed_fe_degree != fe_degree)
correct_pos = " ^";
else
correct_pos = " ";
-template <int dim, int n_dofs_1d, int n_q_points_1d, int n_components,
+template <int dim, int fe_degree, int n_q_points_1d, int n_components,
typename Number>
inline
void
-FEEvaluationGeneral<dim,n_dofs_1d,n_q_points_1d,n_components,Number>::
+FEEvaluationGeneral<dim,fe_degree,n_q_points_1d,n_components,Number>::
evaluate (bool evaluate_val, bool evaluate_grad, bool evaluate_lapl)
{
Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
Assert (this->dof_values_initialized == true,
internal::ExcAccessToUninitializedField());
- const vector_t * val = this->data.shape_values.begin();
- const vector_t * grad = this->data.shape_gradients.begin();
- const vector_t * hess = this->data.shape_hessians.begin();
+ const VectorizedArray<Number> * val = this->data.shape_values.begin();
+ const VectorizedArray<Number> * grad = this->data.shape_gradients.begin();
+ const VectorizedArray<Number> * hess = this->data.shape_hessians.begin();
for(unsigned int comp=0;comp<n_components;comp++)
{
- vector_t temp1[n_dofs_1d > n_q_points_1d ? dofs_per_cell : n_q_points];
- vector_t temp2[n_dofs_1d > n_q_points_1d ? dofs_per_cell : n_q_points];
+ VectorizedArray<Number> temp1[fe_degree >= n_q_points_1d ? dofs_per_cell : n_q_points];
+ VectorizedArray<Number> temp2[fe_degree >= n_q_points_1d ? dofs_per_cell : n_q_points];
if (dim == 3)
{
-template <int dim, int n_dofs_1d, int n_q_points_1d, int n_components,
+template <int dim, int fe_degree, int n_q_points_1d, int n_components,
typename Number>
inline
void
-FEEvaluationGeneral<dim,n_dofs_1d,n_q_points_1d,n_components,Number>::
+FEEvaluationGeneral<dim,fe_degree,n_q_points_1d,n_components,Number>::
integrate (bool integrate_val,bool integrate_grad)
{
#ifdef DEBUG
internal::ExcAccessToUninitializedField());
#endif
- const vector_t * val = this->data.shape_values.begin();
- const vector_t * grad = this->data.shape_gradients.begin();
+ const VectorizedArray<Number> * val = this->data.shape_values.begin();
+ const VectorizedArray<Number> * grad = this->data.shape_gradients.begin();
for(unsigned int comp=0;comp<n_components;comp++)
{
- vector_t temp1[n_dofs_1d > n_q_points_1d ? dofs_per_cell : n_q_points];
- vector_t temp2[n_dofs_1d > n_q_points_1d ? dofs_per_cell : n_q_points];
+ VectorizedArray<Number> temp1[fe_degree >= n_q_points_1d ? dofs_per_cell : n_q_points];
+ VectorizedArray<Number> temp2[fe_degree >= n_q_points_1d ? dofs_per_cell : n_q_points];
if (dim == 3)
{
{
// grad x: can sum to temporary value in temp1
if (integrate_val == true)
- apply_tensor_prod<0,false,true>
+ apply_tensor_prod<0,false,true>
(grad, this->gradients_quad[comp][0],temp1);
else
- apply_tensor_prod<0,false,false>
+ apply_tensor_prod<0,false,false>
(grad, this->gradients_quad[comp][0],temp1);
}
apply_tensor_prod<1,false,false> (val, temp1, temp2);
{
//grad x
if (integrate_val == true)
- apply_tensor_prod<0,false,true>
+ apply_tensor_prod<0,false,true>
(grad, this->gradients_quad[comp][0],temp1);
else
- apply_tensor_prod<0,false,false>
+ apply_tensor_prod<0,false,false>
(grad, this->gradients_quad[comp][0],temp1);
}
apply_tensor_prod<1,false,false> (val, temp1, this->values_dofs[comp]);
-template <int dim, int n_dofs_1d, int n_q_points_1d, int n_components,
+template <int dim, int fe_degree, int n_q_points_1d, int n_components,
typename Number>
inline
Point<dim,VectorizedArray<Number> >
-FEEvaluationGeneral<dim,n_dofs_1d,n_q_points_1d,n_components,Number>::
+FEEvaluationGeneral<dim,fe_degree,n_q_points_1d,n_components,Number>::
quadrature_point (const unsigned int q) const
{
Assert (this->mapping_info.quadrature_points_initialized == true,
// are stored, only the diagonal. Hence, need
// to find the tensor product index and
// retrieve the value from that
- if (this->cell_type == 0)
+ if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
{
- Point<dim,vector_t> point (false);
+ Point<dim,VectorizedArray<Number> > point (false);
switch (dim)
{
case 1:
// to three spatial dimensions. Does not
// assume any symmetry in the shape values
// field
-template <int dim, int n_dofs_1d, int n_q_points_1d, int n_components,
+template <int dim, int fe_degree, int n_q_points_1d, int n_components,
typename Number>
template <int direction, bool dof_to_quad, bool add>
inline
void
-FEEvaluationGeneral<dim,n_dofs_1d,n_q_points_1d,n_components,Number>::
+FEEvaluationGeneral<dim,fe_degree,n_q_points_1d,n_components,Number>::
apply_tensor_prod (const VectorizedArray<Number>*shape_data,
const VectorizedArray<Number> input [],
VectorizedArray<Number> output [])
{
AssertIndexRange (direction, dim);
- const int mm = dof_to_quad ? n_dofs_1d : n_q_points_1d,
- nn = dof_to_quad ? n_q_points_1d : n_dofs_1d;
+ const int mm = dof_to_quad ? (fe_degree+1) : n_q_points_1d,
+ nn = dof_to_quad ? n_q_points_1d : (fe_degree+1);
const int n_blocks1 = (dim > 1 ? (direction > 0 ? nn : mm) : 1);
const int n_blocks2 = (dim > 2 ? (direction > 1 ? nn : mm) : 1);
const int stride = ((direction > 0 ? nn : 1 ) *
(direction > 1 ? nn : 1));
- const vector_t * in = &input[0];
- vector_t * out = &output[0];
+ const VectorizedArray<Number> * in = &input[0];
+ VectorizedArray<Number> * out = &output[0];
for (int i2=0; i2<n_blocks2; ++i2)
{
for (int i1=0; i1<n_blocks1; ++i1)
{
for (int col=0; col<nn; ++col)
{
- vector_t val0;
+ VectorizedArray<Number> val0;
if (dof_to_quad == true)
val0 = shape_data[col];
else
val0 = shape_data[col*n_q_points_1d];
- vector_t res0 = val0 * in[0];
+ VectorizedArray<Number> res0 = val0 * in[0];
for (int ind=1; ind<mm; ++ind)
{
if (dof_to_quad == true)
/*----------------------- FEEvaluation -------------------------------*/
-template <int dim, int n_dofs_1d, int n_q_points_1d, int n_components,
+template <int dim, int fe_degree, int n_q_points_1d, int n_components,
typename Number>
inline
-FEEvaluation<dim,n_dofs_1d,n_q_points_1d,n_components,Number>::
+FEEvaluation<dim,fe_degree,n_q_points_1d,n_components,Number>::
FEEvaluation (const MatrixFree<dim,Number> &data_in,
const unsigned int fe_no,
const unsigned int quad_no)
error_message += "Try FEEvaluationGeneral<...> instead!";
// symmetry for values
+ const unsigned int n_dofs_1d = fe_degree + 1;
for (unsigned int i=0; i<(n_dofs_1d+1)/2; ++i)
for (unsigned int j=0; j<n_q_points_1d; ++j)
Assert (std::fabs(this->data.shape_values[i*n_q_points_1d+j][0] -
-template <int dim, int n_dofs_1d, int n_q_points_1d, int n_components,
+template <int dim, int fe_degree, int n_q_points_1d, int n_components,
typename Number>
inline
void
-FEEvaluation<dim,n_dofs_1d,n_q_points_1d,n_components,Number>::
+FEEvaluation<dim,fe_degree,n_q_points_1d,n_components,Number>::
evaluate (bool evaluate_val, bool evaluate_grad, bool evaluate_lapl)
{
Assert (this->cell != numbers::invalid_unsigned_int,
for(unsigned int comp=0;comp<n_components;comp++)
{
- vector_t temp1[n_dofs_1d > n_q_points_1d ? dofs_per_cell : n_q_points];
- vector_t temp2[n_dofs_1d > n_q_points_1d ? dofs_per_cell : n_q_points];
+ VectorizedArray<Number> temp1[fe_degree >= n_q_points_1d ? dofs_per_cell : n_q_points];
+ VectorizedArray<Number> temp2[fe_degree >= n_q_points_1d ? dofs_per_cell : n_q_points];
if (dim == 3)
{
-template <int dim, int n_dofs_1d, int n_q_points_1d, int n_components,
+template <int dim, int fe_degree, int n_q_points_1d, int n_components,
typename Number>
inline
void
-FEEvaluation<dim,n_dofs_1d,n_q_points_1d,n_components,Number>::
+FEEvaluation<dim,fe_degree,n_q_points_1d,n_components,Number>::
integrate (bool integrate_val,bool integrate_grad)
{
#ifdef DEBUG
for(unsigned int comp=0;comp<n_components;comp++)
{
- vector_t temp1[n_dofs_1d > n_q_points_1d ? dofs_per_cell : n_q_points];
- vector_t temp2[n_dofs_1d > n_q_points_1d ? dofs_per_cell : n_q_points];
+ VectorizedArray<Number> temp1[fe_degree >= n_q_points_1d ? dofs_per_cell : n_q_points];
+ VectorizedArray<Number> temp2[fe_degree >= n_q_points_1d ? dofs_per_cell : n_q_points];
if (dim == 3)
{
// ----------------- optimized implementation tensor product symmetric case
-template <int dim, int n_dofs_1d, int n_q_points_1d, int n_components,
+template <int dim, int fe_degree, int n_q_points_1d, int n_components,
typename Number>
template <int direction, bool dof_to_quad, bool add>
inline
void
-FEEvaluation<dim,n_dofs_1d,n_q_points_1d,n_components,Number>::
+FEEvaluation<dim,fe_degree,n_q_points_1d,n_components,Number>::
apply_values (const VectorizedArray<Number> input [],
VectorizedArray<Number> output [])
{
AssertIndexRange (direction, dim);
- const int mm = dof_to_quad ? n_dofs_1d : n_q_points_1d,
- nn = dof_to_quad ? n_q_points_1d : n_dofs_1d;
+ const int mm = dof_to_quad ? (fe_degree+1) : n_q_points_1d,
+ nn = dof_to_quad ? n_q_points_1d : (fe_degree+1);
const int n_cols = nn / 2;
const int mid = mm / 2;
const int stride = ((direction > 0 ? nn : 1 ) *
(direction > 1 ? nn : 1));
- const vector_t * in = &input[0];
- vector_t * out = &output[0];
+ const VectorizedArray<Number> * in = &input[0];
+ VectorizedArray<Number> * out = &output[0];
for (int i2=0; i2<n_blocks2; ++i2)
{
for (int i1=0; i1<n_blocks1; ++i1)
{
for (int col=0; col<n_cols; ++col)
{
- vector_t val0, val1, res0, res1;
+ VectorizedArray<Number> val0, val1, res0, res1;
if (dof_to_quad == true)
{
val0 = this->data.shape_values[col];
}
}
else
- res0 = res1 = vector_t();
+ res0 = res1 = VectorizedArray<Number>();
if (dof_to_quad == true)
{
if (mm % 2 == 1)
}
else if (dof_to_quad == true && nn%2==1)
{
- vector_t res0;
- vector_t val0 = this->data.shape_values[n_cols];
+ VectorizedArray<Number> res0;
+ VectorizedArray<Number> val0 = this->data.shape_values[n_cols];
if (mid > 0)
{
res0 = in[0] + in[stride*(mm-1)];
for (int ind=1; ind<mid; ++ind)
{
val0 = this->data.shape_values[ind*n_q_points_1d+n_cols];
- vector_t val1 = in[stride*ind] + in[stride*(mm-1-ind)];
+ VectorizedArray<Number> val1 = in[stride*ind] + in[stride*(mm-1-ind)];
val1 *= val0;
res0 += val1;
}
}
else
- res0 = vector_t();
+ res0 = VectorizedArray<Number>();
if (mm % 2 == 1)
{
val0 = this->data.shape_values[mid*n_q_points_1d+n_cols];
}
else if (dof_to_quad == false && nn%2 == 1)
{
- vector_t res0;
+ VectorizedArray<Number> res0;
if (mid > 0)
{
- vector_t val0 = this->data.shape_values[n_cols*n_q_points_1d];
+ VectorizedArray<Number> val0 = this->data.shape_values[n_cols*n_q_points_1d];
res0 = in[0] + in[stride*(mm-1)];
res0 *= val0;
for (int ind=1; ind<mid; ++ind)
{
val0 = this->data.shape_values[n_cols*n_q_points_1d+ind];
- vector_t val1 = in[stride*ind] + in[stride*(mm-1-ind)];
+ VectorizedArray<Number> val1 = in[stride*ind] + in[stride*(mm-1-ind)];
val1 *= val0;
res0 += val1;
}
-template <int dim, int n_dofs_1d, int n_q_points_1d, int n_components,
+template <int dim, int fe_degree, int n_q_points_1d, int n_components,
typename Number>
template <int direction, bool dof_to_quad, bool add>
inline
void
-FEEvaluation<dim,n_dofs_1d,n_q_points_1d,n_components,Number>::
+FEEvaluation<dim,fe_degree,n_q_points_1d,n_components,Number>::
apply_gradients (const VectorizedArray<Number> input [],
VectorizedArray<Number> output [])
{
AssertIndexRange (direction, dim);
- const int mm = dof_to_quad ? n_dofs_1d : n_q_points_1d,
- nn = dof_to_quad ? n_q_points_1d : n_dofs_1d;
+ const int mm = dof_to_quad ? (fe_degree+1) : n_q_points_1d,
+ nn = dof_to_quad ? n_q_points_1d : (fe_degree+1);
const int n_cols = nn / 2;
const int mid = mm / 2;
const int stride = ((direction > 0 ? nn : 1 ) *
(direction > 1 ? nn : 1));
- const vector_t * in = &input[0];
- vector_t * out = &output[0];
+ const VectorizedArray<Number> * in = &input[0];
+ VectorizedArray<Number> * out = &output[0];
for (int i2=0; i2<n_blocks2; ++i2)
{
for (int i1=0; i1<n_blocks1; ++i1)
{
for (int col=0; col<n_cols; ++col)
{
- vector_t val0, val1, res0, res1;
+ VectorizedArray<Number> val0, val1, res0, res1;
if (dof_to_quad == true)
{
val0 = this->data.shape_gradients[col];
}
}
else
- res0 = res1 = vector_t();
+ res0 = res1 = VectorizedArray<Number>();
if (mm % 2 == 1)
{
if (dof_to_quad == true)
}
if ( nn%2 == 1 )
{
- vector_t val0, res0;
+ VectorizedArray<Number> val0, res0;
if (dof_to_quad == true)
val0 = this->data.shape_gradients[n_cols];
else
val0 = this->data.shape_gradients[ind*n_q_points_1d+n_cols];
else
val0 = this->data.shape_gradients[n_cols*n_q_points_1d+ind];
- vector_t val1 = in[stride*ind] - in[stride*(mm-1-ind)];
+ VectorizedArray<Number> val1 = in[stride*ind] - in[stride*(mm-1-ind)];
val1 *= val0;
res0 += val1;
}
// same symmetry relations hold. However, it
// is not possible to omit some values that
// are zero for the values
-template <int dim, int n_dofs_1d, int n_q_points_1d, int n_components,
+template <int dim, int fe_degree, int n_q_points_1d, int n_components,
typename Number>
template <int direction, bool dof_to_quad, bool add>
inline
void
-FEEvaluation<dim,n_dofs_1d,n_q_points_1d,n_components,Number>::
+FEEvaluation<dim,fe_degree,n_q_points_1d,n_components,Number>::
apply_hessians (const VectorizedArray<Number> input [],
VectorizedArray<Number> output [])
{
AssertIndexRange (direction, dim);
- const int mm = dof_to_quad ? n_dofs_1d : n_q_points_1d,
- nn = dof_to_quad ? n_q_points_1d : n_dofs_1d;
+ const int mm = dof_to_quad ? (fe_degree+1) : n_q_points_1d,
+ nn = dof_to_quad ? n_q_points_1d : (fe_degree+1);
const int n_cols = nn / 2;
const int mid = mm / 2;
const int stride = ((direction > 0 ? nn : 1 ) *
(direction > 1 ? nn : 1));
- const vector_t * in = &input[0];
- vector_t * out = &output[0];
+ const VectorizedArray<Number> * in = &input[0];
+ VectorizedArray<Number> * out = &output[0];
for (int i2=0; i2<n_blocks2; ++i2)
{
for (int i1=0; i1<n_blocks1; ++i1)
{
for (int col=0; col<n_cols; ++col)
{
- vector_t val0, val1, res0, res1;
+ VectorizedArray<Number> val0, val1, res0, res1;
if (dof_to_quad == true)
{
val0 = this->data.shape_hessians[col];
}
}
else
- res0 = res1 = vector_t();
+ res0 = res1 = VectorizedArray<Number>();
if (mm % 2 == 1)
{
if (dof_to_quad == true)
}
if ( nn%2 == 1 )
{
- vector_t val0, res0;
+ VectorizedArray<Number> val0, res0;
if (dof_to_quad == true)
val0 = this->data.shape_hessians[n_cols];
else
val0 = this->data.shape_hessians[ind*n_q_points_1d+n_cols];
else
val0 = this->data.shape_hessians[n_cols*n_q_points_1d+ind];
- vector_t val1 = in[stride*ind] + in[stride*(mm-1-ind)];
+ VectorizedArray<Number> val1 = in[stride*ind] + in[stride*(mm-1-ind)];
val1 *= val0;
res0 += val1;
}
}
else
- res0 = vector_t();
+ res0 = VectorizedArray<Number>();
if (mm % 2 == 1)
{
if (dof_to_quad == true)
/*----------------------- FEEvaluationGL -------------------------------*/
-template <int dim, int n_points_1d, int n_components, typename Number>
+template <int dim, int fe_degree, int n_components, typename Number>
inline
-FEEvaluationGL<dim,n_points_1d,n_components,Number>::
+FEEvaluationGL<dim,fe_degree,n_components,Number>::
FEEvaluationGL (const MatrixFree<dim,Number> &data_in,
const unsigned int fe_no,
const unsigned int quad_no)
const double zero_tol =
types_are_equal<Number,double>::value==true?1e-9:1e-7;
+ const unsigned int n_points_1d = fe_degree+1;
for (unsigned int i=0; i<n_points_1d; ++i)
for (unsigned int j=0; j<n_points_1d; ++j)
if (i!=j)
-template <int dim, int n_points_1d, int n_components, typename Number>
+template <int dim, int fe_degree, int n_components, typename Number>
inline
void
-FEEvaluationGL<dim,n_points_1d,n_components,Number>::
+FEEvaluationGL<dim,fe_degree,n_components,Number>::
evaluate (bool evaluate_val,bool evaluate_grad,bool evaluate_lapl)
{
Assert (this->cell != numbers::invalid_unsigned_int,
this->template apply_hessians<2,true,false> (this->values_dofs[comp],
this->hessians_quad[comp][2]);
- vector_t temp1[n_q_points];
+ VectorizedArray<Number> temp1[n_q_points];
// grad xy
apply_gradients<0,true,false> (this->values_dofs[comp], temp1);
apply_gradients<1,true,false> (temp1, this->hessians_quad[comp][3]);
// grad y
this->template apply_hessians<1,true,false> (this->values_dofs[comp],
this->hessians_quad[comp][1]);
- vector_t temp1[n_q_points];
+ VectorizedArray<Number> temp1[n_q_points];
// grad xy
apply_gradients<0,true,false> (this->values_dofs[comp], temp1);
apply_gradients<1,true,false> (temp1, this->hessians_quad[comp][2]);
-template <int dim, int n_points_1d, int n_components, typename Number>
+template <int dim, int fe_degree, int n_components, typename Number>
inline
void
-FEEvaluationGL<dim,n_points_1d,n_components,Number>::
+FEEvaluationGL<dim,fe_degree,n_components,Number>::
integrate (bool integrate_val, bool integrate_grad)
{
Assert (this->cell != numbers::invalid_unsigned_int,
-template <int dim, int n_points_1d, int n_components, typename Number>
+template <int dim, int fe_degree, int n_components, typename Number>
template <int direction, bool dof_to_quad, bool add>
inline
void
-FEEvaluationGL<dim,n_points_1d,n_components,Number>::
+FEEvaluationGL<dim,fe_degree,n_components,Number>::
apply_gradients (const VectorizedArray<Number> input [],
VectorizedArray<Number> output [])
{
AssertIndexRange (direction, dim);
- const int mm = n_points_1d;
- const int nn = n_points_1d;
+ const int mm = fe_degree+1;
+ const int nn = fe_degree+1;
const int n_cols = nn / 2;
const int mid = mm / 2;
const int stride = ((direction > 0 ? nn : 1 ) *
(direction > 1 ? nn : 1));
- const vector_t * in = &input[0];
- vector_t * out = &output[0];
+ const VectorizedArray<Number> * in = &input[0];
+ VectorizedArray<Number> * out = &output[0];
for (int i2=0; i2<n_blocks2; ++i2)
{
for (int i1=0; i1<n_blocks1; ++i1)
{
for (int col=0; col<n_cols; ++col)
{
- vector_t val0, val1, res0, res1;
+ VectorizedArray<Number> val0, val1, res0, res1;
if (dof_to_quad == true)
{
val0 = this->data.shape_gradients[col];
}
else
{
- val0 = this->data.shape_gradients[col*n_points_1d];
- val1 = this->data.shape_gradients[(nn-col-1)*n_points_1d];
+ val0 = this->data.shape_gradients[col*mm];
+ val1 = this->data.shape_gradients[(nn-col-1)*mm];
}
if (mid > 0)
{
{
if (dof_to_quad == true)
{
- val0 = this->data.shape_gradients[ind*n_points_1d+col];
- val1 = this->data.shape_gradients[ind*n_points_1d+nn-1-col];
+ val0 = this->data.shape_gradients[ind*mm+col];
+ val1 = this->data.shape_gradients[ind*mm+nn-1-col];
}
else
{
- val0 = this->data.shape_gradients[col*n_points_1d+ind];
- val1 = this->data.shape_gradients[(nn-col-1)*n_points_1d+ind];
+ val0 = this->data.shape_gradients[col*mm+ind];
+ val1 = this->data.shape_gradients[(nn-col-1)*mm+ind];
}
// at inner points, the gradient is zero for
}
}
else
- res0 = res1 = vector_t();
+ res0 = res1 = VectorizedArray<Number>();
if (mm % 2 == 1)
{
if (dof_to_quad == true)
- val0 = this->data.shape_gradients[mid*n_points_1d+col];
+ val0 = this->data.shape_gradients[mid*mm+col];
else
- val0 = this->data.shape_gradients[col*n_points_1d+mid];
+ val0 = this->data.shape_gradients[col*mm+mid];
val1 = val0 * in[stride*mid];
res0 += val1;
res1 -= val1;
}
if ( nn%2 == 1 )
{
- vector_t val0, res0;
+ VectorizedArray<Number> val0, res0;
if (dof_to_quad == true)
val0 = this->data.shape_gradients[n_cols];
else
- val0 = this->data.shape_gradients[n_cols*n_points_1d];
+ val0 = this->data.shape_gradients[n_cols*mm];
if (mid > 0)
{
res0 = in[0] - in[stride*(mm-1)];
for (int ind=1; ind<mid; ++ind)
{
if (dof_to_quad == true)
- val0 = this->data.shape_gradients[ind*n_points_1d+n_cols];
+ val0 = this->data.shape_gradients[ind*mm+n_cols];
else
- val0 = this->data.shape_gradients[n_cols*n_points_1d+ind];
- vector_t val1 = in[stride*ind] - in[stride*(mm-1-ind)];
+ val0 = this->data.shape_gradients[n_cols*mm+ind];
+ VectorizedArray<Number> val1 = in[stride*ind] - in[stride*(mm-1-ind)];
val1 *= val0;
res0 += val1;
}
}
else
- res0 = vector_t();
+ res0 = VectorizedArray<Number>();
if (add == false)
out[stride*n_cols] = res0;
else
namespace MatrixFreeFunctions
{
// forward declaration of internal data structure
- namespace internal
- {
- template <typename Number> struct ConstraintValues;
- }
-
-
- // set minimum grain size for parallel
- // computations
- namespace internal
- {
- const unsigned int minimum_parallel_grain_size = 500;
- }
-
-
- /*
- * Compressed data type to store a two
- * dimensional array. The data is stored in
- * a single standard vector. In a second
- * vector, the first element belonging to
- * each row is stored.
- */
- template<typename T>
- struct CompressedMatrix
- {
- AlignedVector<T> data;
- std::vector<unsigned int> row_index;
- T* operator[] (const unsigned int row) {
- return begin(row);
- };
- const T* operator[] (const unsigned int row) const {
- return begin(row);
- };
- const T* begin(const unsigned int row) const {
- AssertIndexRange (row, row_index.size()-1);
- return data.begin() + row_index[row];
- };
- const T* end(const unsigned int row) const {
- AssertIndexRange (row, row_index.size()-1);
- return data.begin() + row_index[row+1];
- };
- unsigned int row_length (const unsigned int row) const {
- AssertIndexRange (row, row_index.size()-1);
- return row_index[row+1] - row_index[row];
- };
- T* begin(const unsigned int row) {
- AssertIndexRange (row, row_index.size()-1);
- return data.begin() + row_index[row];
- };
- T* end(const unsigned int row) {
- AssertIndexRange (row, row_index.size()-1);
- return data.begin() + row_index[row+1];
- };
- void complete_last_row() {
- row_index.push_back (data.size());
- }
- void swap (CompressedMatrix<T> &other) {
- data.swap (other.data);
- row_index.swap (other.row_index);
- }
- void print (std::ostream &out) const
- {
- for (unsigned int row=0; row<row_index.size(); ++row)
- {
- for (const T* iterator=begin(row); iterator != end(row); ++iterator)
- out << *iterator << " ";
- out << std::endl;
- }
- };
- void clear()
- {
- data.clear();
- row_index.clear();
- }
- unsigned int memory_consumption() const
- {
- return MemoryConsumption::memory_consumption(data)+
- MemoryConsumption::memory_consumption(row_index);
- };
- };
+ template <typename Number> struct ConstraintValues;
/**
* A struct that collects all information
/**
* Constructor.
*/
- TaskInfo ()
- {
- clear();
- }
+ TaskInfo ();
/**
* Clears all the data fields and resets them
* to zero.
*/
- void clear ()
- {
- block_size = 0;
- n_blocks = 0;
- block_size_last = 0;
- position_short_block = 0;
- use_multithreading = false;
- use_partition_partition = false;
- use_coloring_only = false;
- partition_color_blocks.clear();
- evens = 0;
- odds = 0;
- n_blocked_workers = 0;
- n_workers = 0;
- partition_evens.clear();
- partition_odds.clear();
- partition_n_blocked_workers.clear();
- partition_n_workers.clear();
- }
+ void clear ();
- std::size_t memory_consumption () const
- {
- return (MemoryConsumption::memory_consumption (partition_color_blocks) +
- MemoryConsumption::memory_consumption (partition_evens) +
- MemoryConsumption::memory_consumption (partition_odds) +
- MemoryConsumption::memory_consumption (partition_n_blocked_workers) +
- MemoryConsumption::memory_consumption (partition_n_workers));
- }
+ /**
+ * Returns the memory consumption of
+ * the class.
+ */
+ std::size_t memory_consumption () const;
unsigned int block_size;
unsigned int n_blocks;
bool use_partition_partition;
bool use_coloring_only;
- CompressedMatrix<unsigned int> partition_color_blocks;
+ std::vector<unsigned int> partition_color_blocks_row_index;
+ std::vector<unsigned int> partition_color_blocks_data;
unsigned int evens;
unsigned int odds;
unsigned int n_blocked_workers;
/**
* Constructor.
*/
- SizeInfo ()
- {
- clear();
- }
+ SizeInfo ();
/**
* Clears all data fields and resets the sizes
* to zero.
*/
- void clear()
- {
- n_active_cells = 0;
- n_macro_cells = 0;
- boundary_cells_start = 0;
- boundary_cells_end = 0;
- n_vectors = 0;
- locally_owned_cells = IndexSet();
- ghost_cells = IndexSet();
- communicator = MPI_COMM_SELF;
- my_pid = 0;
- n_procs = 0;
- }
-
+ void clear();
+
+ /**
+ * Prints minimum, average, and
+ * maximal memory consumption over the
+ * MPI processes.
+ */
template <typename STREAM>
- void print_mem (STREAM &out,
- std::size_t data_length) const
- {
- Utilities::MPI::MinMaxAvg memory_c;
- if (Utilities::System::job_supports_mpi() == true)
- {
- memory_c = Utilities::MPI::min_max_avg (1e-6*data_length,
- communicator);
- }
- else
- {
- memory_c.sum = 1e-6*data_length;
- memory_c.min = memory_c.sum;
- memory_c.max = memory_c.sum;
- memory_c.avg = memory_c.sum;
- memory_c.min_index = 0;
- memory_c.max_index = 0;
- }
- if (n_procs < 2)
- out << memory_c.min;
- else
- out << memory_c.min << "/" << memory_c.avg << "/" << memory_c.max;
- out << " MB" << std::endl;
- }
+ void print_memory_statistics (STREAM &out,
+ std::size_t data_length) const;
+ /**
+ * Determines the position of cells
+ * with ghosts for distributed-memory
+ * calculations.
+ */
void make_layout (const unsigned int n_active_cells_in,
- const unsigned int n_boundary_cells,
- const unsigned int n_vectors_in,
- std::vector<unsigned int> &irregular_cells)
- {
- n_vectors = n_vectors_in;
- n_active_cells = n_active_cells_in;
-
- // check that number of boundary cells is
- // divisible by n_vectors or that it contains
- // all cells
- Assert (n_boundary_cells % n_vectors == 0 ||
- n_boundary_cells == n_active_cells, ExcInternalError());
- n_macro_cells = (n_active_cells+n_vectors-1)/n_vectors;
- irregular_cells.resize (n_macro_cells);
- if (n_macro_cells*n_vectors > n_active_cells)
- {
- irregular_cells[n_macro_cells-1] =
- n_vectors - (n_macro_cells*n_vectors - n_active_cells);
- }
- if (n_procs > 1)
- {
- const unsigned int n_macro_boundary_cells =
- (n_boundary_cells+n_vectors-1)/n_vectors;
- boundary_cells_start = (n_macro_cells-n_macro_boundary_cells)/2;
- boundary_cells_end = boundary_cells_start + n_macro_boundary_cells;
- }
- else
- boundary_cells_start = boundary_cells_end = n_macro_cells;
- }
+ const unsigned int vectorization_length_in,
+ std::vector<unsigned int> &boundary_cells,
+ std::vector<unsigned int> &irregular_cells);
unsigned int n_active_cells;
unsigned int n_macro_cells;
unsigned int boundary_cells_start;
unsigned int boundary_cells_end;
- unsigned int n_vectors;
+ unsigned int vectorization_length;
/**
* index sets to describe the layout of cells:
unsigned int n_procs;
};
+ /**
+ * Data type to identify cell type.
+ */
+ enum CellType {cartesian=0, affine=1, general=2, undefined=3};
-
- namespace internal
- {
- // ----------------- hash structure --------------------------------
+ // ----------------- hash structure --------------------------------
/**
* A class that is
* easily detected (unless roundoff spoils the
* hash function)
*/
- struct HashValue
- {
+ struct HashValue
+ {
// Constructor: sets the size of Number values
// with the typical magnitude that is to be
// expected.
- HashValue (const double element_size = 1.)
- :
- scaling (element_size * std::numeric_limits<double>::epsilon() *
- 1024.)
- {};
-
+ HashValue (const double element_size = 1.);
+
// get hash value for a vector of floating
// point numbers (which are assumed to be of
// order of magnitude one). Do this by first
// the scaling (in order to eliminate noise
// from roundoff errors) and then calling the
// boost hash function
- unsigned int operator ()(const std::vector<double> &vec)
- {
- std::vector<double> mod_vec(vec);
- for (unsigned int i=0; i<mod_vec.size(); ++i)
- mod_vec[i] -= fmod (mod_vec[i], scaling);
- return static_cast<unsigned int>(boost::hash_range (mod_vec.begin(), mod_vec.end()));
- };
+ unsigned int operator ()(const std::vector<double> &vec);
// get hash value for a tensor of rank
// two where the magnitude of the
// entries is given by the parameter
// weight
- template <int dim, typename number>
- unsigned int operator ()(const Tensor<2,dim,VectorizedArray<number> > &input,
- const bool is_diagonal)
- {
- const unsigned int n_vectors = VectorizedArray<number>::n_array_elements;
-
- if (is_diagonal)
- {
- number mod_tensor [dim][n_vectors];
- for (unsigned int i=0; i<dim; ++i)
- for (unsigned int j=0; j<n_vectors; ++j)
- mod_tensor[i][j] = input[i][i][j] - fmod (input[i][i][j],
- number(scaling));
- return static_cast<unsigned int>(boost::hash_range
- (&mod_tensor[0][0],
- &mod_tensor[0][0]+dim*n_vectors));
- }
- else
- {
- number mod_tensor [dim][dim][n_vectors];
- for (unsigned int i=0; i<dim; ++i)
- for (unsigned int d=0; d<dim; ++d)
- for (unsigned int j=0; j<n_vectors; ++j)
- mod_tensor[i][d][j] = input[i][d][j] - fmod (input[i][d][j],
- number(scaling));
- return static_cast<unsigned int>(boost::hash_range
- (&mod_tensor[0][0][0],
- &mod_tensor[0][0][0]+
- dim*dim*n_vectors));
- }
- };
-
- const double scaling;
- };
+ template <int dim, typename number>
+ unsigned int operator ()(const Tensor<2,dim,VectorizedArray<number> >
+ &input,
+ const bool is_diagonal);
+
+
+ const double scaling;
+ };
- } // end of namespace internal
+ // Note: Implementation in matrix_free.templates.h
} // end of namespace MatrixFreeFunctions
} // end of namespace internal
template <int dim, typename Number>
struct MappingInfo
{
- typedef VectorizedArray<Number> vector_t;
- typedef Point<dim,vector_t> point;
- typedef Tensor<1,dim,vector_t> tensor1;
- typedef Tensor<2,dim,vector_t> tensor2;
- typedef Tensor<3,dim,vector_t> tensor3;
- typedef Tensor<1,(dim>1?dim*(dim-1)/2:1),Tensor<1,dim,vector_t> > tensorUT;
- static const std::size_t n_vectors
- = VectorizedArray<Number>::n_array_elements;
-
/**
* Determines how many bits of an unsigned int
* are used to distinguish the cell types
* Returns the type of a given cell as
* detected during initialization.
*/
- unsigned int get_cell_type (const unsigned int cell_chunk_no) const
- {
- AssertIndexRange (cell_chunk_no, cell_type.size());
- return cell_type[cell_chunk_no] % n_cell_types;
- };
+ CellType get_cell_type (const unsigned int cell_chunk_no) const;
/**
* Returns the type of a given cell as
* detected during initialization.
*/
- unsigned int get_cell_data_index (const unsigned int cell_chunk_no) const
- {
- AssertIndexRange (cell_chunk_no, cell_type.size());
- return cell_type[cell_chunk_no] >> n_cell_type_bits;
- };
+ unsigned int get_cell_data_index (const unsigned int cell_chunk_no) const;
/**
* Clears all data fields in this class.
* quadrature point, whereas the determinant
* is the same on each quadrature point).
*/
- AlignedVector<std::pair<tensor1,vector_t> > cartesian;
+ AlignedVector<std::pair<Tensor<1,dim,VectorizedArray<Number> >,
+ VectorizedArray<Number> > > cartesian_data;
/**
* The first field stores the Jacobian for
* the determinant is the same on each
* quadrature point).
*/
- AlignedVector<std::pair<tensor2,vector_t> > linear;
+ AlignedVector<std::pair<Tensor<2,dim,VectorizedArray<Number> >,
+ VectorizedArray<Number> > > affine_data;
/**
* Definition of a structure that stores data
* FEValues::inverse_jacobian) for general
* cells.
*/
- AlignedVector<tensor2> jacobians;
+ AlignedVector<Tensor<2,dim,VectorizedArray<Number> > > jacobians;
/**
* This field stores the Jacobian
* determinant times the quadrature weights
* (JxW in deal.II speak) for general cells.
*/
- AlignedVector<vector_t> JxW_values;
+ AlignedVector<VectorizedArray<Number> > JxW_values;
/**
* Stores the diagonal part of the gradient of
* x_i \partial x_j, i\neq j$ because that is
* only needed for computing a full Hessian.
*/
- AlignedVector<tensor2> jacobians_grad_diag;
+ AlignedVector<Tensor<2,dim,VectorizedArray<Number> > > jacobians_grad_diag;
/**
* Stores the off-diagonal part of the
* so on. The second index is the spatial
* coordinate. Not filled currently.
*/
- AlignedVector<tensorUT> jacobians_grad_upper;
+ AlignedVector<Tensor<1,(dim>1?dim*(dim-1)/2:1),
+ Tensor<1,dim,VectorizedArray<Number> > > > jacobians_grad_upper;
/**
* Stores the row start for quadrature points
* coordinates for Cartesian cells (does not
* need to store the full data on all points)
*/
- AlignedVector<point> quadrature_points;
+ AlignedVector<Point<dim,VectorizedArray<Number> > > quadrature_points;
/**
* The dim-dimensional quadrature formula
* The quadrature weights (vectorized data
* format) on the unit cell.
*/
- std::vector<AlignedVector<vector_t> > quadrature_weights;
+ std::vector<AlignedVector<VectorizedArray<Number> > > quadrature_weights;
/**
* This variable stores the number of
* given degree is actually present.
*/
unsigned int
- quad_index_from_n_q_points (const unsigned int n_q_points) const
- {
- for (unsigned int i=0; i<quad_index_conversion.size(); ++i)
- if (n_q_points == quad_index_conversion[i])
- return i;
- return 0;
- }
+ quad_index_from_n_q_points (const unsigned int n_q_points) const;
/**
*/
struct CellData
{
- CellData (const double jac_size_in) :
- jac_size (jac_size_in) {}
-
- void resize (const unsigned int size)
- {
- if (general_jac.size() != size)
- {
- quadrature_points.resize(size);
- general_jac.resize(size);
- general_jac_grad.resize(size);
- }
- }
-
- AlignedVector<tensor1> quadrature_points;
- AlignedVector<tensor2> general_jac;
- AlignedVector<tensor3> general_jac_grad;
- tensor2 const_jac;
- const double jac_size;
+ CellData (const double jac_size);
+ void resize (const unsigned int size);
+
+ AlignedVector<Tensor<1,dim,VectorizedArray<Number> > > quadrature_points;
+ AlignedVector<Tensor<2,dim,VectorizedArray<Number> > > general_jac;
+ AlignedVector<Tensor<3,dim,VectorizedArray<Number> > > general_jac_grad;
+ Tensor<2,dim,VectorizedArray<Number> > const_jac;
+ const double jac_size;
};
/**
const std::pair<unsigned int,unsigned int> *cells,
const unsigned int cell,
const unsigned int my_q,
- unsigned int (&cell_t_prev)[n_vectors],
- unsigned int (&cell_t)[n_vectors],
+ CellType (&cell_t_prev)[VectorizedArray<Number>::n_array_elements],
+ CellType (&cell_t)[VectorizedArray<Number>::n_array_elements],
FEValues<dim,dim> &fe_values,
CellData &cell_data) const;
};
+
+
+ /* ------------------- inline functions ----------------------------- */
+
+ template <int dim, typename Number>
+ inline
+ unsigned int
+ MappingInfo<dim,Number>::MappingInfoDependent::
+ quad_index_from_n_q_points (const unsigned int n_q_points) const
+ {
+ for (unsigned int i=0; i<quad_index_conversion.size(); ++i)
+ if (n_q_points == quad_index_conversion[i])
+ return i;
+ return 0;
+ }
+
+
+
+ template <int dim, typename Number>
+ inline
+ CellType
+ MappingInfo<dim,Number>::get_cell_type (const unsigned int cell_no) const
+ {
+ AssertIndexRange (cell_no, cell_type.size());
+ CellType enum_cell_type = (CellType)(cell_type[cell_no] % n_cell_types);
+ Assert(enum_cell_type != undefined, ExcInternalError());
+ return enum_cell_type;
+ }
+
+
+
+ template <int dim, typename Number>
+ inline
+ unsigned int
+ MappingInfo<dim,Number>::get_cell_data_index (const unsigned int cell_no) const
+ {
+ AssertIndexRange (cell_no, cell_type.size());
+ return cell_type[cell_no] >> n_cell_type_bits;
+ }
+
} // end of namespace MatrixFreeFunctions
} // end of namespace internal
second_derivatives_initialized = false;
mapping_data_gen.clear();
cell_type.clear();
- cartesian.clear();
- linear.clear();
+ cartesian_data.clear();
+ affine_data.clear();
}
clear();
const unsigned int n_quads = quad.size();
const unsigned int n_cells = cells.size();
- Assert (n_cells%n_vectors == 0, ExcInternalError());
- const unsigned int n_macro_cells = n_cells/n_vectors;
+ const unsigned int vectorization_length =
+ VectorizedArray<Number>::n_array_elements;
+ Assert (n_cells%vectorization_length == 0, ExcInternalError());
+ const unsigned int n_macro_cells = n_cells/vectorization_length;
mapping_data_gen.resize (n_quads);
cell_type.resize (n_macro_cells);
const double jacobian_size = internal::get_jacobian_size(tria);
// objects that hold the data for up to
- // n_vectors cells while we fill them up. Only
- // after all n_vectors cells have been
+ // vectorization_length cells while we fill them up. Only
+ // after all vectorization_length cells have been
// processed, we can insert the data into the
// data structures of this class
CellData data (jacobian_size);
if (cells.size() == 0)
continue;
- tensor3 jac_grad, grad_jac_inv;
- tensor1 tmp;
+ Tensor<3,dim,VectorizedArray<Number> > jac_grad, grad_jac_inv;
+ Tensor<1,dim,VectorizedArray<Number> > tmp;
// encodes the cell types of the current
// cell. Since several cells must be
// considered together, this variable holds
// the individual info of the last chunk of
// cells
- unsigned int cell_t [n_vectors], cell_t_prev [n_vectors];
- for (unsigned int j=0; j<n_vectors; ++j)
- cell_t_prev[j] = numbers::invalid_unsigned_int;
+ CellType cell_t [vectorization_length],
+ cell_t_prev [vectorization_length];
+ for (unsigned int j=0; j<vectorization_length; ++j)
+ cell_t_prev[j] = undefined;
// fe_values object that is used to compute
// the mapping data. for the hp case there
// similarities between mapping data from one
// cell to the next.
std::vector<std::pair<unsigned int, int> > hash_collection;
- internal::HashValue hash_value (jacobian_size);
+ HashValue hash_value (jacobian_size);
// loop over all cells
for (unsigned int cell=0; cell<n_macro_cells; ++cell)
{
// GENERAL OUTLINE: First generate the data in
- // format "number" for n_vectors cells, and
+ // format "number" for vectorization_length cells, and
// then find the most general type of cell for
// appropriate vectorized formats. then fill
// this data in
// similarity due to some cells further ahead)
if (cell > 0 && active_fe_index.size() > 0 &&
active_fe_index[cell] != active_fe_index[cell-1])
- cell_t_prev[n_vectors-1] = numbers::invalid_unsigned_int;
- evaluate_on_cell (tria, &cells[cell*n_vectors],
+ cell_t_prev[vectorization_length-1] = undefined;
+ evaluate_on_cell (tria, &cells[cell*vectorization_length],
cell, my_q, cell_t_prev, cell_t, fe_val, data);
// now reorder the data into vectorized
// types. if we are here for the first time,
// we need to find out whether the Jacobian
// allows for some simplification (Cartesian,
- // linear) taking n_vectors cell together and
+ // affine) taking vectorization_length cell together and
// we have to insert that data into the
// respective fields. Also, we have to
// compress different cell indicators into one
{
// find the most general cell type (most
// general type is 2 (general cell))
- unsigned int most_general_type = 0;
- for (unsigned int j=0; j<n_vectors; ++j)
+ CellType most_general_type = cartesian;
+ for (unsigned int j=0; j<vectorization_length; ++j)
if (cell_t[j] > most_general_type)
most_general_type = cell_t[j];
AssertIndexRange (most_general_type, 3);
// Jacobian determinant
unsigned int insert_position = numbers::invalid_unsigned_int;
typedef std::vector<std::pair<unsigned int,int> >::iterator iter;
- if (most_general_type == 0)
+ if (most_general_type == cartesian)
{
- std::pair<tensor1,vector_t> new_entry;
+ std::pair<Tensor<1,dim,VectorizedArray<Number> >,
+ VectorizedArray<Number> > new_entry;
for (unsigned int d=0; d<dim; ++d)
new_entry.first[d] = data.const_jac[d][d];
- insert_position = cartesian.size();
+ insert_position = cartesian_data.size();
// check whether everything is the same as on
// another cell before. find an insertion point
pos->first == hash)
{
for (unsigned int d=0; d<dim; ++d)
- for (unsigned int j=0; j<n_vectors; ++j)
+ for (unsigned int j=0; j<vectorization_length; ++j)
if (std::fabs(data.const_jac[d][d][j]-
- cartesian[-pos->second].first[d][j])>
+ cartesian_data[-pos->second].first[d][j])>
hash_value.scaling)
duplicate = false;
}
if (duplicate == false)
{
hash_collection.insert (pos, insertion);
- cartesian.push_back (new_entry);
+ cartesian_data.push_back (new_entry);
}
// else, remember the position
else
// Constant Jacobian case. same strategy as
// before, but with other data fields
- else if (most_general_type == 1)
+ else if (most_general_type == affine)
{
- insert_position = linear.size();
+ insert_position = affine_data.size();
// check whether everything is the same as on
// the previous cell
{
for (unsigned int d=0; d<dim; ++d)
for (unsigned int e=0; e<dim; ++e)
- for (unsigned int j=0; j<n_vectors; ++j)
+ for (unsigned int j=0; j<vectorization_length; ++j)
if (std::fabs(data.const_jac[d][e][j]-
- linear[-pos->second].first[d][e][j])>
+ affine_data[-pos->second].first[d]
+ [e][j])>
hash_value.scaling)
duplicate = false;
}
if (duplicate == false)
{
hash_collection.insert (pos, insertion);
- linear.push_back (std::pair<tensor2,vector_t>(data.const_jac,
- make_vectorized_array (Number(0.))));
+ affine_data.push_back
+ (std::pair<Tensor<2,dim,VectorizedArray<Number> >,
+ VectorizedArray<Number> >(data.const_jac,
+ make_vectorized_array
+ (Number(0.))));
}
else
insert_position = -pos->second;
// here involves at most one reallocation.
else
{
- Assert (most_general_type == 2, ExcInternalError());
+ Assert (most_general_type == general, ExcInternalError());
insert_position = current_data.rowstart_jacobians.size();
if (current_data.rowstart_jacobians.size() == 0)
{
}
cell_type[cell] = ((insert_position << n_cell_type_bits) +
- most_general_type);
+ (unsigned int)most_general_type);
} // end if (my_q == 0)
// quadrature points and collect the
// data. done for all different quadrature
// formulas, so do it outside the above loop.
- if (get_cell_type(cell) == 2)
+ if (get_cell_type(cell) == general)
{
const unsigned int previous_size =
current_data.jacobians.size();
}
for (unsigned int q=0; q<n_q_points; ++q)
{
- tensor2 &jac = data.general_jac[q];
- tensor3 &jacobian_grad = data.general_jac_grad[q];
- for (unsigned int j=0; j<n_vectors; ++j)
- if (cell_t[j] < 2)
+ Tensor<2,dim,VectorizedArray<Number> > &jac = data.general_jac[q];
+ Tensor<3,dim,VectorizedArray<Number> > &jacobian_grad = data.general_jac_grad[q];
+ for (unsigned int j=0; j<vectorization_length; ++j)
+ if (cell_t[j] == cartesian || cell_t[j] == affine)
{
for (unsigned int d=0; d<dim; ++d)
for (unsigned int e=0; e<dim; ++e)
}
}
- const vector_t det = determinant (jac);
+ const VectorizedArray<Number> det = determinant (jac);
current_data.jacobians.push_back (transpose(invert(jac)));
- const tensor2 &inv_jac = current_data.jacobians.back();
+ const Tensor<2,dim,VectorizedArray<Number> > &inv_jac = current_data.jacobians.back();
// TODO: deal.II does not use abs on
// determinants. Is there an assumption
{
for (unsigned int f=0; f<dim; ++f)
{
- tmp[f] = vector_t();
+ tmp[f] = VectorizedArray<Number>();
for (unsigned int g=0; g<dim; ++g)
tmp[f] -= jac_grad[d][f][g] * inv_jac[g][e];
}
}
{
- vector_t grad_diag[dim][dim];
+ VectorizedArray<Number> grad_diag[dim][dim];
for (unsigned int d=0; d<dim; ++d)
for (unsigned int e=0; e<dim; ++e)
grad_diag[d][e] = grad_jac_inv[d][d][e];
current_data.jacobians_grad_diag.push_back
- (Tensor<2,dim,vector_t>(grad_diag));
+ (Tensor<2,dim,VectorizedArray<Number> >(grad_diag));
}
// sets upper-diagonal part of Jacobian
- tensorUT grad_upper;
+ Tensor<1,(dim>1?dim*(dim-1)/2:1),Tensor<1,dim,VectorizedArray<Number> > > grad_upper;
for (unsigned int d=0, count=0; d<dim; ++d)
for (unsigned int e=d+1; e<dim; ++e, ++count)
for (unsigned int f=0; f<dim; ++f)
current_data.quadrature_points.size();
current_data.rowstart_q_points[cell] = old_size;
- tensor1 quad_point;
+ Tensor<1,dim,VectorizedArray<Number> > quad_point;
- if (get_cell_type(cell) == 0)
+ if (get_cell_type(cell) == cartesian)
{
current_data.quadrature_points.resize (old_size+
n_q_points_1d[fe_index]);
current_data.rowstart_q_points[n_macro_cells] =
current_data.quadrature_points.size();
- // finally, need to invert and transpose the
- // Jacobians in the cartesian and linear
+ // finally, need to invert and
+ // transpose the Jacobians in the
+ // cartesian_data and affine_data
// fields and compute the JxW value.
if (my_q == 0)
{
- for (unsigned int i=0; i<cartesian.size(); ++i)
+ for (unsigned int i=0; i<cartesian_data.size(); ++i)
{
- vector_t det = cartesian[i].first[0];
+ VectorizedArray<Number> det = cartesian_data[i].first[0];
for (unsigned int d=1; d<dim; ++d)
- det *= cartesian[i].first[d];
+ det *= cartesian_data[i].first[d];
for (unsigned int d=0; d<dim; ++d)
- cartesian[i].first[d] = 1./cartesian[i].first[d];
- cartesian[i].second = std::abs(det);
+ cartesian_data[i].first[d] = 1./cartesian_data[i].first[d];
+ cartesian_data[i].second = std::abs(det);
}
- for (unsigned int i=0; i<linear.size(); ++i)
+ for (unsigned int i=0; i<affine_data.size(); ++i)
{
- vector_t det = determinant(linear[i].first);
- linear[i].first = transpose(invert(linear[i].first));
- linear[i].second = std::abs(det);
+ VectorizedArray<Number> det = determinant(affine_data[i].first);
+ affine_data[i].first = transpose(invert(affine_data[i].first));
+ affine_data[i].second = std::abs(det);
}
}
}
const std::pair<unsigned int,unsigned int> *cells,
const unsigned int cell,
const unsigned int my_q,
- unsigned int (&cell_t_prev)[n_vectors],
- unsigned int (&cell_t)[n_vectors],
+ CellType (&cell_t_prev)[VectorizedArray<Number>::n_array_elements],
+ CellType (&cell_t)[VectorizedArray<Number>::n_array_elements],
FEValues<dim,dim> &fe_val,
CellData &data) const
{
+ const unsigned int vectorization_length =
+ VectorizedArray<Number>::n_array_elements;
const unsigned int n_q_points = fe_val.n_quadrature_points;
const UpdateFlags update_flags = fe_val.get_update_flags();
// not have that field here)
const double zero_tolerance_double = data.jac_size *
std::numeric_limits<double>::epsilon() * 1024.;
- for (unsigned int j=0; j<n_vectors; ++j)
+ for (unsigned int j=0; j<vectorization_length; ++j)
{
typename dealii::Triangulation<dim>::cell_iterator
cell_it (&tria, cells[j].first, cells[j].second);
fe_val.reinit(cell_it);
- cell_t[j] = numbers::invalid_unsigned_int;
+ cell_t[j] = undefined;
// extract quadrature points and store them
// temporarily. if we have Cartesian cells, we
// and we already have determined that this
// cell is either Cartesian or with constant
// Jacobian, we have nothing more to do.
- if (my_q > 0 && get_cell_type(cell) < 2)
+ if (my_q > 0 && (get_cell_type(cell) == cartesian
+ || get_cell_type(cell) == affine) )
continue;
// first round: if the transformation is
if (j==0)
{
Assert (cell>0, ExcInternalError());
- cell_t[j] = cell_t_prev[n_vectors-1];
+ cell_t[j] = cell_t_prev[vectorization_length-1];
}
else
cell_t[j] = cell_t[j-1];
// check whether the Jacobian is constant on
// this cell the first time we come around
// here
- if (cell_t[j] == numbers::invalid_unsigned_int)
+ if (cell_t[j] == undefined)
{
bool jacobian_constant = true;
for (unsigned int q=1; q<n_q_points; ++q)
}
// set cell type
if (cell_cartesian == true)
- cell_t[j] = 0;
+ cell_t[j] = cartesian;
else if (jacobian_constant == true)
- cell_t[j] = 1;
+ cell_t[j] = affine;
else
- cell_t[j] = 2;
+ cell_t[j] = general;
}
// Cartesian cell
- if (cell_t[j] == 0)
+ if (cell_t[j] == cartesian)
{
// set Jacobian into diagonal and clear
// off-diagonal part
continue;
}
- // cell with linear mapping
- else if (cell_t[j] == 1)
+ // cell with affine mapping
+ else if (cell_t[j] == affine)
{
// compress out very small values
for (unsigned int d=0; d<dim; ++d)
data.general_jac_grad[q][d][e][f][j] = jacobian_grad[d][e][f];
}
}
- } // end loop over all entries in vectorization (n_vectors cells)
+ } // end loop over all entries in vectorization (vectorization_length cells)
// set information for next cell
- for (unsigned int j=0; j<n_vectors; ++j)
+ for (unsigned int j=0; j<vectorization_length; ++j)
cell_t_prev[j] = cell_t[j];
}
+ template <int dim, typename Number>
+ MappingInfo<dim,Number>::CellData::CellData (const double jac_size_in)
+ :
+ jac_size (jac_size_in)
+ {}
+
+
+
+ template <int dim, typename Number>
+ void
+ MappingInfo<dim,Number>::CellData::resize (const unsigned int size)
+ {
+ if (general_jac.size() != size)
+ {
+ quadrature_points.resize(size);
+ general_jac.resize(size);
+ general_jac_grad.resize(size);
+ }
+ }
+
template <int dim, typename Number>
{
std::size_t
memory= MemoryConsumption::memory_consumption (mapping_data_gen);
- memory += MemoryConsumption::memory_consumption (linear);
- memory += MemoryConsumption::memory_consumption (cartesian);
+ memory += MemoryConsumption::memory_consumption (affine_data);
+ memory += MemoryConsumption::memory_consumption (cartesian_data);
memory += MemoryConsumption::memory_consumption (cell_type);
memory += sizeof (this);
return memory;
(STREAM &out,
const SizeInfo &size_info) const
{
- // print_mem involves global communication, so
- // we can disable the check here only if no
+ // print_memory_statistics involves
+ // global communication, so we can
+ // disable the check here only if no
// processor has any such data
#if DEAL_II_COMPILER_SUPPORTS_MPI
unsigned int general_size_glob = 0, general_size_loc = jacobians.size();
if (general_size_glob > 0)
{
out << " Memory Jacobian data: ";
- size_info.print_mem (out,
- MemoryConsumption::memory_consumption (jacobians)
- +
- MemoryConsumption::memory_consumption (JxW_values));
+ size_info.print_memory_statistics
+ (out, MemoryConsumption::memory_consumption (jacobians) +
+ MemoryConsumption::memory_consumption (JxW_values));
out << " Memory second derivative data: ";
- size_info.print_mem (out,
- MemoryConsumption::memory_consumption (jacobians_grad_diag)
- +
- MemoryConsumption::memory_consumption (jacobians_grad_upper));
+ size_info.print_memory_statistics
+ (out,MemoryConsumption::memory_consumption (jacobians_grad_diag) +
+ MemoryConsumption::memory_consumption (jacobians_grad_upper));
}
#if DEAL_II_COMPILER_SUPPORTS_MPI
if (quad_size_glob > 0)
{
out << " Memory quadrature points: ";
- size_info.print_mem (out,
- MemoryConsumption::memory_consumption (rowstart_q_points)
- +
- MemoryConsumption::memory_consumption (quadrature_points));
+ size_info.print_memory_statistics
+ (out, MemoryConsumption::memory_consumption (rowstart_q_points) +
+ MemoryConsumption::memory_consumption (quadrature_points));
}
}
const SizeInfo &size_info) const
{
out << " Cell types: ";
- size_info.print_mem (out, MemoryConsumption::memory_consumption (cell_type));
+ size_info.print_memory_statistics
+ (out, MemoryConsumption::memory_consumption (cell_type));
out << " Memory transformations compr: ";
- size_info.print_mem (out, MemoryConsumption::memory_consumption (linear) +
- MemoryConsumption::memory_consumption (cartesian));
+ size_info.print_memory_statistics
+ (out, MemoryConsumption::memory_consumption (affine_data) +
+ MemoryConsumption::memory_consumption (cartesian_data));
for (unsigned int j=0; j<mapping_data_gen.size(); ++j)
{
out << " Data component " << j << std::endl;
#include <deal.II/hp/dof_handler.h>
#include <deal.II/hp/q_collection.h>
#include <deal.II/matrix_free/helper_functions.h>
-#include <deal.II/matrix_free/fe_evaluation_data.h>
+#include <deal.II/matrix_free/shape_info.h>
#include <deal.II/matrix_free/dof_info.h>
#include <deal.II/matrix_free/mapping_info.h>
* matrix-vector products or residual computations on the same
* mesh. The class is used in step-37 and step-48.
*
+ * This class does not implement any operations involving finite element basis
+ * functions, i.e., regarding the operation performed on the cells. For these
+ * operations, the class FEEvaluation is designed to use the data collected in
+ * this class.
+ *
* The stored data can be subdivided into three main components:
*
* - DoFInfo: It stores how local degrees of freedom relate to global degrees
* are necessary in order to build derivatives of finite element functions
* and find location of quadrature weights in physical space.
*
- * - FEEvaluationData: It contains the shape functions of the finite element,
+ * - ShapeInfo: It contains the shape functions of the finite element,
* evaluated on the unit cell.
*
* Besides the initialization routines, this class implements only a
bool initialize_mapping;
};
+ /**
+ * @name 1: Construction and initialization
+ */
+ //@{
/**
* Default empty constructor. Does
* nothing.
*/
void clear();
+ //@}
+
+ /**
+ * @name 2: Loop over cells
+ */
+ //@{
/**
* This method runs the loop over all
* cells (in parallel) and performs
const InVector &src) const;
/**
- * Returns an approximation of the memory
- * consumption of this class in bytes.
+ * In the hp adaptive case, a subrange of
+ * cells as computed during the cell loop
+ * might contain elements of different
+ * degrees. Use this function to compute what
+ * the subrange for an individual finite
+ * element degree is. The finite element
+ * degree is associated to the vector
+ * component given in the function call.
*/
- std::size_t memory_consumption() const;
+ std::pair<unsigned int,unsigned int>
+ create_cell_subrange_hp (const std::pair<unsigned int,unsigned int> &range,
+ const unsigned int fe_degree,
+ const unsigned int vector_component = 0) const;
/**
- * Prints a detailed summary of memory
- * consumption in the different structures of
- * this class to the given output stream.
+ * In the hp adaptive case, a subrange of
+ * cells as computed during the cell loop
+ * might contain elements of different
+ * degrees. Use this function to compute what
+ * the subrange for a given index the hp
+ * finite element, as opposed to the finite
+ * element degree in the other function.
*/
- template <typename STREAM>
- void print_memory_consumption(STREAM &out) const;
+ std::pair<unsigned int,unsigned int>
+ create_cell_subrange_hp_by_index (const std::pair<unsigned int,unsigned int> &range,
+ const unsigned int fe_index,
+ const unsigned int vector_component = 0) const;
+
+ //@}
/**
- * Prints a summary of this class to the given
- * output stream. It is focused on the
- * indices, and does not print all the data
- * stored.
+ * @name 3: Initialization of vectors
*/
- void print (std::ostream &out) const;
-
+ //@{
/**
* Initialize function for a general
* vector. The length of the vector is equal
* to the total number of degrees in the
* DoFHandler. If the vector is of class
- * parallel::distributed::Vector<Number>, the ghost
+ * parallel::distributed::Vector@<Number@>, the ghost
* entries are set accordingly. For
* vector-valued problems with several
* DoFHandlers underlying this class, the
* vector. The length of the vector is equal
* to the total number of degrees in the
* DoFHandler. If the vector is of class
- * parallel::distributed::Vector<Number>, the ghost
+ * parallel::distributed::Vector@<Number@>, the ghost
* entries are set accordingly. For
* vector-valued problems with several
* DoFHandlers underlying this class, the
* Returns the partitioner that represents the
* locally owned data and the ghost indices
* where access is needed to for the cell
- * loop.
+ * loop. The partitioner is constructed from
+ * the locally owned dofs and ghost dofs given
+ * by the respective fields. If you want to
+ * have specific information about these
+ * objects, you can query them with the
+ * respective access functions. If you just
+ * want to initialize a (parallel) vector, you
+ * should usually prefer this data structure
+ * as the data exchange information can be
+ * reused from one vector to another.
*/
const std_cxx1x::shared_ptr<const Utilities::MPI::Partitioner>&
get_vector_partitioner (const unsigned int vector_component=0) const;
+ /**
+ * Returns the set of cells that are
+ * oned by the processor.
+ */
+ const IndexSet &
+ get_locally_owned_set (const unsigned int fe_component = 0) const;
+
+ /**
+ * Returns the set of ghost cells
+ * needed but not owned by the
+ * processor.
+ */
+ const IndexSet &
+ get_ghost_set (const unsigned int fe_component = 0) const;
+
/**
* Returns a list of all degrees of freedom
* that are constrained. The list is returned
const std::vector<unsigned int> &
get_constrained_dofs (const unsigned int fe_component = 0) const;
- /**
- * In the hp adaptive case, a subrange of
- * cells as computed during the cell loop
- * might contain elements of different
- * degrees. Use this function to compute what
- * the subrange for an individual finite
- * element degree is. The finite element
- * degree is associated to the vector
- * component given in the function call.
- */
- std::pair<unsigned int,unsigned int>
- create_cell_subrange_hp (const std::pair<unsigned int,unsigned int> &range,
- const unsigned int fe_degree,
- const unsigned int vector_component = 0) const;
-
- /**
- * In the hp adaptive case, a subrange of
- * cells as computed during the cell loop
- * might contain elements of different
- * degrees. Use this function to compute what
- * the subrange for a given index the hp
- * finite element, as opposed to the finite
- * element degree in the other function.
- */
- std::pair<unsigned int,unsigned int>
- create_cell_subrange_hp_by_index (const std::pair<unsigned int,unsigned int> &range,
- const unsigned int fe_index,
- const unsigned int vector_component = 0) const;
/**
* Calls renumber_dofs function in dof
* info which renumbers the the
void renumber_dofs (std::vector<unsigned int> &renumbering,
const unsigned int vector_component = 0);
- unsigned int n_components () const;
+ //@}
/**
- * Returns information on task graph.
+ * @name 4: General information
*/
- const internal::MatrixFreeFunctions::TaskInfo &
- get_task_info () const;
-
+ //@{
/**
- * Returns information on system size.
+ * Returns the number of different DoFHandlers
+ * specified at initialization.
*/
- const internal::MatrixFreeFunctions::SizeInfo &
- get_size_info () const;
+ unsigned int n_components () const;
/**
* Returns the number of cells this structure
unsigned int n_physical_cells () const;
/**
- * Returns the number of macro cells that this
- * structure works on, i.e., the number of
- * cell chunks that are worked on after the
- * application of vectorization which in
- * general works on several cells at once. The
- * cell range in @p cell_loop runs from zero
- * to n_macro_cells() (exclusive), so this is
- * the appropriate size if you want to store
- * arrays of data for all cells to be worked
- * on. This number is approximately
- * n_physical_cells()/VectorizedArray<Number>::n_array_elements
- * (depending on how many cells are not filled
- * up completely).
+ * Returns the number of macro cells
+ * that this structure works on, i.e.,
+ * the number of cell chunks that are
+ * worked on after the application of
+ * vectorization which in general
+ * works on several cells at once. The
+ * cell range in @p cell_loop runs
+ * from zero to n_macro_cells()
+ * (exclusive), so this is the
+ * appropriate size if you want to
+ * store arrays of data for all cells
+ * to be worked on. This number is
+ * approximately
+ * n_physical_cells()/VectorizedArray@<Number@>::n_array_elements
+ * (depending on how many cell chunks
+ * that do not get filled up
+ * completely).
*/
unsigned int n_macro_cells () const;
- /*
- * Returns geometry-dependent
- * information on the cells.
- */
-
- const internal::MatrixFreeFunctions::MappingInfo<dim,Number> &
- get_mapping_info () const;
-
- /**
- * Returns information on indexation
- * degrees of freedom.
- */
-
- const internal::MatrixFreeFunctions::DoFInfo &
- get_dof_info (const unsigned int fe_component = 0) const;
-
- /*
- * Returns the constraint pool holding
- * all the constraints in the mesh.
- */
-
- const internal::MatrixFreeFunctions::CompressedMatrix<Number> &
- get_constraint_pool () const;
-
/**
* In case this structure was built based on a
* DoFHandler, this returns the
* mixed with deal.II access to cells,
* care needs to be taken. This
* function returns @p true if not all
- * @p n_vectors cells for the given @p
+ * @p vectorization_length cells for the given @p
* macro_cell are real cells. To find
* out how many cells are actually
* used, use the function @p
* vectorization data types correspond
* to real cells in the mesh. For most
* given @p macro_cells, this is just
- * @p n_vectors many, but there might
+ * @p vectorization_length many, but there might
* be one or a few meshes (where the
* numbers do not add up) where there
* are less such components filled,
get_n_q_points_face (const unsigned int quad_index = 0,
const unsigned int hp_active_fe_index = 0) const;
- /**
- * Returns the set of cells that are
- * oned by the processor.
- */
- const IndexSet &
- get_locally_owned_set (const unsigned int fe_component = 0) const;
-
- /**
- * Returns the set of ghost cells
- * needed but not owned by the
- * processor.
- */
- const IndexSet &
- get_ghost_set (const unsigned int fe_component = 0) const;
-
- /**
- * Returns the unit cell information
- * for given hp index.
- */
- const internal::MatrixFreeFunctions::FEEvaluationData<Number> &
- get_fe_evaluation (const unsigned int fe_component = 0,
- const unsigned int quad_index = 0,
- const unsigned int hp_active_fe_index = 0,
- const unsigned int hp_active_quad_index = 0) const;
-
/**
* Returns the quadrature rule for
* given hp index.
bool mapping_initialized () const;
+ /**
+ * Returns an approximation of the memory
+ * consumption of this class in bytes.
+ */
+ std::size_t memory_consumption() const;
+
+ /**
+ * Prints a detailed summary of memory
+ * consumption in the different structures of
+ * this class to the given output stream.
+ */
+ template <typename STREAM>
+ void print_memory_consumption(STREAM &out) const;
+
+ /**
+ * Prints a summary of this class to the given
+ * output stream. It is focused on the
+ * indices, and does not print all the data
+ * stored.
+ */
+ void print (std::ostream &out) const;
+
+ //@}
+
+ /**
+ * @name 5: Access of internal data structure (expert mode)
+ */
+ //@{
+ /**
+ * Returns information on task graph.
+ */
+ const internal::MatrixFreeFunctions::TaskInfo &
+ get_task_info () const;
+
+ /**
+ * Returns information on system size.
+ */
+ const internal::MatrixFreeFunctions::SizeInfo &
+ get_size_info () const;
+
+ /*
+ * Returns geometry-dependent
+ * information on the cells.
+ */
+ const internal::MatrixFreeFunctions::MappingInfo<dim,Number> &
+ get_mapping_info () const;
+
+ /**
+ * Returns information on indexation
+ * degrees of freedom.
+ */
+ const internal::MatrixFreeFunctions::DoFInfo &
+ get_dof_info (const unsigned int fe_component = 0) const;
+
+ /**
+ * Returns a pointer to the first
+ * number in the constraint pool data
+ * with index @p pool_index (to
+ * be used together with @p
+ * constraint_pool_end()).
+ */
+ const Number*
+ constraint_pool_begin (const unsigned int pool_index) const;
+
+ /**
+ * Returns a pointer to one past the
+ * last number in the constraint pool
+ * data with index @p pool_index (to
+ * be used together with @p
+ * constraint_pool_begin()).
+ */
+ const Number*
+ constraint_pool_end (const unsigned int pool_index) const;
+
+ /**
+ * Returns the unit cell information
+ * for given hp index.
+ */
+ const internal::MatrixFreeFunctions::ShapeInfo<Number> &
+ get_shape_info (const unsigned int fe_component = 0,
+ const unsigned int quad_index = 0,
+ const unsigned int hp_active_fe_index = 0,
+ const unsigned int hp_active_quad_index = 0) const;
+
+ //@}
+
private:
- /**
- * This is the actual reinit function
- * that sets up the indices for the
- * DoFHandler and MGDoFHandler case.
- */
+ /**
+ * This is the actual reinit function
+ * that sets up the indices for the
+ * DoFHandler and MGDoFHandler case.
+ */
template <typename DoFHandler>
void internal_reinit (const Mapping<dim> &mapping,
const std::vector<const DoFHandler*> &dof_handler,
const std::vector<hp::QCollection<1> > &quad,
const AdditionalData additional_data);
- /**
- * Same as before but for hp::DoFHandler
- * instead of generic DoFHandler type.
- */
+ /**
+ * Same as before but for hp::DoFHandler
+ * instead of generic DoFHandler type.
+ */
void internal_reinit (const Mapping<dim> &mapping,
const std::vector<const hp::DoFHandler<dim>*> &dof_handler,
const std::vector<const ConstraintMatrix*> &constraint,
const AdditionalData additional_data);
/**
- * Initializes the fields in DoFInfo together
- * with @p constraint_pool.
+ * Initializes the fields in DoFInfo
+ * together with the constraint pool
+ * that holds all different weights in
+ * the constraints (not part of
+ * DoFInfo because several DoFInfo
+ * classes can have the same weights
+ * which consequently only need to be
+ * stored once).
*/
void
initialize_indices (const std::vector<const ConstraintMatrix*> &constraint,
* arguments on DoFInfo and keeps it a plain
* field of indices only.
*/
- internal::MatrixFreeFunctions::CompressedMatrix<Number> constraint_pool;
+ std::vector<Number> constraint_pool_data;
+
+ /**
+ * Contains an indicator to the start
+ * of the ith index in the constraint
+ * pool data.
+ */
+ std::vector<unsigned int> constraint_pool_row_index;
/**
* Holds information on transformation of
* Contains shape value information on the
* unit cell.
*/
- Table<4,internal::MatrixFreeFunctions::FEEvaluationData<Number> > fe_evaluation_data;
+ Table<4,internal::MatrixFreeFunctions::ShapeInfo<Number> > shape_info;
/**
* Describes how the cells are gone
template <int dim, typename Number>
inline
-const internal::MatrixFreeFunctions::CompressedMatrix<Number> &
-MatrixFree<dim,Number>::get_constraint_pool () const
+const Number*
+MatrixFree<dim,Number>::constraint_pool_begin (const unsigned int row) const
+{
+ AssertIndexRange (row, constraint_pool_row_index.size()-1);
+ return &constraint_pool_data[0] + constraint_pool_row_index[row];
+}
+
+
+
+template <int dim, typename Number>
+inline
+const Number*
+MatrixFree<dim,Number>::constraint_pool_end (const unsigned int row) const
{
- return constraint_pool;
+ AssertIndexRange (row, constraint_pool_row_index.size()-1);
+ return &constraint_pool_data[0] + constraint_pool_row_index[row+1];
}
const unsigned int vector_number,
const unsigned int dof_index) const
{
- const unsigned int n_vectors=VectorizedArray<Number>::n_array_elements;
+ const unsigned int vectorization_length=VectorizedArray<Number>::n_array_elements;
#ifdef DEBUG
AssertIndexRange (dof_index, dof_handlers.n_dof_handlers);
AssertIndexRange (macro_cell_number, size_info.n_macro_cells);
- AssertIndexRange (vector_number, n_vectors);
+ AssertIndexRange (vector_number, vectorization_length);
const unsigned int irreg_filled =
std_cxx1x::get<2>(dof_info[dof_index].row_starts[macro_cell_number]);
if (irreg_filled > 0)
}
std::pair<unsigned int,unsigned int> index =
- cell_level_index[macro_cell_number*n_vectors+vector_number];
+ cell_level_index[macro_cell_number*vectorization_length+vector_number];
return typename DoFHandler<dim>::active_cell_iterator
(&dofh->get_tria(), index.first, index.second, dofh);
}
const unsigned int vector_number,
const unsigned int dof_index) const
{
- const unsigned int n_vectors=VectorizedArray<Number>::n_array_elements;
+ const unsigned int vectorization_length=VectorizedArray<Number>::n_array_elements;
#ifdef DEBUG
AssertIndexRange (dof_index, dof_handlers.n_dof_handlers);
AssertIndexRange (macro_cell_number, size_info.n_macro_cells);
- AssertIndexRange (vector_number, n_vectors);
+ AssertIndexRange (vector_number, vectorization_length);
const unsigned int irreg_filled =
std_cxx1x::get<2>(dof_info[dof_index].row_starts[macro_cell_number]);
if (irreg_filled > 0)
const MGDoFHandler<dim> * dofh = dof_handlers.mg_dof_handler[dof_index];
std::pair<unsigned int,unsigned int> index =
- cell_level_index[macro_cell_number*n_vectors+vector_number];
+ cell_level_index[macro_cell_number*vectorization_length+vector_number];
return typename MGDoFHandler<dim>::cell_iterator
(&dofh->get_tria(), index.first, index.second, dofh);
}
const unsigned int vector_number,
const unsigned int dof_index) const
{
- const unsigned int n_vectors=VectorizedArray<Number>::n_array_elements;
+ const unsigned int vectorization_length=VectorizedArray<Number>::n_array_elements;
#ifdef DEBUG
AssertIndexRange (dof_index, dof_handlers.n_dof_handlers);
AssertIndexRange (macro_cell_number, size_info.n_macro_cells);
- AssertIndexRange (vector_number, n_vectors);
+ AssertIndexRange (vector_number, vectorization_length);
const unsigned int irreg_filled =
std_cxx1x::get<2>(dof_info[dof_index].row_starts[macro_cell_number]);
if (irreg_filled > 0)
ExcNotImplemented());
const hp::DoFHandler<dim> * dofh = dof_handlers.hp_dof_handler[dof_index];
std::pair<unsigned int,unsigned int> index =
- cell_level_index[macro_cell_number*n_vectors+vector_number];
+ cell_level_index[macro_cell_number*vectorization_length+vector_number];
return typename hp::DoFHandler<dim>::cell_iterator
(&dofh->get_tria(), index.first, index.second, dofh);
}
template <int dim, typename Number>
inline
-const internal::MatrixFreeFunctions::FEEvaluationData<Number> &
-MatrixFree<dim,Number>::get_fe_evaluation(const unsigned int index_fe,
- const unsigned int index_quad,
- const unsigned int active_fe_index,
- const unsigned int active_quad_index) const
+const internal::MatrixFreeFunctions::ShapeInfo<Number> &
+MatrixFree<dim,Number>::get_shape_info (const unsigned int index_fe,
+ const unsigned int index_quad,
+ const unsigned int active_fe_index,
+ const unsigned int active_quad_index) const
{
- AssertIndexRange (index_fe, fe_evaluation_data.size(0));
- AssertIndexRange (index_quad, fe_evaluation_data.size(1));
- AssertIndexRange (active_fe_index, fe_evaluation_data.size(2));
- AssertIndexRange (active_quad_index, fe_evaluation_data.size(3));
- return fe_evaluation_data(index_fe, index_quad,
- active_fe_index, active_quad_index);
+ AssertIndexRange (index_fe, shape_info.size(0));
+ AssertIndexRange (index_quad, shape_info.size(1));
+ AssertIndexRange (active_fe_index, shape_info.size(2));
+ AssertIndexRange (active_quad_index, shape_info.size(3));
+ return shape_info(index_fe, index_quad,
+ active_fe_index, active_quad_index);
}
tbb::task* execute ()
{
std::pair<unsigned int, unsigned int> cell_range
- (task_info.partition_color_blocks.data[partition],
- task_info.partition_color_blocks.data[partition+1]);
+ (task_info.partition_color_blocks_data[partition],
+ task_info.partition_color_blocks_data[partition+1]);
worker(cell_range);
if(blocked==true)
dummy->spawn (*dummy);
if(false)
{
std::pair<unsigned int, unsigned int> cell_range
- (task_info.partition_color_blocks.data
- [task_info.partition_color_blocks.row_index[partition]],
- task_info.partition_color_blocks.data
- [task_info.partition_color_blocks.row_index[partition+1]]);
+ (task_info.partition_color_blocks_data
+ [task_info.partition_color_blocks_row_index[partition]],
+ task_info.partition_color_blocks_data
+ [task_info.partition_color_blocks_row_index[partition+1]]);
function(cell_range);
}
else
{
worker[j] = new(root->allocate_child())
CellWork<Worker,false>(function,task_info.
- partition_color_blocks.
- row_index[partition]+
- 2*j,task_info);
+ partition_color_blocks_row_index
+ [partition] + 2*j, task_info);
if(j>0)
{
worker[j]->set_ref_count(2);
{
blocked_worker[j] = new(worker[j]->allocate_child())
CellWork<Worker,true>(function,task_info.
- partition_color_blocks.
- row_index[partition]+
- 2*j+1,task_info);
+ partition_color_blocks_row_index
+ [partition] + 2*j+1, task_info);
}
else
{
worker[evens] = new(worker[j]->allocate_child())
CellWork<Worker,false>(function,
task_info.
- partition_color_blocks.
- row_index[partition]+
- 2*j+1,task_info);
+ partition_color_blocks_row_index
+ [partition]+2*j+1,task_info);
worker[j]->spawn(*worker[evens]);
}
else
{};
tbb::task* execute ()
{
- unsigned int lower = task_info.partition_color_blocks.data[partition],
- upper = task_info.partition_color_blocks.data[partition+1];
+ unsigned int lower = task_info.partition_color_blocks_data[partition],
+ upper = task_info.partition_color_blocks_data[partition+1];
parallel_for(tbb::blocked_range<unsigned int>(lower,upper,1),
CellWork<Worker> (worker,task_info));
if(blocked==true)
tbb::empty_task* root = new( tbb::task::allocate_root() ) tbb::empty_task;
root->set_ref_count(evens+1);
unsigned int n_blocked_workers = odds-(odds+evens+1)%2;
- unsigned int n_workers = task_info.partition_color_blocks.data.size()-1-
+ unsigned int n_workers = task_info.partition_color_blocks_data.size()-1-
n_blocked_workers;
std::vector<internal::color::PartitionWork<Worker,false>*> worker(n_workers);
std::vector<internal::color::PartitionWork<Worker,true>*> blocked_worker(n_blocked_workers);
internal::MPIComCompress<OutVector>(dst);
worker_compr->set_ref_count(1);
for (unsigned int part=0;
- part<task_info.partition_color_blocks.row_index.size()-1;part++)
+ part<task_info.partition_color_blocks_row_index.size()-1;part++)
{
spawn_index_new = worker_index;
if(part == 0)
worker[worker_index] = new(root->allocate_child())
internal::color::PartitionWork<Worker,false>(func,slice_index,task_info);
slice_index++;
- for(;slice_index<task_info.partition_color_blocks.row_index[part+1];
+ for(;slice_index<task_info.partition_color_blocks_row_index[part+1];
slice_index++)
{
worker[worker_index]->set_ref_count(1);
worker_index++;
}
part += 1;
- if(part<task_info.partition_color_blocks.row_index.size()-1)
+ if(part<task_info.partition_color_blocks_row_index.size()-1)
{
- if(part<task_info.partition_color_blocks.row_index.size()-2)
+ if(part<task_info.partition_color_blocks_row_index.size()-2)
{
blocked_worker[part/2] = new(worker[worker_index-1]->allocate_child())
internal::color::PartitionWork<Worker,true>(func,slice_index,task_info);
slice_index++;
if(slice_index<
- task_info.partition_color_blocks.row_index[part+1])
+ task_info.partition_color_blocks_row_index[part+1])
{
blocked_worker[part/2]->set_ref_count(1);
worker[worker_index] = new(blocked_worker[part/2]->allocate_child())
continue;
}
}
- for(;slice_index<task_info.partition_color_blocks.row_index[part+1];
+ for(;slice_index<task_info.partition_color_blocks_row_index[part+1];
slice_index++)
{
if(slice_index>
- task_info.partition_color_blocks.row_index[part])
+ task_info.partition_color_blocks_row_index[part])
{
worker[worker_index]->set_ref_count(1);
worker_index++;
internal::update_ghost_values_finish(src);
for (unsigned int color=0;
- color < task_info.partition_color_blocks.row_index[1];
+ color < task_info.partition_color_blocks_row_index[1];
++color)
{
- unsigned int lower = task_info.partition_color_blocks.data[color],
- upper = task_info.partition_color_blocks.data[color+1];
+ unsigned int lower = task_info.partition_color_blocks_data[color],
+ upper = task_info.partition_color_blocks_data[color+1];
parallel_for(tbb::blocked_range<unsigned int>(lower,upper,1),
internal::color::CellWork<Worker>
(func,task_info));
#include <deal.II/distributed/tria.h>
#include <deal.II/matrix_free/matrix_free.h>
-#include <deal.II/matrix_free/fe_evaluation_data.templates.h>
+#include <deal.II/matrix_free/shape_info.templates.h>
#include <deal.II/matrix_free/mapping_info.templates.h>
#include <deal.II/matrix_free/dof_info.templates.h>
clear ();
dof_handlers = v.dof_handlers;
dof_info = v.dof_info;
- constraint_pool = v.constraint_pool;
+ constraint_pool_data = v.constraint_pool_data;
+ constraint_pool_row_index = v.constraint_pool_row_index;
mapping_info = v.mapping_info;
- fe_evaluation_data = v.fe_evaluation_data;
+ shape_info = v.shape_info;
cell_level_index = v.cell_level_index;
task_info = v.task_info;
size_info = v.size_info;
// set dof_indices together with
// constraint_indicator and
- // constraint_pool. It also reorders the way
+ // constraint_pool_data. It also reorders the way
// cells are gone through (to separate cells
// with overlap to other processors from
// others without).
// Hessians for quadrature points.
const unsigned int n_fe = dof_handler.size();
const unsigned int n_quad = quad.size();
- fe_evaluation_data.reinit (TableIndices<4>(n_fe, n_quad, 1, 1));
+ shape_info.reinit (TableIndices<4>(n_fe, n_quad, 1, 1));
for (unsigned int no=0; no<n_fe; no++)
{
const FiniteElement<dim> &fe = dof_handler[no]->get_fe();
for(unsigned int nq =0;nq<n_quad;nq++)
{
AssertDimension (quad[nq].size(), 1);
- fe_evaluation_data(no,nq,0,0).reinit(quad[nq][0], fe.base_element(0));
+ shape_info(no,nq,0,0).reinit(quad[nq][0], fe.base_element(0));
}
}
// set dof_indices together with
// constraint_indicator and
- // constraint_pool. It also reorders the way
+ // constraint_pool_data. It also reorders the way
// cells are gone through (to separate cells
// with overlap to other processors from
// others without).
unsigned int n_quad_in_collection = 0;
for (unsigned int q=0; q<n_quad; ++q)
n_quad_in_collection = std::max (n_quad_in_collection, quad[q].size());
- fe_evaluation_data.reinit (TableIndices<4>(n_components, n_quad,
- n_fe_in_collection,
- n_quad_in_collection));
+ shape_info.reinit (TableIndices<4>(n_components, n_quad,
+ n_fe_in_collection,
+ n_quad_in_collection));
for (unsigned int no=0; no<n_components; no++)
for (unsigned int fe_no=0; fe_no<dof_handler[no]->get_fe().size(); ++fe_no)
{
const FiniteElement<dim> &fe = dof_handler[no]->get_fe()[fe_no];
for(unsigned int nq =0; nq<n_quad; nq++)
for (unsigned int q_no=0; q_no<quad[nq].size(); ++q_no)
- fe_evaluation_data(no,nq,fe_no,q_no).reinit (quad[nq][q_no],
- fe.base_element(0));
+ shape_info(no,nq,fe_no,q_no).reinit (quad[nq][q_no],
+ fe.base_element(0));
}
// Evaluates transformations from unit to real
std::vector<std::vector<unsigned int> > ghost_dofs(n_fe);
std::vector<std::vector<std::vector<unsigned int> > > lexicographic_inv(n_fe);
- internal::MatrixFreeFunctions::internal::ConstraintValues<double> constraint_values;
+ internal::MatrixFreeFunctions::ConstraintValues<double> constraint_values;
std::vector<unsigned int> constraint_indices;
for(unsigned int no=0; no<n_fe; ++no)
ExcMessage ("MatrixFree only works for DoFHandler with one base element"));
const unsigned int n_fe_components = fe.element_multiplicity (0);
- // cache number of finite elements and
- // dofs_per_cell
+ // cache number of finite elements and
+ // dofs_per_cell
dof_info[no].dofs_per_cell.push_back (fe.dofs_per_cell);
dof_info[no].dofs_per_face.push_back (fe.dofs_per_face);
dof_info[no].n_components = n_fe_components;
- // get permutation that gives lexicographic
- // renumbering of the cell dofs
- // renumber (this is necessary for FE_Q, for
- // example, since there the vertex DoFs come
- // first, which is incompatible with the
- // lexicographic ordering necessary to apply
- // tensor products efficiently)
- const FE_Poly<TensorProductPolynomials<dim>,dim,dim> *cast_fe =
+ // get permutation that gives lexicographic
+ // renumbering of the cell dofs
+ // renumber (this is necessary for FE_Q, for
+ // example, since there the vertex DoFs come
+ // first, which is incompatible with the
+ // lexicographic ordering necessary to apply
+ // tensor products efficiently)
+ const FE_Poly<TensorProductPolynomials<dim>,dim,dim> *fe_poly =
dynamic_cast<const FE_Poly<TensorProductPolynomials<dim>,dim,dim>*>
(&fe.base_element(0));
- // This class currently only works for
- // elements derived from
- // FE_Poly<TensorProductPolynomials<dim>,dim,dim>.
- // For any other element, the dynamic cast
- // above will fail and give cast_fe == 0.
- Assert (cast_fe != 0, ExcNotImplemented());
-
- // create a derived finite element that gives
- // us access to the inverse numbering (which
- // we need in order to get a lexicographic
- // ordering of local degrees of freedom)
- const internal::MatrixFreeFunctions::internal::FE_PolyAccess<dim,dim>&fe_acc =
- static_cast<const internal::MatrixFreeFunctions::internal::
- FE_PolyAccess<dim,dim> &>(*cast_fe);
+
+ // This class currently only works for
+ // elements derived from
+ // FE_Poly<TensorProductPolynomials<dim>,dim,dim>.
+ // For any other element, the dynamic cast
+ // above will fail and give fe_poly == 0.
+ Assert (fe_poly != 0, ExcNotImplemented());
if (n_fe_components == 1)
{
- lexicographic_inv[no][fe_index] = fe_acc.get_numbering_inverse();
+ lexicographic_inv[no][fe_index] =
+ fe_poly->get_poly_space_numbering_inverse();
AssertDimension (lexicographic_inv[no][fe_index].size(),
dof_info[no].dofs_per_cell[fe_index]);
}
else
{
- // ok, we have more than one component
+ // ok, we have more than one component
Assert (n_fe_components > 1, ExcInternalError());
- std::vector<unsigned int> scalar_lex=fe_acc.get_numbering();
+ std::vector<unsigned int> scalar_lex =
+ fe_poly->get_poly_space_numbering();
AssertDimension (scalar_lex.size() * n_fe_components,
dof_info[no].dofs_per_cell[fe_index]);
- lexicographic_inv[no][fe_index].resize (dof_info[no].dofs_per_cell[fe_index]);
std::vector<unsigned int> lexicographic (dof_info[no].dofs_per_cell[fe_index]);
for (unsigned int comp=0; comp<n_fe_components; ++comp)
for (unsigned int i=0; i<scalar_lex.size(); ++i)
lexicographic[fe.component_to_system_index(comp,i)]
= scalar_lex.size () * comp + scalar_lex[i];
- // invert numbering
- for (unsigned int i=0; i<lexicographic.size(); ++i)
- lexicographic_inv[no][fe_index][lexicographic[i]] = i;
-
-#ifdef DEBUG
- // check that we got a useful permutation
- lexicographic = lexicographic_inv[no][fe_index];
- std::sort(lexicographic.begin(), lexicographic.end());
- for (unsigned int i=0; i<lexicographic.size(); ++i)
- AssertDimension (lexicographic[i], i);
-#endif
+ // invert numbering
+ lexicographic_inv[no][fe_index] =
+ Utilities::invert_permutation(lexicographic);
}
AssertDimension (lexicographic_inv[no][fe_index].size(),
dof_info[no].dofs_per_cell[fe_index]);
boundary_cells.push_back(counter);
}
- // try to make the number of boundary cells
- // divisible by the number of vectors in
- // vectorization
- const unsigned int n_vectors = VectorizedArray<Number>::n_array_elements;
- {
- unsigned int n_max_boundary_cells = boundary_cells.size();
- unsigned int n_boundary_cells = n_max_boundary_cells;
-
- /*
- // try to balance the number of cells before
- // and after the boundary part on each
- // processor. probably not worth it!
-#if DEAL_II_COMPILER_SUPPORTS_MPI
- MPI_Allreduce (&n_boundary_cells, &n_max_boundary_cells, 1, MPI_UNSIGNED,
- MPI_MAX, size_info.communicator);
-#endif
- if (n_max_boundary_cells > n_active_cells)
- n_max_boundary_cells = n_active_cells;
- */
-
- unsigned int fillup_needed =
- (n_vectors - n_boundary_cells%n_vectors)%n_vectors;
- /*
- if (task_info.use_multithreading == true)
- fillup_needed =
- (n_vectors - n_boundary_cells%n_vectors)%n_vectors;
- else
- fillup_needed = (n_max_boundary_cells +
- (n_vectors - n_max_boundary_cells%n_vectors)%n_vectors -
- n_boundary_cells);
- */
- if (fillup_needed > 0 && n_boundary_cells < n_active_cells)
- {
- // fill additional cells into the list of
- // boundary cells to get a balanced number. Go
- // through the indices successively until we
- // found enough indices
- std::vector<unsigned int> new_boundary_cells;
- new_boundary_cells.reserve (n_max_boundary_cells);
-
- unsigned int next_free_slot = 0, bound_index = 0;
- while (fillup_needed > 0 && bound_index < boundary_cells.size())
- {
- if (next_free_slot < boundary_cells[bound_index])
- {
- // check if there are enough cells to fill
- // with in the current slot
- if (next_free_slot + fillup_needed <= boundary_cells[bound_index])
- {
- for (unsigned int j=boundary_cells[bound_index]-fillup_needed;
- j < boundary_cells[bound_index]; ++j)
- new_boundary_cells.push_back(j);
- fillup_needed = 0;
- }
- // ok, not enough indices, so just take them
- // all up to the next boundary cell
- else
- {
- for (unsigned int j=next_free_slot;
- j<boundary_cells[bound_index]; ++j)
- new_boundary_cells.push_back(j);
- fillup_needed -= boundary_cells[bound_index]-next_free_slot;
- }
- }
- new_boundary_cells.push_back(boundary_cells[bound_index]);
- next_free_slot = boundary_cells[bound_index]+1;
- ++bound_index;
- }
- while (fillup_needed > 0 && (new_boundary_cells.size()==0 ||
- new_boundary_cells.back()<n_active_cells-1))
- new_boundary_cells.push_back(new_boundary_cells.back()+1);
- while (bound_index<boundary_cells.size())
- new_boundary_cells.push_back(boundary_cells[bound_index++]);
-
- boundary_cells.swap(new_boundary_cells);
- }
- }
-
- // set the number of cells
- const unsigned int n_boundary_cells = boundary_cells.size();
- std::sort (boundary_cells.begin(), boundary_cells.end());
+ const unsigned int vectorization_length =
+ VectorizedArray<Number>::n_array_elements;
std::vector<unsigned int> irregular_cells;
- size_info.make_layout (n_active_cells, n_boundary_cells, n_vectors,
+ size_info.make_layout (n_active_cells, vectorization_length, boundary_cells,
irregular_cells);
for (unsigned int no=0; no<n_fe; ++no)
dof_info[no].assign_ghosts (boundary_cells);
- // reorganize the indices: we want to put the
- // boundary cells at the beginning for
- // multithreading. So just renumber the cell
- // indices and put them at the beginning of
- // the list that determines the order of the
- // cells
- std::vector<unsigned int> renumbering (n_active_cells,
- numbers::invalid_unsigned_int);
- {
- std::vector<unsigned int> reverse_numbering (n_active_cells,
- numbers::invalid_unsigned_int);
- unsigned int counter;
- if (task_info.use_multithreading == true)
- {
- for (unsigned int j=0; j<n_boundary_cells; ++j)
- reverse_numbering[boundary_cells[j]] = j;
- counter = n_boundary_cells;
- for (unsigned int j=0; j<n_active_cells; ++j)
- if (reverse_numbering[j] == numbers::invalid_unsigned_int)
- reverse_numbering[j] = counter++;
-
- size_info.boundary_cells_end = (size_info.boundary_cells_end -
- size_info.boundary_cells_start);
- size_info.boundary_cells_start = 0;
- }
- // Otherwise, we put the boundary cells to
- // the middle.
- else
- {
- for (unsigned int j=0; j<n_boundary_cells; ++j)
- reverse_numbering[boundary_cells[j]] = j+n_vectors*size_info.boundary_cells_start;
- counter = 0;
- unsigned int j = 0;
- while (counter < n_active_cells &&
- counter < n_vectors * size_info.boundary_cells_start)
- {
- if (reverse_numbering[j] == numbers::invalid_unsigned_int)
- reverse_numbering[j] = counter++;
- j++;
- }
- counter = std::min (n_vectors*size_info.boundary_cells_start+n_boundary_cells,
- n_active_cells);
- if (counter < n_active_cells)
- {
- for ( ; j<n_active_cells; ++j)
- if (reverse_numbering[j] == numbers::invalid_unsigned_int)
- reverse_numbering[j] = counter++;
- }
- }
- AssertDimension (counter, n_active_cells);
- for (unsigned int j=0; j<n_active_cells; ++j)
- {
- AssertIndexRange (reverse_numbering[j], n_active_cells);
- renumbering[reverse_numbering[j]] = j;
- }
- }
-
- // reorder cells so that we can parallelize by
- // threads
+ // reorganize the indices in order to overlap
+ // communication in MPI with computations:
+ // Place all cells with ghost indices into one
+ // chunk. Also reorder cells so that we can
+ // parallelize by threads
+ std::vector<unsigned int> renumbering;
if (task_info.use_multithreading == true)
{
+ dof_info[0].compute_renumber_parallel (boundary_cells, size_info,
+ renumbering);
if(task_info.use_partition_partition == true)
dof_info[0].make_thread_graph_partition_partition
(size_info, task_info, renumbering, irregular_cells,
// In case, we have an hp-dofhandler, we have
// to reorder the cell according to the
// polynomial degree on the cell.
+ dof_info[0].compute_renumber_serial (boundary_cells, size_info,
+ renumbering);
if (dof_handlers.active_dof_handler == DoFHandlers::hp)
- {
- const unsigned int max_fe_index =
- dof_info[0].max_fe_index;
- irregular_cells.resize (0);
- irregular_cells.resize (size_info.n_macro_cells+3*max_fe_index);
- const std::vector<unsigned int> &cell_active_fe_index =
- dof_info[0].cell_active_fe_index;
- std::vector<std::vector<unsigned int> > renumbering_fe_index;
- renumbering_fe_index.resize(max_fe_index);
- unsigned int counter,n_macro_cells_before = 0;
- const unsigned int
- start_bound = std::min (size_info.n_active_cells,
- size_info.boundary_cells_start*n_vectors),
- end_bound = std::min (size_info.n_active_cells,
- size_info.boundary_cells_end*n_vectors);
- for(counter=0; counter<start_bound; counter++)
- {
- renumbering_fe_index[cell_active_fe_index[renumbering[counter]]].
- push_back(renumbering[counter]);
- }
- counter = 0;
- for (unsigned int j=0;j<max_fe_index;j++)
- {
- for(unsigned int jj=0;jj<renumbering_fe_index[j].size();jj++)
- renumbering[counter++] = renumbering_fe_index[j][jj];
- irregular_cells[renumbering_fe_index[j].size()/n_vectors+
- n_macro_cells_before] =
- renumbering_fe_index[j].size()%n_vectors;
- n_macro_cells_before += (renumbering_fe_index[j].size()+n_vectors-1)/
- n_vectors;
- renumbering_fe_index[j].resize(0);
- }
- unsigned int new_boundary_start = n_macro_cells_before;
- for(counter = start_bound; counter < end_bound; counter++)
- {
- renumbering_fe_index[cell_active_fe_index[renumbering[counter]]].
- push_back(renumbering[counter]);
- }
- counter = start_bound;
- for (unsigned int j=0;j<max_fe_index;j++)
- {
- for(unsigned int jj=0;jj<renumbering_fe_index[j].size();jj++)
- renumbering[counter++] = renumbering_fe_index[j][jj];
- irregular_cells[renumbering_fe_index[j].size()/n_vectors+
- n_macro_cells_before] =
- renumbering_fe_index[j].size()%n_vectors;
- n_macro_cells_before += (renumbering_fe_index[j].size()+n_vectors-1)/
- n_vectors;
- renumbering_fe_index[j].resize(0);
- }
- unsigned int new_boundary_end = n_macro_cells_before;
- for(counter=end_bound; counter<n_active_cells; counter++)
- {
- renumbering_fe_index[cell_active_fe_index[renumbering[counter]]].
- push_back(renumbering[counter]);
- }
- counter = end_bound;
- for (unsigned int j=0;j<max_fe_index;j++)
- {
- for(unsigned int jj=0;jj<renumbering_fe_index[j].size();jj++)
- renumbering[counter++] = renumbering_fe_index[j][jj];
- irregular_cells[renumbering_fe_index[j].size()/n_vectors+
- n_macro_cells_before] =
- renumbering_fe_index[j].size()%n_vectors;
- n_macro_cells_before += (renumbering_fe_index[j].size()+n_vectors-1)/
- n_vectors;
- }
- AssertIndexRange (n_macro_cells_before,
- size_info.n_macro_cells + 3*max_fe_index+1);
- irregular_cells.resize (n_macro_cells_before);
- size_info.n_macro_cells = n_macro_cells_before;
- size_info.boundary_cells_start = new_boundary_start;
- size_info.boundary_cells_end = new_boundary_end;
- }
+ dof_info[0].compute_renumber_hp_serial (size_info, renumbering,
+ irregular_cells);
}
+
// Finally perform the renumbering. We also
// want to group several cells together to one
// "macro-cell" for vectorization (where the
std::vector<std::pair<unsigned int,unsigned int> >
cell_level_index_old;
cell_level_index.swap (cell_level_index_old);
- cell_level_index.reserve(size_info.n_macro_cells*n_vectors);
+ cell_level_index.reserve(size_info.n_macro_cells*vectorization_length);
unsigned int position_cell=0;
for (unsigned int i=0; i<size_info.n_macro_cells; ++i)
{
unsigned int n_comp = (irregular_cells[i]>0)?
- irregular_cells[i] : n_vectors;
+ irregular_cells[i] : vectorization_length;
for (unsigned int j=0; j<n_comp; ++j)
cell_level_index.push_back
(cell_level_index_old[renumbering[position_cell+j]]);
// generate a cell and level index
// also when we have not filled up
- // n_vectors cells. This is needed for
+ // vectorization_length cells. This is needed for
// MappingInfo when the transformation
// data is initialized. We just set
// the value to the last valid cell in
// that case.
- for (unsigned int j=n_comp; j<n_vectors; ++j)
+ for (unsigned int j=n_comp; j<vectorization_length; ++j)
cell_level_index.push_back
(cell_level_index_old[renumbering[position_cell+n_comp-1]]);
position_cell += n_comp;
}
AssertDimension (position_cell, size_info.n_active_cells);
- AssertDimension (cell_level_index.size(),size_info.n_macro_cells*n_vectors);
+ AssertDimension (cell_level_index.size(),size_info.n_macro_cells*vectorization_length);
}
// set constraint pool and reorder the indices
- constraint_pool.row_index =
- constraint_values.constraint_pool.row_index;
- constraint_pool.data.resize (constraint_values.constraint_pool.data.size());
- std::copy (constraint_values.constraint_pool.data.begin(),
- constraint_values.constraint_pool.data.end(),
- constraint_pool.data.begin());
+ constraint_pool_row_index =
+ constraint_values.constraint_pool_row_index;
+ constraint_pool_data.resize (constraint_values.constraint_pool_data.size());
+ std::copy (constraint_values.constraint_pool_data.begin(),
+ constraint_values.constraint_pool_data.end(),
+ constraint_pool_data.begin());
for (unsigned int no=0; no<n_fe; ++no)
{
dof_info[no].reorder_cells(size_info, renumbering,
- constraint_pool.row_index,
- irregular_cells, n_vectors);
+ constraint_pool_row_index,
+ irregular_cells, vectorization_length);
}
indices_are_initialized = true;
{
std::size_t memory = MemoryConsumption::memory_consumption (dof_info);
memory += MemoryConsumption::memory_consumption (cell_level_index);
- memory += MemoryConsumption::memory_consumption (fe_evaluation_data);
- memory += MemoryConsumption::memory_consumption (constraint_pool);
+ memory += MemoryConsumption::memory_consumption (shape_info);
+ memory += MemoryConsumption::memory_consumption (constraint_pool_data);
+ memory += MemoryConsumption::memory_consumption (constraint_pool_row_index);
memory += MemoryConsumption::memory_consumption (task_info);
memory += sizeof(this);
memory += mapping_info.memory_consumption();
void MatrixFree<dim,Number>::print_memory_consumption (STREAM &out) const
{
out << " Memory cell FE operator total: --> ";
- size_info.print_mem (out, memory_consumption());
+ size_info.print_memory_statistics (out, memory_consumption());
out << " Memory cell index: ";
- size_info.print_mem (out, MemoryConsumption::memory_consumption (cell_level_index));
+ size_info.print_memory_statistics
+ (out, MemoryConsumption::memory_consumption (cell_level_index));
for (unsigned int j=0; j<dof_info.size(); ++ j)
{
out << " Memory DoFInfo component "<< j << std::endl;
mapping_info.print_memory_consumption(out, size_info);
out << " Memory unit cell shape data: ";
- size_info.print_mem (out, MemoryConsumption::memory_consumption (fe_evaluation_data));
+ size_info.print_memory_statistics
+ (out, MemoryConsumption::memory_consumption (shape_info));
if (task_info.use_multithreading == true)
{
out << " Memory task partitioning info: ";
- size_info.print_mem (out, MemoryConsumption::memory_consumption (task_info));
+ size_info.print_memory_statistics
+ (out, MemoryConsumption::memory_consumption (task_info));
}
}
for (unsigned int no=0; no<dof_info.size(); ++no)
{
out << "\n-- Index data for component " << no << " --" << std::endl;
- dof_info[no].print (constraint_pool, out);
+ dof_info[no].print (constraint_pool_data, constraint_pool_row_index, out);
out << std::endl;
}
}
+
+/*-------------------- Implementation of helper functions ------------------*/
+
+namespace internal
+{
+ namespace MatrixFreeFunctions
+ {
+
+ TaskInfo::TaskInfo ()
+ {
+ clear();
+ }
+
+
+
+ void TaskInfo::clear ()
+ {
+ block_size = 0;
+ n_blocks = 0;
+ block_size_last = 0;
+ position_short_block = 0;
+ use_multithreading = false;
+ use_partition_partition = false;
+ use_coloring_only = false;
+ partition_color_blocks_row_index.clear();
+ partition_color_blocks_data.clear();
+ evens = 0;
+ odds = 0;
+ n_blocked_workers = 0;
+ n_workers = 0;
+ partition_evens.clear();
+ partition_odds.clear();
+ partition_n_blocked_workers.clear();
+ partition_n_workers.clear();
+ }
+
+
+
+ std::size_t
+ TaskInfo::memory_consumption () const
+ {
+ return (MemoryConsumption::memory_consumption (partition_color_blocks_row_index) +
+ MemoryConsumption::memory_consumption (partition_color_blocks_data)+
+ MemoryConsumption::memory_consumption (partition_evens) +
+ MemoryConsumption::memory_consumption (partition_odds) +
+ MemoryConsumption::memory_consumption (partition_n_blocked_workers) +
+ MemoryConsumption::memory_consumption (partition_n_workers));
+ }
+
+
+
+ SizeInfo::SizeInfo ()
+ {
+ clear();
+ }
+
+
+
+ void SizeInfo::clear()
+ {
+ n_active_cells = 0;
+ n_macro_cells = 0;
+ boundary_cells_start = 0;
+ boundary_cells_end = 0;
+ vectorization_length = 0;
+ locally_owned_cells = IndexSet();
+ ghost_cells = IndexSet();
+ communicator = MPI_COMM_SELF;
+ my_pid = 0;
+ n_procs = 0;
+ }
+
+
+
+ template <typename STREAM>
+ void SizeInfo::print_memory_statistics (STREAM &out,
+ std::size_t data_length) const
+ {
+ Utilities::MPI::MinMaxAvg memory_c;
+ if (Utilities::System::job_supports_mpi() == true)
+ {
+ memory_c = Utilities::MPI::min_max_avg (1e-6*data_length,
+ communicator);
+ }
+ else
+ {
+ memory_c.sum = 1e-6*data_length;
+ memory_c.min = memory_c.sum;
+ memory_c.max = memory_c.sum;
+ memory_c.avg = memory_c.sum;
+ memory_c.min_index = 0;
+ memory_c.max_index = 0;
+ }
+ if (n_procs < 2)
+ out << memory_c.min;
+ else
+ out << memory_c.min << "/" << memory_c.avg << "/" << memory_c.max;
+ out << " MB" << std::endl;
+ }
+
+
+
+ inline
+ void SizeInfo::make_layout (const unsigned int n_active_cells_in,
+ const unsigned int vectorization_length_in,
+ std::vector<unsigned int> &boundary_cells,
+ std::vector<unsigned int> &irregular_cells)
+ {
+ vectorization_length = vectorization_length_in;
+ n_active_cells = n_active_cells_in;
+
+ unsigned int n_max_boundary_cells = boundary_cells.size();
+ unsigned int n_boundary_cells = n_max_boundary_cells;
+
+ // try to make the number of boundary cells
+ // divisible by the number of vectors in
+ // vectorization
+ /*
+ // try to balance the number of cells before
+ // and after the boundary part on each
+ // processor. probably not worth it!
+#if DEAL_II_COMPILER_SUPPORTS_MPI
+ MPI_Allreduce (&n_boundary_cells, &n_max_boundary_cells, 1, MPI_UNSIGNED,
+ MPI_MAX, size_info.communicator);
+#endif
+ if (n_max_boundary_cells > n_active_cells)
+ n_max_boundary_cells = n_active_cells;
+ */
+
+ unsigned int fillup_needed =
+ (vectorization_length - n_boundary_cells%vectorization_length)%vectorization_length;
+ if (fillup_needed > 0 && n_boundary_cells < n_active_cells)
+ {
+ // fill additional cells into the list of
+ // boundary cells to get a balanced number. Go
+ // through the indices successively until we
+ // found enough indices
+ std::vector<unsigned int> new_boundary_cells;
+ new_boundary_cells.reserve (n_max_boundary_cells);
+
+ unsigned int next_free_slot = 0, bound_index = 0;
+ while (fillup_needed > 0 && bound_index < boundary_cells.size())
+ {
+ if (next_free_slot < boundary_cells[bound_index])
+ {
+ // check if there are enough cells to fill
+ // with in the current slot
+ if (next_free_slot + fillup_needed <= boundary_cells[bound_index])
+ {
+ for (unsigned int j=boundary_cells[bound_index]-fillup_needed;
+ j < boundary_cells[bound_index]; ++j)
+ new_boundary_cells.push_back(j);
+ fillup_needed = 0;
+ }
+ // ok, not enough indices, so just take them
+ // all up to the next boundary cell
+ else
+ {
+ for (unsigned int j=next_free_slot;
+ j<boundary_cells[bound_index]; ++j)
+ new_boundary_cells.push_back(j);
+ fillup_needed -= boundary_cells[bound_index]-next_free_slot;
+ }
+ }
+ new_boundary_cells.push_back(boundary_cells[bound_index]);
+ next_free_slot = boundary_cells[bound_index]+1;
+ ++bound_index;
+ }
+ while (fillup_needed > 0 && (new_boundary_cells.size()==0 ||
+ new_boundary_cells.back()<n_active_cells-1))
+ new_boundary_cells.push_back(new_boundary_cells.back()+1);
+ while (bound_index<boundary_cells.size())
+ new_boundary_cells.push_back(boundary_cells[bound_index++]);
+
+ boundary_cells.swap(new_boundary_cells);
+ }
+
+ // set the number of cells
+ std::sort (boundary_cells.begin(), boundary_cells.end());
+ n_boundary_cells = boundary_cells.size();
+
+ // check that number of boundary cells
+ // is divisible by
+ // vectorization_length or that it
+ // contains all cells
+ Assert (n_boundary_cells % vectorization_length == 0 ||
+ n_boundary_cells == n_active_cells, ExcInternalError());
+ n_macro_cells = (n_active_cells+vectorization_length-1)/vectorization_length;
+ irregular_cells.resize (n_macro_cells);
+ if (n_macro_cells*vectorization_length > n_active_cells)
+ {
+ irregular_cells[n_macro_cells-1] =
+ vectorization_length - (n_macro_cells*vectorization_length - n_active_cells);
+ }
+ if (n_procs > 1)
+ {
+ const unsigned int n_macro_boundary_cells =
+ (n_boundary_cells+vectorization_length-1)/vectorization_length;
+ boundary_cells_start = (n_macro_cells-n_macro_boundary_cells)/2;
+ boundary_cells_end = boundary_cells_start + n_macro_boundary_cells;
+ }
+ else
+ boundary_cells_start = boundary_cells_end = n_macro_cells;
+ }
+
+
+
+ HashValue::HashValue (const double element_size)
+ :
+ scaling (element_size * std::numeric_limits<double>::epsilon() *
+ 1024.)
+ {}
+
+
+
+ unsigned int HashValue::operator ()(const std::vector<double> &vec)
+ {
+ std::vector<double> mod_vec(vec);
+ for (unsigned int i=0; i<mod_vec.size(); ++i)
+ mod_vec[i] -= fmod (mod_vec[i], scaling);
+ return static_cast<unsigned int>(boost::hash_range (mod_vec.begin(), mod_vec.end()));
+ }
+
+
+ template <int dim, typename number>
+ unsigned int HashValue::operator ()
+ (const Tensor<2,dim,VectorizedArray<number> > &input,
+ const bool is_diagonal)
+ {
+ const unsigned int vectorization_length =
+ VectorizedArray<number>::n_array_elements;
+
+ if (is_diagonal)
+ {
+ number mod_tensor [dim][vectorization_length];
+ for (unsigned int i=0; i<dim; ++i)
+ for (unsigned int j=0; j<vectorization_length; ++j)
+ mod_tensor[i][j] = input[i][i][j] - fmod (input[i][i][j],
+ number(scaling));
+ return static_cast<unsigned int>
+ (boost::hash_range(&mod_tensor[0][0],
+ &mod_tensor[0][0]+dim*vectorization_length));
+ }
+ else
+ {
+ number mod_tensor [dim][dim][vectorization_length];
+ for (unsigned int i=0; i<dim; ++i)
+ for (unsigned int d=0; d<dim; ++d)
+ for (unsigned int j=0; j<vectorization_length; ++j)
+ mod_tensor[i][d][j] = input[i][d][j] - fmod (input[i][d][j],
+ number(scaling));
+ return static_cast<unsigned int>(boost::hash_range
+ (&mod_tensor[0][0][0],
+ &mod_tensor[0][0][0]+
+ dim*dim*vectorization_length));
+ }
+ }
+
+ }
+}
+
+
DEAL_II_NAMESPACE_CLOSE
//
//---------------------------------------------------------------------------
-#ifndef __deal2__matrix_free_fe_evaluation_data_h
-#define __deal2__matrix_free_fe_evaluation_data_h
+#ifndef __deal2__matrix_free_shape_info_h
+#define __deal2__matrix_free_shape_info_h
#include <deal.II/base/exceptions.h>
* @author Katharina Kormann and Martin Kronbichler, 2010, 2011
*/
template <typename Number>
- struct FEEvaluationData
+ struct ShapeInfo
{
- typedef VectorizedArray<Number> vector_t;
- static const std::size_t n_vectors = VectorizedArray<Number>::n_array_elements;
-
/**
* Empty constructor. Does nothing.
*/
- FEEvaluationData ();
+ ShapeInfo ();
/**
* Initializes the data fields. Takes a
* quadrature points are the index running
* fastest.
*/
- AlignedVector<vector_t> shape_values;
+ AlignedVector<VectorizedArray<Number> > shape_values;
/**
* Stores the shape gradients of the 1D finite
* quadrature points are the index running
* fastest.
*/
- AlignedVector<vector_t> shape_gradients;
+ AlignedVector<VectorizedArray<Number> > shape_gradients;
/**
* Stores the shape Hessians of the 1D finite
* quadrature points are the index running
* fastest.
*/
- AlignedVector<vector_t> shape_hessians;
+ AlignedVector<VectorizedArray<Number> > shape_hessians;
/**
* Stores the indices from cell DoFs to face
#include <deal.II/fe/fe_poly.h>
#include <deal.II/fe/fe_tools.h>
-#include <deal.II/matrix_free/fe_evaluation_data.h>
+#include <deal.II/matrix_free/shape_info.h>
DEAL_II_NAMESPACE_OPEN
{
namespace MatrixFreeFunctions
{
- namespace internal
- {
-
- // ----------------- FE_PolyAccess -----------------------------------
-
- // in order to read out the 1D info from a
- // finite element and use the tensor product
- // structure easily, we need to be able to
- // access the numbering in the polynomial
- // space of the finite element. that
- // information is not public, but we can get
- // access to that information by creating a
- // new dummy class that is based on
- // FE_Poly<TensorProductPolynomials<dim>,dim,spacedim>
- template <int dim, int spacedim>
- class FE_PolyAccess : public FE_Poly<TensorProductPolynomials<dim>, dim, spacedim>
- {
- public:
- FE_PolyAccess (const FE_Poly<TensorProductPolynomials<dim>,dim,spacedim> &fe)
- :
- FE_Poly<TensorProductPolynomials<dim>,dim,spacedim>(fe)
- {}
-
- virtual std::string get_name() const
- {
- Assert (false, ExcNotImplemented());
- return 0;
- }
- virtual FiniteElement<dim,spacedim> * clone() const
- {
- Assert (false, ExcNotImplemented());
- return 0;
- }
-
- const std::vector<unsigned int> get_numbering () const
- {
- return this->poly_space.get_numbering();
- }
-
- const std::vector<unsigned int> get_numbering_inverse () const
- {
- return this->poly_space.get_numbering_inverse();
- }
- };
-
- } // end of namespace internal
-
-
- // ----------------- actual FEEvaluationData functions --------------------
+ // ----------------- actual ShapeInfo functions --------------------
template <typename Number>
- FEEvaluationData<Number>::FEEvaluationData ()
+ ShapeInfo<Number>::ShapeInfo ()
:
n_q_points (0),
dofs_per_cell (0)
template <typename Number>
template <int dim>
void
- FEEvaluationData<Number>::reinit (const Quadrature<1> &quad,
+ ShapeInfo<Number>::reinit (const Quadrature<1> &quad,
const FiniteElement<dim> &fe_dim)
{
Assert (fe_dim.n_components() == 1,
template <typename Number>
void
- FEEvaluationData<Number>::do_initialize (const Quadrature<1> &quad,
+ ShapeInfo<Number>::do_initialize (const Quadrature<1> &quad,
const FiniteElement<1> &fe,
const unsigned int dim)
{
// lexicographic ordering necessary to apply
// tensor products efficiently)
{
- const FE_Poly<TensorProductPolynomials<1>,1,1> *cast_fe =
+ const FE_Poly<TensorProductPolynomials<1>,1,1> *fe_poly =
dynamic_cast<const FE_Poly<TensorProductPolynomials<1>,1,1>*>(&fe);
- Assert (cast_fe != 0, ExcNotImplemented());
- const internal::FE_PolyAccess<1,1> & fe_acc =
- static_cast< const internal::FE_PolyAccess<1,1> &>(*cast_fe);
- lexicographic = fe_acc.get_numbering();
+ Assert (fe_poly != 0, ExcNotImplemented());
+ lexicographic = fe_poly->get_poly_space_numbering();
}
n_q_points = 1;
const unsigned int my_i = lexicographic[i];
for (unsigned int q=0; q<n_q_points_1d; ++q)
{
- // fill both vectors with n_vectors copies for
- // the shape information and non-vectorized
- // fields
+ // fill both vectors with
+ // VectorizedArray<Number>::n_array_elements
+ // copies for the shape information and
+ // non-vectorized fields
const Point<1> q_point = quad.get_points()[q];
shape_values_number[my_i*n_q_points_1d+q] = fe.shape_value(i,q_point);
shape_gradient_number[my_i*n_q_points_1d+q] = fe.shape_grad (i,q_point)[0];
template <typename Number>
std::size_t
- FEEvaluationData<Number>::memory_consumption () const
+ ShapeInfo<Number>::memory_consumption () const
{
std::size_t memory = sizeof(*this);
memory += MemoryConsumption::memory_consumption(shape_values);
return memory;
}
- // end of functions for FEEvaluationData
+ // end of functions for ShapeInfo
} // end of namespace MatrixFreeFunctions
} // end of namespace internal
EOT
;
-my $vector_functions_also_parallel = <<EOT
+my $vector_functions_also_parallel = <<'EOT'
template void ConstraintMatrix::set_zero<V1 >(V1&) const;
######################################################################
multisubst($vector_functions, ['V1'], \@sequential_vectors);
+multisubst($vector_functions, ['V1'], \@deal_parallel_vectors);
multisubst($vector_functions_also_parallel, ['V1'], \@sequential_vectors);
multisubst($vector_functions_also_parallel, ['V1'], \@parallel_vectors);
multisubst($scalar_functions, ['S1'], \@real_scalars);
DEAL::27 23 0.156
DEAL::27 24 0.312
DEAL::27 25 -0.0625
-DEAL::27 26 0.312
+DEAL::27 26 0.313
DEAL::28 0 0
DEAL::28 1 0
DEAL::28 2 0
DoFHandler<dim> dof (tria);
deallog << "Testing " << fe.get_name() << std::endl;
- // run test for several different meshes
+ // run test for several different meshes
for (unsigned int i=0; i<8-2*dim; ++i)
{
cell = tria.begin_active ();
unsigned int counter = 0;
for (; cell!=endc; ++cell, ++counter)
- if (counter % (9-i) == 0)
- cell->set_refine_flag();
+ if (counter % (9-i) == 0)
+ cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
dof.distribute_dofs(fe);
ConstraintMatrix constraints;
DoFTools::make_hanging_node_constraints(dof, constraints);
VectorTools::interpolate_boundary_values (dof, 0, ZeroFunction<dim>(),
- constraints);
+ constraints);
constraints.close();
//std::cout << "Number of cells: " << dof.get_tria().n_active_cells() << std::endl;
MatrixFree<dim,number> mf_data;
{
- const QGauss<1> quad (fe_degree+1);
- mf_data.reinit (dof, constraints, quad,
- typename MatrixFree<dim,number>::AdditionalData(MPI_COMM_SELF,MatrixFree<dim,number>::AdditionalData::none));
+ const QGauss<1> quad (fe_degree+1);
+ mf_data.reinit (dof, constraints, quad,
+ typename MatrixFree<dim,number>::AdditionalData(MPI_COMM_SELF,MatrixFree<dim,number>::AdditionalData::none));
}
- MatrixFreeTest<dim,fe_degree+1,number> mf_ref (mf_data);
+ MatrixFreeTest<dim,fe_degree,number> mf_ref (mf_data);
Vector<number> in_dist (dof.n_dofs());
Vector<number> out_ref (in_dist), out_copy (in_dist);
- MatrixFree<dim,number> mf_copy;
+ MatrixFree<dim,number> mf_copy;
mf_copy.copy_from (mf_data);
- MatrixFreeTest<dim,fe_degree+1,number> copied (mf_copy);
+ MatrixFreeTest<dim,fe_degree,number> copied (mf_copy);
for (unsigned int i=0; i<dof.n_dofs(); ++i)
- {
- if(constraints.is_constrained(i))
- continue;
- const double entry = rand()/(double)RAND_MAX;
- in_dist(i) = entry;
- }
+ {
+ if(constraints.is_constrained(i))
+ continue;
+ const double entry = rand()/(double)RAND_MAX;
+ in_dist(i) = entry;
+ }
mf_ref.vmult (out_ref, in_dist);
copied.vmult (out_copy, in_dist);
out_copy -= out_ref;
double diff_norm = out_copy.linfty_norm();
deallog << "Error in copied MF: " << diff_norm
- << std::endl;
+ << std::endl;
}
deallog << std::endl;
}
void create_mesh (Triangulation<2> &tria,
- const double scale_grid = 1.)
+ const double scale_grid = 1.)
{
const unsigned int dim = 2;
std::vector<Point<dim> > points (12);
- // build the mesh layer by layer from points
+ // build the mesh layer by layer from points
- // 1. cube cell
+ // 1. cube cell
points[0] = Point<dim> (0, 0);
points[1] = Point<dim> (0, 1);
points[2] = Point<dim> (1 ,0);
points[3] = Point<dim> (1 ,1);
- // 2. rectangular cell
+ // 2. rectangular cell
points[4] = Point<dim> (3., 0);
points[5] = Point<dim> (3., 1);
- // 3. parallelogram cell
+ // 3. parallelogram cell
points[6] = Point<dim> (5., 1.);
points[7] = Point<dim> (5., 2.);
- // almost square cell (but trapezoidal by
- // 1e-8)
+ // almost square cell (but trapezoidal by
+ // 1e-8)
points[8] = Point<dim> (6., 1.);
points[9] = Point<dim> (6., 2.+1e-8);
- // apparently trapezoidal cell
+ // apparently trapezoidal cell
points[10] = Point<dim> (7., 1.4);
points[11] = Point<dim> (7.5, numbers::PI);
if (scale_grid != 1.)
for (unsigned int i=0; i<points.size(); ++i)
points[i] *= scale_grid;
-
+
- // connect the points to cells
+ // connect the points to cells
std::vector<CellData<dim> > cells(5);
for (unsigned int i=0; i<5; ++i)
{
void create_mesh (Triangulation<3> &tria,
- const double scale_grid = 1.)
+ const double scale_grid = 1.)
{
const unsigned int dim = 3;
std::vector<Point<dim> > points (24);
- // build the mesh layer by layer from points
+ // build the mesh layer by layer from points
- // 1. cube cell
+ // 1. cube cell
points[0] = Point<dim> (0,0,0);
points[1] = Point<dim> (0,1.,0);
points[2] = Point<dim> (0,0,1);
points[6] = Point<dim> (1.,0,1);
points[7] = Point<dim> (1.,1.,1);
- // 2. rectangular cell
+ // 2. rectangular cell
points[8] = Point<dim> (3., 0, 0);
points[9] = Point<dim> (3., 1, 0);
points[10] = Point<dim> (3., 0,1);
points[11] = Point<dim> (3., 1,1);
- // 3. parallelogram cell
+ // 3. parallelogram cell
points[12] = Point<dim> (5., 1., 1.);
points[13] = Point<dim> (5., 2., 1.);
points[14] = Point<dim> (5., 1., 2.);
points[15] = Point<dim> (5., 2., 2.);
- // almost square cell (but trapezoidal by
- // 1e-8 in y-direction)
+ // almost square cell (but trapezoidal by
+ // 1e-8 in y-direction)
points[16] = Point<dim> (6., 1., 1.);
points[17] = Point<dim> (6., 2.+1e-8, 1.);
points[18] = Point<dim> (6., 1., 2.);
points[19] = Point<dim> (6., 2., 2.);
- // apparently trapezoidal cell
+ // apparently trapezoidal cell
points[20] = Point<dim> (7., 1.4, 1.2231);
points[21] = Point<dim> (7.5, numbers::PI, 1.334);
points[22] = Point<dim> (7., 1.5, 7.1);
for (unsigned int i=0; i<points.size(); ++i)
points[i] *= scale_grid;
- // connect the points to cells
+ // connect the points to cells
std::vector<CellData<dim> > cells(5);
for (unsigned int i=0; i<5; ++i)
{
GridGenerator::hyper_ball (tria);
static const HyperBallBoundary<dim> boundary;
tria.set_boundary (0, boundary);
- // refine first and last cell
+ // refine first and last cell
tria.begin(tria.n_levels()-1)->set_refine_flag();
tria.last()->set_refine_flag();
tria.execute_coarsening_and_refinement();
-template <int dim, int n_dofs_1d, int n_q_points_1d=n_dofs_1d, typename Number=double>
+template <int dim, int fe_degree, int n_q_points_1d=fe_degree+1, typename Number=double>
class MatrixFreeTest
{
public:
MatrixFreeTest(const MatrixFree<dim,Number> &data_in):
data (data_in),
fe_val (data.get_dof_handler().get_fe(),
- Quadrature<dim>(data.get_quad(0)),
- update_values | update_gradients | update_hessians)
+ Quadrature<dim>(data.get_quad(0)),
+ update_values | update_gradients | update_hessians)
{};
MatrixFreeTest(const MatrixFree<dim,Number> &data_in,
- const Mapping<dim> &mapping):
+ const Mapping<dim> &mapping):
data (data_in),
fe_val (mapping, data.get_dof_handler().get_fe(),
- Quadrature<dim>(data.get_quad(0)),
- update_values | update_gradients | update_hessians)
+ Quadrature<dim>(data.get_quad(0)),
+ update_values | update_gradients | update_hessians)
{};
virtual ~MatrixFreeTest ()
{}
- // make function virtual to allow derived
- // classes to define a different function
+ // make function virtual to allow derived
+ // classes to define a different function
virtual void
operator () (const MatrixFree<dim,Number> &data,
- Vector<Number> &,
- const Vector<Number> &src,
- const std::pair<unsigned int,unsigned int> &cell_range) const
+ Vector<Number> &,
+ const Vector<Number> &src,
+ const std::pair<unsigned int,unsigned int> &cell_range) const
{
typedef VectorizedArray<Number> vector_t;
- FEEvaluation<dim,n_dofs_1d,n_q_points_1d,1,Number> fe_eval (data);
+ FEEvaluation<dim,fe_degree,n_q_points_1d,1,Number> fe_eval (data);
std::vector<double> reference_values (fe_eval.n_q_points);
std::vector<Tensor<1,dim> > reference_grads (fe_eval.n_q_points);
for(unsigned int cell=cell_range.first;cell<cell_range.second;++cell)
{
- fe_eval.reinit (cell);
- fe_eval.read_dof_values(src);
- fe_eval.evaluate (true,true,true);
-
- // compare values with the ones the FEValues
- // gives us. Those are seen as reference
- for (unsigned int j=0; j<data.n_components_filled(cell); ++j)
- {
- fe_val.reinit (data.get_cell_iterator(cell,j));
- fe_val.get_function_values(src, reference_values);
- fe_val.get_function_gradients(src, reference_grads);
- fe_val.get_function_hessians(src, reference_hess);
-
- for (int q=0; q<(int)fe_eval.n_q_points; q++)
- {
- errors[0] += std::fabs(fe_eval.get_value(q)[j]-
- reference_values[q]);
- for (unsigned int d=0; d<dim; ++d)
- errors[1] += std::fabs(fe_eval.get_gradient(q)[d][j]-
- reference_grads[q][d]);
- errors[2] += std::fabs(fe_eval.get_laplacian(q)[j]-
- trace(reference_hess[q]));
- for (unsigned int d=0; d<dim; ++d)
+ fe_eval.reinit (cell);
+ fe_eval.read_dof_values(src);
+ fe_eval.evaluate (true,true,true);
+
+ // compare values with the ones the FEValues
+ // gives us. Those are seen as reference
+ for (unsigned int j=0; j<data.n_components_filled(cell); ++j)
+ {
+ fe_val.reinit (data.get_cell_iterator(cell,j));
+ fe_val.get_function_values(src, reference_values);
+ fe_val.get_function_gradients(src, reference_grads);
+ fe_val.get_function_hessians(src, reference_hess);
+
+ for (int q=0; q<(int)fe_eval.n_q_points; q++)
+ {
+ errors[0] += std::fabs(fe_eval.get_value(q)[j]-
+ reference_values[q]);
+ for (unsigned int d=0; d<dim; ++d)
+ errors[1] += std::fabs(fe_eval.get_gradient(q)[d][j]-
+ reference_grads[q][d]);
+ errors[2] += std::fabs(fe_eval.get_laplacian(q)[j]-
+ trace(reference_hess[q]));
+ for (unsigned int d=0; d<dim; ++d)
{
errors[3] += std::fabs(fe_eval.get_hessian_diagonal(q)[d][j]-
- reference_hess[q][d][d]);
- for (unsigned int e=0; e<dim; ++e)
- errors[4] += std::fabs(fe_eval.get_hessian(q)[d][e][j]-
- reference_hess[q][d][e]);
- }
-
- total[0] += std::fabs(reference_values[q]);
- for (unsigned int d=0; d<dim; ++d)
- total[1] += std::fabs(reference_grads[q][d]);
-
- // reference for second derivatives computed
- // from fe_eval because FEValues is not
- // accurate enough with finite differences
- total[2] += std::fabs(fe_eval.get_laplacian(q)[j]);
- for (unsigned int d=0; d<dim; ++d)
+ reference_hess[q][d][d]);
+ for (unsigned int e=0; e<dim; ++e)
+ errors[4] += std::fabs(fe_eval.get_hessian(q)[d][e][j]-
+ reference_hess[q][d][e]);
+ }
+
+ total[0] += std::fabs(reference_values[q]);
+ for (unsigned int d=0; d<dim; ++d)
+ total[1] += std::fabs(reference_grads[q][d]);
+
+ // reference for second derivatives computed
+ // from fe_eval because FEValues is not
+ // accurate enough with finite differences
+ total[2] += std::fabs(fe_eval.get_laplacian(q)[j]);
+ for (unsigned int d=0; d<dim; ++d)
{
- total[3] += std::fabs(fe_eval.get_hessian_diagonal(q)[d][j]);
- for (unsigned int e=0; e<dim; ++e)
- total[4] += std::fabs(fe_eval.get_hessian(q)[d][e][j]);
+ total[3] += std::fabs(fe_eval.get_hessian_diagonal(q)[d][j]);
+ for (unsigned int e=0; e<dim; ++e)
+ total[4] += std::fabs(fe_eval.get_hessian(q)[d][e][j]);
}
- }
- }
+ }
+ }
}
}
{
for (unsigned int i=0; i<5; ++i)
{
- errors[i] = 0;
- total[i] = 0;
+ errors[i] = 0;
+ total[i] = 0;
}
Vector<Number> dst_dummy;
data.cell_loop (&MatrixFreeTest::operator(), this, dst_dummy, src);
- // for doubles, use a stricter condition than
- // for floats for the relative error size
+ // for doubles, use a stricter condition than
+ // for floats for the relative error size
if (types_are_equal<Number,double>::value == true)
{
- deallog.threshold_double (5e-14);
- deallog << "Error function values: "
- << errors[0]/total[0] << std::endl;
- deallog << "Error function gradients: "
- << errors[1]/total[1] << std::endl;
-
- // need to set quite a loose tolerance because
- // FEValues approximates Hessians with finite
- // differences, which are not so
- // accurate. moreover, Hessians are quite
- // large since we chose random numbers. for
- // some elements, it might also be zero
- // (linear elements on quadrilaterals), so
- // need to check for division by 0, too.
- deallog.threshold_double (5e-7);
- const double output2 = total[2] == 0 ? 0. : errors[2] / total[2];
- deallog << "Error function Laplacians: " << output2 << std::endl;
+ deallog.threshold_double (5e-14);
+ deallog << "Error function values: "
+ << errors[0]/total[0] << std::endl;
+ deallog << "Error function gradients: "
+ << errors[1]/total[1] << std::endl;
+
+ // need to set quite a loose tolerance because
+ // FEValues approximates Hessians with finite
+ // differences, which are not so
+ // accurate. moreover, Hessians are quite
+ // large since we chose random numbers. for
+ // some elements, it might also be zero
+ // (linear elements on quadrilaterals), so
+ // need to check for division by 0, too.
+ deallog.threshold_double (5e-7);
+ const double output2 = total[2] == 0 ? 0. : errors[2] / total[2];
+ deallog << "Error function Laplacians: " << output2 << std::endl;
const double output3 = total[3] == 0 ? 0. : errors[3] / total[3];
- deallog << "Error function diagonal of Hessian: " << output3 << std::endl;
+ deallog << "Error function diagonal of Hessian: " << output3 << std::endl;
const double output4 = total[4] == 0 ? 0. : errors[4] / total[4];
- deallog << "Error function Hessians: " << output4 << std::endl;
+ deallog << "Error function Hessians: " << output4 << std::endl;
}
else if (types_are_equal<Number,float>::value == true)
{
- deallog.threshold_double (1e-6);
- deallog << "Error function values: "
- << errors[0]/total[0] << std::endl;
- deallog << "Error function gradients: "
- << errors[1]/total[1] << std::endl;
- const double output2 = total[2] == 0 ? 0. : errors[2] / total[2];
- deallog.threshold_double (1e-5);
- deallog << "Error function Laplacians: " << output2 << std::endl;
+ deallog.threshold_double (1e-6);
+ deallog << "Error function values: "
+ << errors[0]/total[0] << std::endl;
+ deallog << "Error function gradients: "
+ << errors[1]/total[1] << std::endl;
+ const double output2 = total[2] == 0 ? 0. : errors[2] / total[2];
+ deallog.threshold_double (1e-5);
+ deallog << "Error function Laplacians: " << output2 << std::endl;
const double output3 = total[3] == 0 ? 0. : errors[3] / total[3];
- deallog << "Error function diagonal of Hessian: " << output3 << std::endl;
+ deallog << "Error function diagonal of Hessian: " << output3 << std::endl;
const double output4 = total[4] == 0 ? 0. : errors[4] / total[4];
- deallog << "Error function Hessians: " << output4 << std::endl;
+ deallog << "Error function Hessians: " << output4 << std::endl;
}
deallog << std::endl;
};
// dummy with empty quadrature formula
-template <int dim, int n_dofs_1d,typename Number>
-class MatrixFreeTest<dim,n_dofs_1d,0,Number>
+template <int dim, int fe_degree,typename Number>
+class MatrixFreeTest<dim,fe_degree,0,Number>
{
public:
typedef VectorizedArray<Number> vector_t;
{};
MatrixFreeTest(const MatrixFree<dim,Number> &,
- const Mapping<dim> &)
+ const Mapping<dim> &)
{};
void cell_integration (Vector<Number> &,
- const Vector<Number> &,
- const std::pair<unsigned int,unsigned int>) const {}
+ const Vector<Number> &,
+ const std::pair<unsigned int,unsigned int>) const {}
void test_functions (const Vector<Number> &) const
{}
template <int dim, int fe_degree, typename number>
void do_test (const DoFHandler<dim> &dof,
- const ConstraintMatrix&constraints)
+ const ConstraintMatrix&constraints)
{
deallog << "Testing " << dof.get_fe().get_name() << std::endl;
// use this for info on problem
//std::cout << "Number of cells: " << dof.get_tria().n_active_cells()
- // << std::endl;
+ // << std::endl;
//std::cout << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
//std::cout << "Number of constraints: " << constraints.n_constraints() << std::endl;
Vector<number> solution (dof.n_dofs());
- // create vector with random entries
+ // create vector with random entries
for (unsigned int i=0; i<dof.n_dofs(); ++i)
{
if(constraints.is_constrained(i))
- continue;
+ continue;
const double entry = rand()/(double)RAND_MAX;
solution(i) = entry;
}
mf_data.reinit (dof, constraints, quad, data);
}
- MatrixFreeTest<dim,fe_degree+1,fe_degree+1,number> mf (mf_data);
+ MatrixFreeTest<dim,fe_degree,fe_degree+1,number> mf (mf_data);
mf.test_functions(solution);
}
create_mesh (tria);
tria.refine_global(4-dim);
- // refine a few cells
+ // refine a few cells
for (unsigned int i=0; i<10-3*dim; ++i)
{
typename Triangulation<dim>::active_cell_iterator
- cell = tria.begin_active (),
- endc = tria.end();
+ cell = tria.begin_active (),
+ endc = tria.end();
unsigned int counter = 0;
for (; cell!=endc; ++cell, ++counter)
- if (counter % (7-i) == 0)
- cell->set_refine_flag();
+ if (counter % (7-i) == 0)
+ cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
}
ConstraintMatrix constraints;
DoFTools::make_hanging_node_constraints (dof, constraints);
VectorTools::interpolate_boundary_values (dof, 1, ZeroFunction<dim>(),
- constraints);
+ constraints);
constraints.close();
do_test <dim, fe_degree, float> (dof, constraints);
#include "get_functions_common.h"
-template <int dim, int n_dofs_1d, typename Number>
-class MatrixFreeTestGL : public MatrixFreeTest<dim, n_dofs_1d, n_dofs_1d, Number>
+template <int dim, int fe_degree, typename Number>
+class MatrixFreeTestGL : public MatrixFreeTest<dim, fe_degree, fe_degree+1, Number>
{
public:
typedef VectorizedArray<Number> vector_t;
static const std::size_t n_vectors = VectorizedArray<Number>::n_array_elements;
MatrixFreeTestGL(const MatrixFree<dim,Number> &data,
- const Mapping<dim> &mapping):
- MatrixFreeTest<dim, n_dofs_1d, n_dofs_1d, Number>(data, mapping)
+ const Mapping<dim> &mapping):
+ MatrixFreeTest<dim, fe_degree, fe_degree+1, Number>(data, mapping)
{};
void operator() (const MatrixFree<dim,Number> &data,
- Vector<Number> &,
- const Vector<Number> &src,
- const std::pair<unsigned int,unsigned int> &cell_range) const
+ Vector<Number> &,
+ const Vector<Number> &src,
+ const std::pair<unsigned int,unsigned int> &cell_range) const
{
- FEEvaluationGL<dim,n_dofs_1d,1,Number> fe_eval (this->data);
+ FEEvaluationGL<dim,fe_degree,1,Number> fe_eval (this->data);
for(unsigned int cell=cell_range.first;cell<cell_range.second;++cell)
{
- fe_eval.reinit (cell);
- std::vector<double> reference_values (fe_eval.n_q_points);
- std::vector<Tensor<1,dim> > reference_grads (fe_eval.n_q_points);
- std::vector<Tensor<2,dim> > reference_hess (fe_eval.n_q_points);
- fe_eval.read_dof_values(src);
- fe_eval.evaluate (true,true,true);
-
- // compare values with the ones the FEValues
- // gives us. Those are seen as reference
- for (unsigned int j=0; j<data.n_components_filled(cell); ++j)
- {
- this->fe_val.reinit (data.get_cell_iterator(cell,j));
- this->fe_val.get_function_values(src, reference_values);
- this->fe_val.get_function_gradients(src, reference_grads);
- this->fe_val.get_function_hessians(src, reference_hess);
-
- for (int q=0; q<(int)fe_eval.n_q_points; q++)
- {
- this->errors[0] += std::fabs(fe_eval.get_value(q)[j]-
- reference_values[q]);
- for (unsigned int d=0; d<dim; ++d)
- this->errors[1] += std::fabs(fe_eval.get_gradient(q)[d][j]-
- reference_grads[q][d]);
- this->errors[2] += std::fabs(fe_eval.get_laplacian(q)[j]-
- trace(reference_hess[q]));
- this->total[0] += std::fabs(reference_values[q]);
- for (unsigned int d=0; d<dim; ++d)
- this->total[1] += std::fabs(reference_grads[q][d]);
- this->total[2] += std::fabs(fe_eval.get_laplacian(q)[j]);
- }
- }
+ fe_eval.reinit (cell);
+ std::vector<double> reference_values (fe_eval.n_q_points);
+ std::vector<Tensor<1,dim> > reference_grads (fe_eval.n_q_points);
+ std::vector<Tensor<2,dim> > reference_hess (fe_eval.n_q_points);
+ fe_eval.read_dof_values(src);
+ fe_eval.evaluate (true,true,true);
+
+ // compare values with the ones the FEValues
+ // gives us. Those are seen as reference
+ for (unsigned int j=0; j<data.n_components_filled(cell); ++j)
+ {
+ this->fe_val.reinit (data.get_cell_iterator(cell,j));
+ this->fe_val.get_function_values(src, reference_values);
+ this->fe_val.get_function_gradients(src, reference_grads);
+ this->fe_val.get_function_hessians(src, reference_hess);
+
+ for (int q=0; q<(int)fe_eval.n_q_points; q++)
+ {
+ this->errors[0] += std::fabs(fe_eval.get_value(q)[j]-
+ reference_values[q]);
+ for (unsigned int d=0; d<dim; ++d)
+ this->errors[1] += std::fabs(fe_eval.get_gradient(q)[d][j]-
+ reference_grads[q][d]);
+ this->errors[2] += std::fabs(fe_eval.get_laplacian(q)[j]-
+ trace(reference_hess[q]));
+ this->total[0] += std::fabs(reference_values[q]);
+ for (unsigned int d=0; d<dim; ++d)
+ this->total[1] += std::fabs(reference_grads[q][d]);
+ this->total[2] += std::fabs(fe_eval.get_laplacian(q)[j]);
+ }
+ }
}
}
};
GridGenerator::hyper_ball (tria);
static const HyperBallBoundary<dim> boundary;
tria.set_boundary (0, boundary);
- // refine first and last cell
+ // refine first and last cell
tria.begin(tria.n_levels()-1)->set_refine_flag();
tria.last()->set_refine_flag();
tria.execute_coarsening_and_refinement();
deallog << "Testing " << dof.get_fe().get_name() << std::endl;
//std::cout << "Number of cells: " << dof.get_tria().n_active_cells()
- // << std::endl;
+ // << std::endl;
//std::cout << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
//std::cout << "Number of constraints: " << constraints.n_constraints() << std::endl;
Vector<number> solution (dof.n_dofs());
- // create vector with random entries
+ // create vector with random entries
for (unsigned int i=0; i<dof.n_dofs(); ++i)
{
if(constraints.is_constrained(i))
- continue;
+ continue;
const double entry = rand()/(double)RAND_MAX;
solution(i) = entry;
}
MatrixFree<dim,number> mf_data;
deallog << "Test with fe_degree " << fe_degree
- << std::endl;
+ << std::endl;
const QGaussLobatto<1> quad (fe_degree+1);
MappingQ<dim> mapping (2);
typename MatrixFree<dim,number>::AdditionalData data;
data.tasks_parallel_scheme = MatrixFree<dim,number>::AdditionalData::none;
data.mapping_update_flags = update_gradients | update_second_derivatives;
mf_data.reinit (mapping, dof, constraints, quad, data);
- MatrixFreeTestGL<dim,fe_degree+1,number> mf (mf_data, mapping);
+ MatrixFreeTestGL<dim,fe_degree,number> mf (mf_data, mapping);
mf.test_functions (solution);
}
GridGenerator::hyper_ball (tria);
static const HyperBallBoundary<dim> boundary;
tria.set_boundary (0, boundary);
- // refine first and last cell
+ // refine first and last cell
tria.begin(tria.n_levels()-1)->set_refine_flag();
tria.last()->set_refine_flag();
tria.execute_coarsening_and_refinement();
DoFTools::make_hanging_node_constraints (dof, constraints);
constraints.close();
- // in the other functions, use do_test in
- // get_functions_common, but here we have to
- // manually choose another mapping
+ // in the other functions, use do_test in
+ // get_functions_common, but here we have to
+ // manually choose another mapping
deallog << "Testing " << dof.get_fe().get_name() << std::endl;
//std::cout << "Number of cells: " << dof.get_tria().n_active_cells()
- // << std::endl;
+ // << std::endl;
//std::cout << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
//std::cout << "Number of constraints: " << constraints.n_constraints() << std::endl;
Vector<number> solution (dof.n_dofs());
- // create vector with random entries
+ // create vector with random entries
for (unsigned int i=0; i<dof.n_dofs(); ++i)
{
if(constraints.is_constrained(i))
- continue;
+ continue;
const double entry = rand()/(double)RAND_MAX;
solution(i) = entry;
}
mf_data.reinit (mapping, dof, constraints, quad, data);
}
- MatrixFreeTest<dim,fe_degree+1,fe_degree+1,number> mf (mf_data, mapping);
+ MatrixFreeTest<dim,fe_degree,fe_degree+1,number> mf (mf_data, mapping);
mf.test_functions(solution);
deallog << std::endl;
}
std::ofstream logfile("get_functions_multife/output");
-template <int dim, int n_dofs_1d, int n_q_points_1d=n_dofs_1d, typename Number=double>
+template <int dim, int fe_degree, int n_q_points_1d=fe_degree+1, typename Number=double>
class MatrixFreeTest
{
public:
MatrixFreeTest(const MatrixFree<dim,Number> &data_in):
data (data_in),
fe_val0 (data.get_dof_handler(0).get_fe(),
- Quadrature<dim>(data.get_quad(0)),
- update_values | update_gradients | update_hessians),
+ Quadrature<dim>(data.get_quad(0)),
+ update_values | update_gradients | update_hessians),
fe_val1 (data.get_dof_handler(1).get_fe(),
- Quadrature<dim>(data.get_quad(1)),
- update_values | update_gradients | update_hessians)
+ Quadrature<dim>(data.get_quad(1)),
+ update_values | update_gradients | update_hessians)
{};
void
operator () (const MatrixFree<dim,Number> &data,
- VectorType &,
- const VectorType &src,
- const std::pair<unsigned int,unsigned int> &cell_range) const
+ VectorType &,
+ const VectorType &src,
+ const std::pair<unsigned int,unsigned int> &cell_range) const
{
- FEEvaluation<dim,n_dofs_1d,n_dofs_1d,1,Number> fe_eval0 (data,0,0);
- FEEvaluation<dim,n_dofs_1d+1,n_dofs_1d+1,1,Number> fe_eval1 (data,1,1);
+ FEEvaluation<dim,fe_degree,fe_degree+1,1,Number> fe_eval0 (data,0,0);
+ FEEvaluation<dim,fe_degree+1,fe_degree+2,1,Number> fe_eval1 (data,1,1);
std::vector<double> reference_values0 (fe_eval0.n_q_points);
std::vector<Tensor<1,dim> > reference_grads0 (fe_eval0.n_q_points);
std::vector<Tensor<2,dim> > reference_hess0 (fe_eval0.n_q_points);
std::vector<Tensor<2,dim> > reference_hess1 (fe_eval1.n_q_points);
for(unsigned int cell=cell_range.first;cell<cell_range.second;++cell)
{
- fe_eval0.reinit (cell);
- fe_eval0.read_dof_values(src[0]);
- fe_eval0.evaluate (true,true,true);
-
- fe_eval1.reinit (cell);
- fe_eval1.read_dof_values(src[1]);
- fe_eval1.evaluate (true,true,true);
-
- // compare values with the ones the FEValues
- // gives us. Those are seen as reference
- for (unsigned int j=0; j<data.n_components_filled(cell); ++j)
- {
- // FE 0
- fe_val0.reinit (data.get_cell_iterator(cell,j,0));
- fe_val0.get_function_values(src[0], reference_values0);
- fe_val0.get_function_gradients(src[0], reference_grads0);
- fe_val0.get_function_hessians(src[0], reference_hess0);
-
- for (int q=0; q<(int)fe_eval0.n_q_points; q++)
- {
- errors[0] += std::fabs(fe_eval0.get_value(q)[j]-
- reference_values0[q]);
- for (unsigned int d=0; d<dim; ++d)
- errors[1] += std::fabs(fe_eval0.get_gradient(q)[d][j]-
- reference_grads0[q][d]);
- errors[2] += std::fabs(fe_eval0.get_laplacian(q)[j]-
- trace(reference_hess0[q]));
- total[0] += std::fabs(reference_values0[q]);
- for (unsigned int d=0; d<dim; ++d)
- total[1] += std::fabs(reference_grads0[q][d]);
- total[2] += std::fabs(fe_eval0.get_laplacian(q)[j]);
- }
-
- // FE 1
- fe_val1.reinit (data.get_cell_iterator(cell,j,1));
- fe_val1.get_function_values(src[1], reference_values1);
- fe_val1.get_function_gradients(src[1], reference_grads1);
- fe_val1.get_function_hessians(src[1], reference_hess1);
-
- for (int q=0; q<(int)fe_eval1.n_q_points; q++)
- {
- errors[3] += std::fabs(fe_eval1.get_value(q)[j]-
- reference_values1[q]);
- for (unsigned int d=0; d<dim; ++d)
- errors[4] += std::fabs(fe_eval1.get_gradient(q)[d][j]-
- reference_grads1[q][d]);
- errors[5] += std::fabs(fe_eval1.get_laplacian(q)[j]-
- trace(reference_hess1[q]));
- total[3] += std::fabs(reference_values1[q]);
- for (unsigned int d=0; d<dim; ++d)
- total[4] += std::fabs(reference_grads1[q][d]);
- total[5] += std::fabs(fe_eval1.get_laplacian(q)[j]);
- }
- }
+ fe_eval0.reinit (cell);
+ fe_eval0.read_dof_values(src[0]);
+ fe_eval0.evaluate (true,true,true);
+
+ fe_eval1.reinit (cell);
+ fe_eval1.read_dof_values(src[1]);
+ fe_eval1.evaluate (true,true,true);
+
+ // compare values with the ones the FEValues
+ // gives us. Those are seen as reference
+ for (unsigned int j=0; j<data.n_components_filled(cell); ++j)
+ {
+ // FE 0
+ fe_val0.reinit (data.get_cell_iterator(cell,j,0));
+ fe_val0.get_function_values(src[0], reference_values0);
+ fe_val0.get_function_gradients(src[0], reference_grads0);
+ fe_val0.get_function_hessians(src[0], reference_hess0);
+
+ for (int q=0; q<(int)fe_eval0.n_q_points; q++)
+ {
+ errors[0] += std::fabs(fe_eval0.get_value(q)[j]-
+ reference_values0[q]);
+ for (unsigned int d=0; d<dim; ++d)
+ errors[1] += std::fabs(fe_eval0.get_gradient(q)[d][j]-
+ reference_grads0[q][d]);
+ errors[2] += std::fabs(fe_eval0.get_laplacian(q)[j]-
+ trace(reference_hess0[q]));
+ total[0] += std::fabs(reference_values0[q]);
+ for (unsigned int d=0; d<dim; ++d)
+ total[1] += std::fabs(reference_grads0[q][d]);
+ total[2] += std::fabs(fe_eval0.get_laplacian(q)[j]);
+ }
+
+ // FE 1
+ fe_val1.reinit (data.get_cell_iterator(cell,j,1));
+ fe_val1.get_function_values(src[1], reference_values1);
+ fe_val1.get_function_gradients(src[1], reference_grads1);
+ fe_val1.get_function_hessians(src[1], reference_hess1);
+
+ for (int q=0; q<(int)fe_eval1.n_q_points; q++)
+ {
+ errors[3] += std::fabs(fe_eval1.get_value(q)[j]-
+ reference_values1[q]);
+ for (unsigned int d=0; d<dim; ++d)
+ errors[4] += std::fabs(fe_eval1.get_gradient(q)[d][j]-
+ reference_grads1[q][d]);
+ errors[5] += std::fabs(fe_eval1.get_laplacian(q)[j]-
+ trace(reference_hess1[q]));
+ total[3] += std::fabs(reference_values1[q]);
+ for (unsigned int d=0; d<dim; ++d)
+ total[4] += std::fabs(reference_grads1[q][d]);
+ total[5] += std::fabs(fe_eval1.get_laplacian(q)[j]);
+ }
+ }
}
}
{
for (unsigned int i=0; i<3*2; ++i)
{
- errors[i] = 0;
- total[i] = 0;
+ errors[i] = 0;
+ total[i] = 0;
}
VectorType dst_dummy;
- data.cell_loop (&MatrixFreeTest<dim,n_dofs_1d,n_q_points_1d,Number>::operator(),
- this, dst_dummy, src);
+ data.cell_loop (&MatrixFreeTest<dim,fe_degree,n_q_points_1d,Number>::operator(),
+ this, dst_dummy, src);
- // for doubles, use a stricter condition then
- // for floats for the relative error size
+ // for doubles, use a stricter condition then
+ // for floats for the relative error size
for (unsigned int i=0; i<2; ++i)
{
- if (types_are_equal<Number,double>::value == true)
- {
- deallog.threshold_double (4e-14);
- deallog << "Error function values FE " << i << ": "
- << errors[i*3+0]/total[i*3+0] << std::endl;
- deallog << "Error function gradients FE " << i << ": "
- << errors[i*3+1]/total[i*3+1] << std::endl;
-
- // need to set quite a loose tolerance because
- // FEValues approximates Hessians with finite
- // differences, which are not so
- // accurate. moreover, Hessians are quite
- // large since we chose random numbers. for
- // some elements, it might also be zero
- // (linear elements on quadrilaterals), so
- // need to check for division by 0, too.
- deallog.threshold_double (5e-7);
- const double output2 = total[i*3+2] == 0 ? 0. : errors[i*3+2] / total[i*3+2];
- deallog << "Error function Laplacians FE " << i << ": " << output2 << std::endl;
- }
- else if (types_are_equal<Number,float>::value == true)
- {
- deallog.threshold_double (1e-6);
- deallog << "Error function values FE " << i << ": "
- << errors[i*3+0]/total[i*3+0] << std::endl;
- deallog << "Error function gradients FE " << i << ": "
- << errors[i*3+1]/total[i*3+1] << std::endl;
- const double output2 = total[i*3+2] == 0 ? 0. : errors[i*3+2] / total[i*3+2];
- deallog.threshold_double (1e-6);
- deallog << "Error function Laplacians FE " << i << ": " << output2 << std::endl;
- }
+ if (types_are_equal<Number,double>::value == true)
+ {
+ deallog.threshold_double (4e-14);
+ deallog << "Error function values FE " << i << ": "
+ << errors[i*3+0]/total[i*3+0] << std::endl;
+ deallog << "Error function gradients FE " << i << ": "
+ << errors[i*3+1]/total[i*3+1] << std::endl;
+
+ // need to set quite a loose tolerance because
+ // FEValues approximates Hessians with finite
+ // differences, which are not so
+ // accurate. moreover, Hessians are quite
+ // large since we chose random numbers. for
+ // some elements, it might also be zero
+ // (linear elements on quadrilaterals), so
+ // need to check for division by 0, too.
+ deallog.threshold_double (5e-7);
+ const double output2 = total[i*3+2] == 0 ? 0. : errors[i*3+2] / total[i*3+2];
+ deallog << "Error function Laplacians FE " << i << ": " << output2 << std::endl;
+ }
+ else if (types_are_equal<Number,float>::value == true)
+ {
+ deallog.threshold_double (1e-6);
+ deallog << "Error function values FE " << i << ": "
+ << errors[i*3+0]/total[i*3+0] << std::endl;
+ deallog << "Error function gradients FE " << i << ": "
+ << errors[i*3+1]/total[i*3+1] << std::endl;
+ const double output2 = total[i*3+2] == 0 ? 0. : errors[i*3+2] / total[i*3+2];
+ deallog.threshold_double (1e-6);
+ deallog << "Error function Laplacians FE " << i << ": " << output2 << std::endl;
+ }
}
};
for (unsigned int no=0; no<2; ++no)
for (unsigned int i=0; i<dof[no]->n_dofs(); ++i)
{
- if(constraints[no]->is_constrained(i))
- continue;
- const double entry = rand()/(double)RAND_MAX;
- src[no](i) = entry;
+ if(constraints[no]->is_constrained(i))
+ continue;
+ const double entry = rand()/(double)RAND_MAX;
+ src[no](i) = entry;
}
for (unsigned int no=0; no<2; ++no)
quad.push_back(QGauss<1>(fe_degree+1+no));
mf_data.reinit (dof, constraints, quad,
- typename MatrixFree<dim,number>::AdditionalData
- (MPI_COMM_SELF,
- MatrixFree<dim,number>::AdditionalData::none));
+ typename MatrixFree<dim,number>::AdditionalData
+ (MPI_COMM_SELF,
+ MatrixFree<dim,number>::AdditionalData::none));
}
- MatrixFreeTest<dim,fe_degree+1,fe_degree+1,number> mf (mf_data);
+ MatrixFreeTest<dim,fe_degree,fe_degree+1,number> mf (mf_data);
mf.test_functions(src);
deallog << std::endl;
}
{
deallog.attach(logfile);
deallog.depth_console(0);
- // need to set quite a loose tolerance because
- // FEValues approximates Hessians with finite
- // differences, which are not so accurate
+ // need to set quite a loose tolerance because
+ // FEValues approximates Hessians with finite
+ // differences, which are not so accurate
deallog.threshold_double(2.e-5);
deallog << std::setprecision (3);
std::ofstream logfile("get_functions_multife2/output");
-template <int dim, int n_dofs_1d, int n_q_points_1d=n_dofs_1d, typename Number=double>
+template <int dim, int fe_degree, int n_q_points_1d=fe_degree+1, typename Number=double>
class MatrixFreeTest
{
public:
MatrixFreeTest(const MatrixFree<dim,Number> &data_in):
data (data_in),
fe_val0 (data.get_dof_handler(0).get_fe(),
- Quadrature<dim>(data.get_quad(0)),
- update_values | update_gradients | update_hessians),
+ Quadrature<dim>(data.get_quad(0)),
+ update_values | update_gradients | update_hessians),
fe_val1 (data.get_dof_handler(1).get_fe(),
- Quadrature<dim>(data.get_quad(1)),
- update_values | update_gradients | update_hessians),
+ Quadrature<dim>(data.get_quad(1)),
+ update_values | update_gradients | update_hessians),
fe_val2 (data.get_dof_handler(2).get_fe(),
- Quadrature<dim>(data.get_quad(1)),
- update_values | update_gradients | update_hessians)
+ Quadrature<dim>(data.get_quad(1)),
+ update_values | update_gradients | update_hessians)
{};
void
operator () (const MatrixFree<dim,Number> &data,
- VectorType &,
- const VectorType &src,
- const std::pair<unsigned int,unsigned int> &cell_range) const
+ VectorType &,
+ const VectorType &src,
+ const std::pair<unsigned int,unsigned int> &cell_range) const
{
- FEEvaluation<dim,1,1,1,Number> fe_eval0 (data,0,0);
- FEEvaluation<dim,n_dofs_1d,n_dofs_1d,1,Number> fe_eval1 (data,1,1);
- FEEvaluation<dim,n_dofs_1d+1,n_dofs_1d,1,Number> fe_eval2 (data,2,1);
+ FEEvaluation<dim,0,1,1,Number> fe_eval0 (data,0,0);
+ FEEvaluation<dim,fe_degree,fe_degree+1,1,Number> fe_eval1 (data,1,1);
+ FEEvaluation<dim,fe_degree+1,fe_degree+1,1,Number> fe_eval2 (data,2,1);
std::vector<double> reference_values0 (fe_eval0.n_q_points);
std::vector<Tensor<1,dim> > reference_grads0 (fe_eval0.n_q_points);
std::vector<Tensor<2,dim> > reference_hess0 (fe_eval0.n_q_points);
std::vector<Tensor<2,dim> > reference_hess2 (fe_eval2.n_q_points);
for(unsigned int cell=cell_range.first;cell<cell_range.second;++cell)
{
- fe_eval0.reinit (cell);
- fe_eval0.read_dof_values(src[0]);
- fe_eval0.evaluate (true,true,true);
-
- fe_eval1.reinit (cell);
- fe_eval1.read_dof_values(src[1]);
- fe_eval1.evaluate (true,true,true);
-
- fe_eval2.reinit (cell);
- fe_eval2.read_dof_values(src[2]);
- fe_eval2.evaluate (true,true,true);
-
- // compare values with the ones the FEValues
- // gives us. Those are seen as reference
- for (unsigned int j=0; j<data.n_components_filled(cell); ++j)
- {
- // FE 0
- fe_val0.reinit (data.get_cell_iterator(cell,j,0));
- fe_val0.get_function_values(src[0], reference_values0);
- fe_val0.get_function_gradients(src[0], reference_grads0);
- fe_val0.get_function_hessians(src[0], reference_hess0);
-
- for (int q=0; q<(int)fe_eval0.n_q_points; q++)
- {
- errors[0] += std::fabs(fe_eval0.get_value(q)[j]-
- reference_values0[q]);
- for (unsigned int d=0; d<dim; ++d)
- errors[1] += std::fabs(fe_eval0.get_gradient(q)[d][j]-
- reference_grads0[q][d]);
- errors[2] += std::fabs(fe_eval0.get_laplacian(q)[j]-
- trace(reference_hess0[q]));
- total[0] += std::fabs(reference_values0[q]);
- for (unsigned int d=0; d<dim; ++d)
- total[1] += std::fabs(reference_grads0[q][d]);
- total[2] += std::fabs(fe_eval0.get_laplacian(q)[j]);
- }
-
- // FE 1
- fe_val1.reinit (data.get_cell_iterator(cell,j,1));
- fe_val1.get_function_values(src[1], reference_values1);
- fe_val1.get_function_gradients(src[1], reference_grads1);
- fe_val1.get_function_hessians(src[1], reference_hess1);
-
- for (int q=0; q<(int)fe_eval1.n_q_points; q++)
- {
- errors[3] += std::fabs(fe_eval1.get_value(q)[j]-
- reference_values1[q]);
- for (unsigned int d=0; d<dim; ++d)
- errors[4] += std::fabs(fe_eval1.get_gradient(q)[d][j]-
- reference_grads1[q][d]);
- errors[5] += std::fabs(fe_eval1.get_laplacian(q)[j]-
- trace(reference_hess1[q]));
- total[3] += std::fabs(reference_values1[q]);
- for (unsigned int d=0; d<dim; ++d)
- total[4] += std::fabs(reference_grads1[q][d]);
- total[5] += std::fabs(fe_eval1.get_laplacian(q)[j]);
- }
-
- // FE 2
- fe_val2.reinit (data.get_cell_iterator(cell,j,2));
- fe_val2.get_function_values(src[2], reference_values2);
- fe_val2.get_function_gradients(src[2], reference_grads2);
- fe_val2.get_function_hessians(src[2], reference_hess2);
-
- for (int q=0; q<(int)fe_eval2.n_q_points; q++)
- {
- errors[6] += std::fabs(fe_eval2.get_value(q)[j]-
- reference_values2[q]);
- for (unsigned int d=0; d<dim; ++d)
- errors[7] += std::fabs(fe_eval2.get_gradient(q)[d][j]-
- reference_grads2[q][d]);
- errors[8] += std::fabs(fe_eval2.get_laplacian(q)[j]-
- trace(reference_hess2[q]));
- total[6] += std::fabs(reference_values2[q]);
- for (unsigned int d=0; d<dim; ++d)
- total[7] += std::fabs(reference_grads2[q][d]);
- total[8] += std::fabs(fe_eval2.get_laplacian(q)[j]);
- }
- }
+ fe_eval0.reinit (cell);
+ fe_eval0.read_dof_values(src[0]);
+ fe_eval0.evaluate (true,true,true);
+
+ fe_eval1.reinit (cell);
+ fe_eval1.read_dof_values(src[1]);
+ fe_eval1.evaluate (true,true,true);
+
+ fe_eval2.reinit (cell);
+ fe_eval2.read_dof_values(src[2]);
+ fe_eval2.evaluate (true,true,true);
+
+ // compare values with the ones the FEValues
+ // gives us. Those are seen as reference
+ for (unsigned int j=0; j<data.n_components_filled(cell); ++j)
+ {
+ // FE 0
+ fe_val0.reinit (data.get_cell_iterator(cell,j,0));
+ fe_val0.get_function_values(src[0], reference_values0);
+ fe_val0.get_function_gradients(src[0], reference_grads0);
+ fe_val0.get_function_hessians(src[0], reference_hess0);
+
+ for (int q=0; q<(int)fe_eval0.n_q_points; q++)
+ {
+ errors[0] += std::fabs(fe_eval0.get_value(q)[j]-
+ reference_values0[q]);
+ for (unsigned int d=0; d<dim; ++d)
+ errors[1] += std::fabs(fe_eval0.get_gradient(q)[d][j]-
+ reference_grads0[q][d]);
+ errors[2] += std::fabs(fe_eval0.get_laplacian(q)[j]-
+ trace(reference_hess0[q]));
+ total[0] += std::fabs(reference_values0[q]);
+ for (unsigned int d=0; d<dim; ++d)
+ total[1] += std::fabs(reference_grads0[q][d]);
+ total[2] += std::fabs(fe_eval0.get_laplacian(q)[j]);
+ }
+
+ // FE 1
+ fe_val1.reinit (data.get_cell_iterator(cell,j,1));
+ fe_val1.get_function_values(src[1], reference_values1);
+ fe_val1.get_function_gradients(src[1], reference_grads1);
+ fe_val1.get_function_hessians(src[1], reference_hess1);
+
+ for (int q=0; q<(int)fe_eval1.n_q_points; q++)
+ {
+ errors[3] += std::fabs(fe_eval1.get_value(q)[j]-
+ reference_values1[q]);
+ for (unsigned int d=0; d<dim; ++d)
+ errors[4] += std::fabs(fe_eval1.get_gradient(q)[d][j]-
+ reference_grads1[q][d]);
+ errors[5] += std::fabs(fe_eval1.get_laplacian(q)[j]-
+ trace(reference_hess1[q]));
+ total[3] += std::fabs(reference_values1[q]);
+ for (unsigned int d=0; d<dim; ++d)
+ total[4] += std::fabs(reference_grads1[q][d]);
+ total[5] += std::fabs(fe_eval1.get_laplacian(q)[j]);
+ }
+
+ // FE 2
+ fe_val2.reinit (data.get_cell_iterator(cell,j,2));
+ fe_val2.get_function_values(src[2], reference_values2);
+ fe_val2.get_function_gradients(src[2], reference_grads2);
+ fe_val2.get_function_hessians(src[2], reference_hess2);
+
+ for (int q=0; q<(int)fe_eval2.n_q_points; q++)
+ {
+ errors[6] += std::fabs(fe_eval2.get_value(q)[j]-
+ reference_values2[q]);
+ for (unsigned int d=0; d<dim; ++d)
+ errors[7] += std::fabs(fe_eval2.get_gradient(q)[d][j]-
+ reference_grads2[q][d]);
+ errors[8] += std::fabs(fe_eval2.get_laplacian(q)[j]-
+ trace(reference_hess2[q]));
+ total[6] += std::fabs(reference_values2[q]);
+ for (unsigned int d=0; d<dim; ++d)
+ total[7] += std::fabs(reference_grads2[q][d]);
+ total[8] += std::fabs(fe_eval2.get_laplacian(q)[j]);
+ }
+ }
}
}
{
for (unsigned int i=0; i<3*3; ++i)
{
- errors[i] = 0;
- total[i] = 0;
+ errors[i] = 0;
+ total[i] = 0;
}
VectorType dst_dummy;
- data.cell_loop (&MatrixFreeTest<dim,n_dofs_1d,n_q_points_1d,Number>::operator(),
- this, dst_dummy, src);
+ data.cell_loop (&MatrixFreeTest<dim,fe_degree,n_q_points_1d,Number>::operator(),
+ this, dst_dummy, src);
- // avoid dividing by zero
+ // avoid dividing by zero
for (unsigned int i=0; i<9; ++i)
if (std::fabs(total[i]) < 1e-20)
- total[i] = 1;
+ total[i] = 1;
- // for doubles, use a stricter condition then
- // for floats for the relative error size
+ // for doubles, use a stricter condition then
+ // for floats for the relative error size
for (unsigned int i=0; i<3; ++i)
{
- if (types_are_equal<Number,double>::value == true)
- {
- deallog.threshold_double (4e-14);
- deallog << "Error function values FE " << i << ": "
- << errors[i*3+0]/total[i*3+0] << std::endl;
- deallog << "Error function gradients FE " << i << ": "
- << errors[i*3+1]/total[i*3+1] << std::endl;
-
- // need to set quite a loose tolerance because
- // FEValues approximates Hessians with finite
- // differences, which are not so
- // accurate. moreover, Hessians are quite
- // large since we chose random numbers. for
- // some elements, it might also be zero
- // (linear elements on quadrilaterals), so
- // need to check for division by 0, too.
- deallog.threshold_double (2e-6);
- const double output2 = total[i*3+2] == 0 ? 0. : errors[i*3+2] / total[i*3+2];
- deallog << "Error function Laplacians FE " << i << ": " << output2 << std::endl;
- }
- else if (types_are_equal<Number,float>::value == true)
- {
- deallog.threshold_double (1e-6);
- deallog << "Error function values FE " << i << ": "
- << errors[i*3+0]/total[i*3+0] << std::endl;
- deallog << "Error function gradients FE " << i << ": "
- << errors[i*3+1]/total[i*3+1] << std::endl;
- const double output2 = total[i*3+2] == 0 ? 0. : errors[i*3+2] / total[i*3+2];
- deallog.threshold_double (1e-6);
- deallog << "Error function Laplacians FE " << i << ": " << output2 << std::endl;
- }
+ if (types_are_equal<Number,double>::value == true)
+ {
+ deallog.threshold_double (4e-14);
+ deallog << "Error function values FE " << i << ": "
+ << errors[i*3+0]/total[i*3+0] << std::endl;
+ deallog << "Error function gradients FE " << i << ": "
+ << errors[i*3+1]/total[i*3+1] << std::endl;
+
+ // need to set quite a loose tolerance because
+ // FEValues approximates Hessians with finite
+ // differences, which are not so
+ // accurate. moreover, Hessians are quite
+ // large since we chose random numbers. for
+ // some elements, it might also be zero
+ // (linear elements on quadrilaterals), so
+ // need to check for division by 0, too.
+ deallog.threshold_double (2e-6);
+ const double output2 = total[i*3+2] == 0 ? 0. : errors[i*3+2] / total[i*3+2];
+ deallog << "Error function Laplacians FE " << i << ": " << output2 << std::endl;
+ }
+ else if (types_are_equal<Number,float>::value == true)
+ {
+ deallog.threshold_double (1e-6);
+ deallog << "Error function values FE " << i << ": "
+ << errors[i*3+0]/total[i*3+0] << std::endl;
+ deallog << "Error function gradients FE " << i << ": "
+ << errors[i*3+1]/total[i*3+1] << std::endl;
+ const double output2 = total[i*3+2] == 0 ? 0. : errors[i*3+2] / total[i*3+2];
+ deallog.threshold_double (1e-6);
+ deallog << "Error function Laplacians FE " << i << ": " << output2 << std::endl;
+ }
}
};
dof[2] = &dof2;
deallog << "Testing " << fe0.get_name() << ", " << fe1.get_name()
- << ", and " << fe1.get_name() << std::endl;
+ << ", and " << fe1.get_name() << std::endl;
//std::cout << "Number of cells: " << tria.n_active_cells() << std::endl;
std::vector<Vector<double> > src (dof.size());
for (unsigned int no=0; no<3; ++no)
for (unsigned int i=0; i<dof[no]->n_dofs(); ++i)
{
- if(constraints[no]->is_constrained(i))
- continue;
- const double entry = rand()/(double)RAND_MAX;
- src[no](i) = entry;
+ if(constraints[no]->is_constrained(i))
+ continue;
+ const double entry = rand()/(double)RAND_MAX;
+ src[no](i) = entry;
}
quad.push_back (QGauss<1>(1));
quad.push_back (QGauss<1>(fe_degree+1));
mf_data.reinit (dof, constraints, quad,
- typename MatrixFree<dim,number>::AdditionalData
- (MPI_COMM_SELF,
- MatrixFree<dim,number>::AdditionalData::none));
+ typename MatrixFree<dim,number>::AdditionalData
+ (MPI_COMM_SELF,
+ MatrixFree<dim,number>::AdditionalData::none));
}
- MatrixFreeTest<dim,fe_degree+1,fe_degree+1,number> mf (mf_data);
+ MatrixFreeTest<dim,fe_degree,fe_degree+1,number> mf (mf_data);
mf.test_functions(src);
deallog << std::endl;
}
{
deallog.attach(logfile);
deallog.depth_console(0);
- // need to set quite a loose tolerance because
- // FEValues approximates Hessians with finite
- // differences, which are not so accurate
+ // need to set quite a loose tolerance because
+ // FEValues approximates Hessians with finite
+ // differences, which are not so accurate
deallog.threshold_double(2.e-5);
deallog << std::setprecision (3);
#include "get_functions_common.h"
-template <int dim, int n_dofs_1d, typename Number>
-class MatrixFreeTestGen : public MatrixFreeTest<dim, n_dofs_1d, n_dofs_1d, Number>
+template <int dim, int fe_degree, typename Number>
+class MatrixFreeTestGen : public MatrixFreeTest<dim, fe_degree, fe_degree+1, Number>
{
public:
typedef VectorizedArray<Number> vector_t;
static const std::size_t n_vectors = VectorizedArray<Number>::n_array_elements;
MatrixFreeTestGen(const MatrixFree<dim,Number> &data,
- const Mapping<dim> &mapping):
- MatrixFreeTest<dim, n_dofs_1d, n_dofs_1d, Number>(data, mapping)
+ const Mapping<dim> &mapping):
+ MatrixFreeTest<dim, fe_degree, fe_degree+1, Number>(data, mapping)
{};
void operator () (const MatrixFree<dim,Number> &data,
- Vector<Number> &,
- const Vector<Number> &src,
- const std::pair<unsigned int,unsigned int> &cell_range) const
+ Vector<Number> &,
+ const Vector<Number> &src,
+ const std::pair<unsigned int,unsigned int> &cell_range) const
{
- FEEvaluationGeneral<dim,n_dofs_1d,n_dofs_1d,1,Number> fe_eval (data);
+ FEEvaluationGeneral<dim,fe_degree,fe_degree+1,1,Number> fe_eval (data);
for(unsigned int cell=cell_range.first;cell<cell_range.second;++cell)
{
- fe_eval.reinit (cell);
- std::vector<double> reference_values (fe_eval.n_q_points);
- std::vector<Tensor<1,dim> > reference_grads (fe_eval.n_q_points);
- std::vector<Tensor<2,dim> > reference_hess (fe_eval.n_q_points);
- fe_eval.read_dof_values(src);
- fe_eval.evaluate (true,true,true);
-
- // compare values with the ones the FEValues
- // gives us. Those are seen as reference
- for (unsigned int j=0; j<data.n_components_filled(cell); ++j)
- {
- this->fe_val.reinit (data.get_cell_iterator(cell,j));
- this->fe_val.get_function_values(src, reference_values);
- this->fe_val.get_function_gradients(src, reference_grads);
- this->fe_val.get_function_hessians(src, reference_hess);
-
- for (int q=0; q<(int)fe_eval.n_q_points; q++)
- {
- this->errors[0] += std::fabs(fe_eval.get_value(q)[j]-
- reference_values[q]);
- for (unsigned int d=0; d<dim; ++d)
- {
- this->errors[1] += std::fabs(fe_eval.get_gradient(q)[d][j]-
- reference_grads[q][d]);
- }
- this->errors[2] += std::fabs(fe_eval.get_laplacian(q)[j]-
- trace(reference_hess[q]));
- this->total[0] += std::fabs(reference_values[q]);
- for (unsigned int d=0; d<dim; ++d)
- this->total[1] += std::fabs(reference_grads[q][d]);
- this->total[2] += std::fabs(fe_eval.get_laplacian(q)[j]);
- }
- }
+ fe_eval.reinit (cell);
+ std::vector<double> reference_values (fe_eval.n_q_points);
+ std::vector<Tensor<1,dim> > reference_grads (fe_eval.n_q_points);
+ std::vector<Tensor<2,dim> > reference_hess (fe_eval.n_q_points);
+ fe_eval.read_dof_values(src);
+ fe_eval.evaluate (true,true,true);
+
+ // compare values with the ones the FEValues
+ // gives us. Those are seen as reference
+ for (unsigned int j=0; j<data.n_components_filled(cell); ++j)
+ {
+ this->fe_val.reinit (data.get_cell_iterator(cell,j));
+ this->fe_val.get_function_values(src, reference_values);
+ this->fe_val.get_function_gradients(src, reference_grads);
+ this->fe_val.get_function_hessians(src, reference_hess);
+
+ for (int q=0; q<(int)fe_eval.n_q_points; q++)
+ {
+ this->errors[0] += std::fabs(fe_eval.get_value(q)[j]-
+ reference_values[q]);
+ for (unsigned int d=0; d<dim; ++d)
+ {
+ this->errors[1] += std::fabs(fe_eval.get_gradient(q)[d][j]-
+ reference_grads[q][d]);
+ }
+ this->errors[2] += std::fabs(fe_eval.get_laplacian(q)[j]-
+ trace(reference_hess[q]));
+ this->total[0] += std::fabs(reference_values[q]);
+ for (unsigned int d=0; d<dim; ++d)
+ this->total[1] += std::fabs(reference_grads[q][d]);
+ this->total[2] += std::fabs(fe_eval.get_laplacian(q)[j]);
+ }
+ }
}
}
};
GridGenerator::hyper_ball (tria);
static const HyperBallBoundary<dim> boundary;
tria.set_boundary (0, boundary);
- // refine first and last cell
+ // refine first and last cell
tria.begin(tria.n_levels()-1)->set_refine_flag();
tria.last()->set_refine_flag();
tria.execute_coarsening_and_refinement();
deallog << "Testing " << dof.get_fe().get_name() << std::endl;
//std::cout << "Number of cells: " << dof.get_tria().n_active_cells()
- // << std::endl;
+ // << std::endl;
//std::cout << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
//std::cout << "Number of constraints: " << constraints.n_constraints() << std::endl;
Vector<number> solution (dof.n_dofs());
- // create vector with random entries
+ // create vector with random entries
for (unsigned int i=0; i<dof.n_dofs(); ++i)
{
if(constraints.is_constrained(i))
- continue;
+ continue;
const double entry = rand()/(double)RAND_MAX;
solution(i) = entry;
}
MatrixFree<dim,number> mf_data;
deallog << "Test with fe_degree " << fe_degree
- << std::endl;
+ << std::endl;
const QGauss<1> quad (fe_degree+1);
MappingQ<dim> mapping (4);
typename MatrixFree<dim,number>::AdditionalData data;
data.tasks_parallel_scheme = MatrixFree<dim,number>::AdditionalData::none;
data.mapping_update_flags = update_gradients | update_second_derivatives;
mf_data.reinit (mapping, dof, constraints, quad, data);
- MatrixFreeTestGen<dim,fe_degree+1,number> mf (mf_data, mapping);
+ MatrixFreeTestGen<dim,fe_degree,number> mf (mf_data, mapping);
mf.test_functions (solution);
}
template <int dim, int fe_degree, int n_q_points_1d, typename number>
void sub_test (const DoFHandler<dim> &dof,
- const ConstraintMatrix &constraints,
- MatrixFree<dim,number> &mf_data,
- Vector<number> &solution)
+ const ConstraintMatrix &constraints,
+ MatrixFree<dim,number> &mf_data,
+ Vector<number> &solution)
{
deallog << "Test with fe_degree " << fe_degree
- << ", n_q_points_1d: " << (n_q_points_1d) << std::endl;
+ << ", n_q_points_1d: " << (n_q_points_1d) << std::endl;
const QGauss<1> quad (n_q_points_1d);
MappingQ<dim> mapping (2);
typename MatrixFree<dim,number>::AdditionalData data;
data.tasks_parallel_scheme = MatrixFree<dim,number>::AdditionalData::none;
data.mapping_update_flags = update_gradients | update_second_derivatives;
mf_data.reinit (mapping, dof, constraints, quad, data);
- MatrixFreeTest<dim,fe_degree+1,n_q_points_1d,number> mf (mf_data, mapping);
+ MatrixFreeTest<dim,fe_degree,n_q_points_1d,number> mf (mf_data, mapping);
mf.test_functions (solution);
}
GridGenerator::hyper_ball (tria);
static const HyperBallBoundary<dim> boundary;
tria.set_boundary (0, boundary);
- // refine first and last cell
+ // refine first and last cell
tria.begin(tria.n_levels()-1)->set_refine_flag();
tria.last()->set_refine_flag();
tria.execute_coarsening_and_refinement();
constraints.close();
- // in the other functions, use do_test in
- // get_functions_common, but here we have to
- // manually choose non-rectangular tests.
+ // in the other functions, use do_test in
+ // get_functions_common, but here we have to
+ // manually choose non-rectangular tests.
deallog << "Testing " << dof.get_fe().get_name() << std::endl;
//std::cout << "Number of cells: " << dof.get_tria().n_active_cells()
- // << std::endl;
+ // << std::endl;
//std::cout << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
//std::cout << "Number of constraints: " << constraints.n_constraints() << std::endl;
Vector<number> solution (dof.n_dofs());
- // create vector with random entries
+ // create vector with random entries
for (unsigned int i=0; i<dof.n_dofs(); ++i)
{
if(constraints.is_constrained(i))
- continue;
+ continue;
const double entry = rand()/(double)RAND_MAX;
solution(i) = entry;
}
MatrixFree<dim,number> mf_data;
if (fe_degree > 1)
sub_test <dim,fe_degree,fe_degree-1,number> (dof, constraints, mf_data,
- solution);
+ solution);
sub_test <dim,fe_degree,fe_degree,number> (dof, constraints, mf_data,
- solution);
+ solution);
sub_test <dim,fe_degree,fe_degree+2,number> (dof, constraints, mf_data,
- solution);
+ solution);
if (dim == 2)
sub_test <dim,fe_degree,fe_degree+3,number> (dof, constraints, mf_data,
- solution);
+ solution);
}
std::ofstream logfile("get_functions_variants/output");
-template <int dim, int n_dofs_1d, typename Number>
+template <int dim, int fe_degree, typename Number>
class MatrixFreeTest
{
public:
{};
void operator () (const MatrixFree<dim,Number> &data,
- VectorType &dst,
- const VectorType &src,
- const std::pair<unsigned int,unsigned int> &cell_range) const;
+ VectorType &dst,
+ const VectorType &src,
+ const std::pair<unsigned int,unsigned int> &cell_range) const;
void test_functions (const VectorType &src) const
{
for (unsigned int i=0; i<5; ++i)
errors[i] = 0;
- data.cell_loop (&MatrixFreeTest<dim,n_dofs_1d,Number>::operator(), this,
- const_cast<VectorType&>(src), src);
+ data.cell_loop (&MatrixFreeTest<dim,fe_degree,Number>::operator(), this,
+ const_cast<VectorType&>(src), src);
deallog << "Error val, function values alone: "
- << errors[0] << std::endl;
+ << errors[0] << std::endl;
deallog << "Error grad, function gradients alone: "
- << errors[1] << std::endl;
+ << errors[1] << std::endl;
deallog << "Error val, function values and gradients alone: "
- << errors[2] << std::endl;
+ << errors[2] << std::endl;
deallog << "Error grad, function values and gradients alone: "
- << errors[3] << std::endl;
+ << errors[3] << std::endl;
deallog << "Error Lapl, function Laplacians alone: "
- << errors[4] << std::endl;
+ << errors[4] << std::endl;
};
private:
-template <int dim, int n_dofs_1d, typename Number>
-void MatrixFreeTest<dim,n_dofs_1d,Number>::
+template <int dim, int fe_degree, typename Number>
+void MatrixFreeTest<dim,fe_degree,Number>::
operator () (const MatrixFree<dim,Number> &data,
- VectorType &,
- const VectorType &src,
- const std::pair<unsigned int,unsigned int> &cell_range) const
+ VectorType &,
+ const VectorType &src,
+ const std::pair<unsigned int,unsigned int> &cell_range) const
{
- FEEvaluation<dim,n_dofs_1d,n_dofs_1d,1,Number> fe_eval (data);
- FEEvaluation<dim,n_dofs_1d,n_dofs_1d,1,Number> fe_eval2 (data);
- FEEvaluation<dim,n_dofs_1d,n_dofs_1d,1,Number> fe_eval3 (data);
- FEEvaluation<dim,n_dofs_1d,n_dofs_1d,1,Number> fe_eval4 (data);
- FEEvaluation<dim,n_dofs_1d,n_dofs_1d,1,Number> fe_eval5 (data);
+ FEEvaluation<dim,fe_degree,fe_degree+1,1,Number> fe_eval (data);
+ FEEvaluation<dim,fe_degree,fe_degree+1,1,Number> fe_eval2 (data);
+ FEEvaluation<dim,fe_degree,fe_degree+1,1,Number> fe_eval3 (data);
+ FEEvaluation<dim,fe_degree,fe_degree+1,1,Number> fe_eval4 (data);
+ FEEvaluation<dim,fe_degree,fe_degree+1,1,Number> fe_eval5 (data);
for(unsigned int cell=cell_range.first;cell<cell_range.second;++cell)
{
fe_eval.reinit (cell);
fe_eval.read_dof_values(src);
fe_eval.evaluate (true,true,true);
- // only for values (additional test)
+ // only for values (additional test)
fe_eval2.reinit (cell);
fe_eval2.read_dof_values(src);
fe_eval2.evaluate (true,false,false);
- // only gradients
+ // only gradients
fe_eval3.reinit (cell);
fe_eval3.read_dof_values(src);
fe_eval3.evaluate (false,true,false);
- // only values and gradients
+ // only values and gradients
fe_eval4.reinit (cell);
fe_eval4.read_dof_values(src);
fe_eval4.evaluate(true,true,false);
- // only laplacians
+ // only laplacians
fe_eval5.reinit (cell);
fe_eval5.read_dof_values(src);
fe_eval5.evaluate (false,false,true);
- // compare values with the values that we get
- // when expanding the full
- // FEEvaluations. Those are tested in other
- // functions and seen as reference here
+ // compare values with the values that we get
+ // when expanding the full
+ // FEEvaluations. Those are tested in other
+ // functions and seen as reference here
for (unsigned int q=0; q<fe_eval.n_q_points; ++q)
- for (unsigned int j=0; j<n_vectors; ++j)
- {
- errors[0] += std::fabs(fe_eval.get_value(q)[j]-
- fe_eval2.get_value(q)[j]);
- errors[2] += std::fabs(fe_eval.get_value(q)[j]-
- fe_eval4.get_value(q)[j]);
- for (unsigned int d=0; d<dim; ++d)
- {
- errors[1] += std::fabs(fe_eval.get_gradient(q)[d][j]-
- fe_eval3.get_gradient(q)[d][j]);
- errors[3] += std::fabs(fe_eval.get_gradient(q)[d][j]-
- fe_eval4.get_gradient(q)[d][j]);
- }
- errors[4] += std::fabs(fe_eval.get_laplacian(q)[j]-
- fe_eval5.get_laplacian(q)[j]);
- }
+ for (unsigned int j=0; j<n_vectors; ++j)
+ {
+ errors[0] += std::fabs(fe_eval.get_value(q)[j]-
+ fe_eval2.get_value(q)[j]);
+ errors[2] += std::fabs(fe_eval.get_value(q)[j]-
+ fe_eval4.get_value(q)[j]);
+ for (unsigned int d=0; d<dim; ++d)
+ {
+ errors[1] += std::fabs(fe_eval.get_gradient(q)[d][j]-
+ fe_eval3.get_gradient(q)[d][j]);
+ errors[3] += std::fabs(fe_eval.get_gradient(q)[d][j]-
+ fe_eval4.get_gradient(q)[d][j]);
+ }
+ errors[4] += std::fabs(fe_eval.get_laplacian(q)[j]-
+ fe_eval5.get_laplacian(q)[j]);
+ }
}
}
Vector<double> solution_dist (dof.n_dofs());
- // create vector with random entries
+ // create vector with random entries
for (unsigned int i=0; i<dof.n_dofs(); ++i)
{
const double entry = rand()/(double)RAND_MAX;
mf_data.reinit (dof, constraints, quad, data);
}
- MatrixFreeTest<dim,fe_degree+1,double> mf (mf_data);
+ MatrixFreeTest<dim,fe_degree,double> mf (mf_data);
mf.test_functions(solution_dist);
deallog << std::endl;
}
std::ofstream logfile("get_values_plain/output");
-template <int dim, int n_dofs_1d, int n_q_points_1d=n_dofs_1d, typename Number=double>
+template <int dim, int fe_degree, int n_q_points_1d=fe_degree+1, typename Number=double>
class MatrixFreeTest
{
public:
data (data_in)
{};
- // make function virtual to allow derived
- // classes to define a different function
+ // make function virtual to allow derived
+ // classes to define a different function
virtual void
operator () (const MatrixFree<dim,Number> &data,
- Vector<Number> &,
- const Vector<Number> &src,
- const std::pair<unsigned int,unsigned int> &cell_range) const
+ Vector<Number> &,
+ const Vector<Number> &src,
+ const std::pair<unsigned int,unsigned int> &cell_range) const
{
typedef VectorizedArray<Number> vector_t;
const unsigned int n_vectors = sizeof(vector_t)/sizeof(Number);
- FEEvaluation<dim,n_dofs_1d,n_q_points_1d,1,Number> fe_eval (data);
- FEEvaluation<dim,n_dofs_1d,n_q_points_1d,1,Number> fe_eval_plain (data);
+ FEEvaluation<dim,fe_degree,n_q_points_1d,1,Number> fe_eval (data);
+ FEEvaluation<dim,fe_degree,n_q_points_1d,1,Number> fe_eval_plain (data);
for(unsigned int cell=cell_range.first;cell<cell_range.second;++cell)
{
- fe_eval.reinit (cell);
- fe_eval.read_dof_values(src);
-
- fe_eval_plain.reinit (cell);
- fe_eval_plain.read_dof_values_plain(src);
-
- for (unsigned int i=0; i<fe_eval.dofs_per_cell; ++i)
- for (unsigned int j=0; j<n_vectors; ++j)
- {
- error += std::fabs(fe_eval.get_dof_value(i)[j]-
- fe_eval_plain.get_dof_value(i)[j]);
- total += std::fabs(fe_eval.get_dof_value(i)[j]);
- }
+ fe_eval.reinit (cell);
+ fe_eval.read_dof_values(src);
+
+ fe_eval_plain.reinit (cell);
+ fe_eval_plain.read_dof_values_plain(src);
+
+ for (unsigned int i=0; i<fe_eval.dofs_per_cell; ++i)
+ for (unsigned int j=0; j<n_vectors; ++j)
+ {
+ error += std::fabs(fe_eval.get_dof_value(i)[j]-
+ fe_eval_plain.get_dof_value(i)[j]);
+ total += std::fabs(fe_eval.get_dof_value(i)[j]);
+ }
}
}
error = 0;
total = 0;
Vector<Number> dst_dummy;
- data.cell_loop (&MatrixFreeTest<dim,n_dofs_1d,n_q_points_1d,Number>::operator(),
- this, dst_dummy, src);
+ data.cell_loop (&MatrixFreeTest<dim,fe_degree,n_q_points_1d,Number>::operator(),
+ this, dst_dummy, src);
deallog.threshold_double(1e-10);
deallog << "Error read_dof_values vs read_dof_values_plain: "
- << error/total << std::endl << std::endl;
+ << error/total << std::endl << std::endl;
};
protected:
template <int dim, int fe_degree, typename number>
void do_test (const DoFHandler<dim> &dof,
- const ConstraintMatrix&constraints)
+ const ConstraintMatrix&constraints)
{
deallog << "Testing " << dof.get_fe().get_name() << std::endl;
//std::cout << "Number of cells: " << dof.get_tria().n_active_cells()
- // << std::endl;
+ // << std::endl;
//std::cout << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
//std::cout << "Number of constraints: " << constraints.n_constraints() << std::endl;
Vector<number> solution (dof.n_dofs());
- // create vector with random entries
+ // create vector with random entries
for (unsigned int i=0; i<dof.n_dofs(); ++i)
{
if(constraints.is_constrained(i))
- continue;
+ continue;
const double entry = rand()/(double)RAND_MAX;
solution(i) = entry;
}
mf_data.reinit (dof, constraints, quad, data);
}
- MatrixFreeTest<dim,fe_degree+1,fe_degree+1,number> mf (mf_data);
+ MatrixFreeTest<dim,fe_degree,fe_degree+1,number> mf (mf_data);
mf.test_functions(solution);
}
tria.set_boundary (0, boundary);
tria.set_boundary (1, boundary);
- // refine a few cells
+ // refine a few cells
for (unsigned int i=0; i<11-3*dim; ++i)
{
typename Triangulation<dim>::active_cell_iterator
- cell = tria.begin_active (),
- endc = tria.end();
+ cell = tria.begin_active (),
+ endc = tria.end();
unsigned int counter = 0;
for (; cell!=endc; ++cell, ++counter)
- if (counter % (7-i) == 0)
- cell->set_refine_flag();
+ if (counter % (7-i) == 0)
+ cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
}
ConstraintMatrix constraints;
DoFTools::make_hanging_node_constraints(dof, constraints);
VectorTools::interpolate_boundary_values (dof, 1, ZeroFunction<dim>(),
- constraints);
+ constraints);
constraints.close();
do_test<dim, fe_degree, double> (dof, constraints);
std::ofstream logfile("integrate_functions/output");
-template <int dim, int n_dofs_1d, typename Number>
+template <int dim, int fe_degree, typename Number>
class MatrixFreeTest
{
public:
MatrixFreeTest(const MatrixFree<dim,Number> &data_in):
data (data_in),
fe_val (data.get_dof_handler().get_fe(),
- Quadrature<dim>(data.get_quad(0)),
- update_values | update_gradients | update_JxW_values)
+ Quadrature<dim>(data.get_quad(0)),
+ update_values | update_gradients | update_JxW_values)
{};
void operator () (const MatrixFree<dim,Number> &data,
- VectorType &dst,
- const VectorType &src,
- const std::pair<unsigned int,unsigned int> &cell_range) const;
+ VectorType &dst,
+ const VectorType &src,
+ const std::pair<unsigned int,unsigned int> &cell_range) const;
void test_functions (Vector<Number> &dst,
- Vector<Number> &dst_deal) const
+ Vector<Number> &dst_deal) const
{
dst = 0;
dst_deal = 0;
dst_data[0] = &dst;
dst_data[1] = &dst_deal;
VectorType src_dummy;
- data.cell_loop (&MatrixFreeTest<dim,n_dofs_1d,Number>::operator(), this,
- dst_data, src_dummy);
+ data.cell_loop (&MatrixFreeTest<dim,fe_degree,Number>::operator(), this,
+ dst_data, src_dummy);
};
private:
-template <int dim, int n_dofs_1d, typename Number>
-void MatrixFreeTest<dim,n_dofs_1d,Number>::
+template <int dim, int fe_degree, typename Number>
+void MatrixFreeTest<dim,fe_degree,Number>::
operator () (const MatrixFree<dim,Number> &data,
- std::vector<Vector<Number>*> &dst,
- const std::vector<Vector<Number>*> &,
- const std::pair<unsigned int,unsigned int> &cell_range) const
+ std::vector<Vector<Number>*> &dst,
+ const std::vector<Vector<Number>*> &,
+ const std::pair<unsigned int,unsigned int> &cell_range) const
{
- FEEvaluation<dim,n_dofs_1d,n_dofs_1d,1,Number> fe_eval (data);
+ FEEvaluation<dim,fe_degree,fe_degree+1,1,Number> fe_eval (data);
const unsigned int n_q_points = fe_eval.n_q_points;
const unsigned int dofs_per_cell = fe_eval.dofs_per_cell;
AlignedVector<vector_t> values (n_q_points);
for(unsigned int cell=cell_range.first;cell<cell_range.second;++cell)
{
fe_eval.reinit(cell);
- // compare values with the ones the FEValues
- // gives us. Those are seen as reference
+ // compare values with the ones the FEValues
+ // gives us. Those are seen as reference
for (unsigned int j=0; j<data.n_components_filled(cell); ++j)
- {
- // generate random numbers at quadrature
- // points and test them with basis functions
- // and their gradients
- for (unsigned int q=0; q<n_q_points; ++q)
- {
- values[q][j] = rand()/(double)RAND_MAX;
- for (unsigned int d=0; d<dim; ++d)
- gradients[q*dim+d][j] = -1. + 2. * (rand()/(double)RAND_MAX);
- }
- fe_val.reinit (data.get_cell_iterator(cell,j));
- data.get_cell_iterator(cell,j)->get_dof_indices(dof_indices);
-
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- {
- double sum = 0.;
- for (unsigned int q=0; q<n_q_points; ++q)
- {
- sum += values[q][j] * fe_val.shape_value(i,q) * fe_val.JxW(q);
- for (unsigned int d=0; d<dim; ++d)
- sum += (gradients[q*dim+d][j] * fe_val.shape_grad(i,q)[d] *
- fe_val.JxW(q));
- }
- (*dst[1])(dof_indices[i]) += sum;
- }
- }
+ {
+ // generate random numbers at quadrature
+ // points and test them with basis functions
+ // and their gradients
+ for (unsigned int q=0; q<n_q_points; ++q)
+ {
+ values[q][j] = rand()/(double)RAND_MAX;
+ for (unsigned int d=0; d<dim; ++d)
+ gradients[q*dim+d][j] = -1. + 2. * (rand()/(double)RAND_MAX);
+ }
+ fe_val.reinit (data.get_cell_iterator(cell,j));
+ data.get_cell_iterator(cell,j)->get_dof_indices(dof_indices);
+
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ double sum = 0.;
+ for (unsigned int q=0; q<n_q_points; ++q)
+ {
+ sum += values[q][j] * fe_val.shape_value(i,q) * fe_val.JxW(q);
+ for (unsigned int d=0; d<dim; ++d)
+ sum += (gradients[q*dim+d][j] * fe_val.shape_grad(i,q)[d] *
+ fe_val.JxW(q));
+ }
+ (*dst[1])(dof_indices[i]) += sum;
+ }
+ }
for (unsigned int q=0; q<n_q_points; ++q)
- {
- fe_eval.submit_value (values[q], q);
- Tensor<1,dim,vector_t> submit (false);
- for (unsigned int d=0; d<dim; ++d)
- submit[d] = gradients[q*dim+d];
- fe_eval.submit_gradient (submit, q);
- }
+ {
+ fe_eval.submit_value (values[q], q);
+ Tensor<1,dim,vector_t> submit (false);
+ for (unsigned int d=0; d<dim; ++d)
+ submit[d] = gradients[q*dim+d];
+ fe_eval.submit_gradient (submit, q);
+ }
fe_eval.integrate (true,true);
fe_eval.distribute_local_to_global (*dst[0]);
}
cell = tria.begin_active ();
unsigned int counter = 0;
for (; cell!=endc; ++cell, ++counter)
- if (counter % (7-i) == 0)
- cell->set_refine_flag();
+ if (counter % (7-i) == 0)
+ cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
}
{
const QGauss<1> quad (fe_degree+1);
mf_data.reinit (dof, constraints, quad,
- typename MatrixFree<dim,number>::AdditionalData(MPI_COMM_SELF,MatrixFree<dim,number>::AdditionalData::none));
+ typename MatrixFree<dim,number>::AdditionalData(MPI_COMM_SELF,MatrixFree<dim,number>::AdditionalData::none));
}
- MatrixFreeTest<dim,fe_degree+1,number> mf (mf_data);
+ MatrixFreeTest<dim,fe_degree,number> mf (mf_data);
Vector<number> solution (dof.n_dofs());
Vector<number> solution_dist (dof.n_dofs());
std::ofstream logfile("integrate_functions_multife/output");
-template <int dim, int n_dofs_1d, typename Number>
+template <int dim, int fe_degree, typename Number>
class MatrixFreeTest
{
public:
MatrixFreeTest(const MatrixFree<dim,Number> &data_in):
data (data_in),
fe_val0 (data.get_dof_handler(0).get_fe(),
- Quadrature<dim>(data.get_quad(0)),
- update_values | update_gradients | update_JxW_values),
+ Quadrature<dim>(data.get_quad(0)),
+ update_values | update_gradients | update_JxW_values),
fe_val01 (data.get_dof_handler(0).get_fe(),
- Quadrature<dim>(data.get_quad(1)),
- update_values | update_gradients | update_JxW_values),
+ Quadrature<dim>(data.get_quad(1)),
+ update_values | update_gradients | update_JxW_values),
fe_val1 (data.get_dof_handler(1).get_fe(),
- Quadrature<dim>(data.get_quad(1)),
- update_values | update_gradients | update_JxW_values)
+ Quadrature<dim>(data.get_quad(1)),
+ update_values | update_gradients | update_JxW_values)
{};
void operator () (const MatrixFree<dim,Number> &data,
- VectorType &dst,
- const VectorType &src,
- const std::pair<unsigned int,unsigned int> &cell_range) const;
+ VectorType &dst,
+ const VectorType &src,
+ const std::pair<unsigned int,unsigned int> &cell_range) const;
void test_functions (VectorType &dst) const
{
for (unsigned int comp=0; comp<dst.size(); ++comp)
dst[comp] = 0;
VectorType src_dummy;
- data.cell_loop (&MatrixFreeTest<dim,n_dofs_1d,Number>::operator(), this,
- dst, src_dummy);
+ data.cell_loop (&MatrixFreeTest<dim,fe_degree,Number>::operator(), this,
+ dst, src_dummy);
};
private:
-template <int dim, int n_dofs_1d, typename Number>
-void MatrixFreeTest<dim,n_dofs_1d,Number>::
+template <int dim, int fe_degree, typename Number>
+void MatrixFreeTest<dim,fe_degree,Number>::
operator () (const MatrixFree<dim,Number> &data,
- std::vector<Vector<Number> > &dst,
- const std::vector<Vector<Number> > &,
- const std::pair<unsigned int,unsigned int> &cell_range) const
+ std::vector<Vector<Number> > &dst,
+ const std::vector<Vector<Number> > &,
+ const std::pair<unsigned int,unsigned int> &cell_range) const
{
- FEEvaluation<dim,n_dofs_1d,n_dofs_1d,1,Number> fe_eval0 (data, 0, 0);
- FEEvaluation<dim,n_dofs_1d+1,n_dofs_1d+1,1,Number> fe_eval1 (data, 1, 1);
- FEEvaluation<dim,n_dofs_1d,n_dofs_1d+1,1,Number> fe_eval01 (data, 0, 1);
+ FEEvaluation<dim,fe_degree,fe_degree+1,1,Number> fe_eval0 (data, 0, 0);
+ FEEvaluation<dim,fe_degree+1,fe_degree+2,1,Number> fe_eval1 (data, 1, 1);
+ FEEvaluation<dim,fe_degree,fe_degree+2,1,Number> fe_eval01 (data, 0, 1);
const unsigned int n_q_points0 = fe_eval0.n_q_points;
const unsigned int n_q_points1 = fe_eval1.n_q_points;
const unsigned int dofs_per_cell0 = fe_eval0.dofs_per_cell;
fe_eval1.reinit(cell);
fe_eval01.reinit(cell);
- // compare values with the ones the FEValues
- // gives us. Those are seen as reference
+ // compare values with the ones the FEValues
+ // gives us. Those are seen as reference
for (unsigned int j=0; j<data.n_components_filled(cell); ++j)
- {
- // FE 0, Quad 0
- // generate random numbers at quadrature
- // points and test them with basis functions
- // and their gradients
- for (unsigned int q=0; q<n_q_points0; ++q)
- {
- values0[q][j] = rand()/(double)RAND_MAX;
- for (unsigned int d=0; d<dim; ++d)
- gradients0[q*dim+d][j] = -1. + 2. * (rand()/(double)RAND_MAX);
- }
- fe_val0.reinit (data.get_cell_iterator(cell,j,0));
- data.get_cell_iterator(cell,j,0)->get_dof_indices(dof_indices0);
-
- for (unsigned int i=0; i<dofs_per_cell0; ++i)
- {
- double sum = 0.;
- for (unsigned int q=0; q<n_q_points0; ++q)
- {
- sum += values0[q][j] * fe_val0.shape_value(i,q) * fe_val0.JxW(q);
- for (unsigned int d=0; d<dim; ++d)
- sum += (gradients0[q*dim+d][j] * fe_val0.shape_grad(i,q)[d] *
- fe_val0.JxW(q));
- }
- dst[0+1](dof_indices0[i]) += sum;
- }
-
- // FE 1, Quad 1
- fe_val1.reinit (data.get_cell_iterator(cell,j,1));
- data.get_cell_iterator(cell,j,1)->get_dof_indices(dof_indices1);
-
- for (unsigned int q=0; q<n_q_points1; ++q)
- {
- values1[q][j] = rand()/(double)RAND_MAX;
- for (unsigned int d=0; d<dim; ++d)
- gradients1[q*dim+d][j] = -1. + 2. * (rand()/(double)RAND_MAX);
- }
- for (unsigned int i=0; i<dofs_per_cell1; ++i)
- {
- double sum = 0.;
- for (unsigned int q=0; q<n_q_points1; ++q)
- {
- sum += values1[q][j] * fe_val1.shape_value(i,q) * fe_val1.JxW(q);
- for (unsigned int d=0; d<dim; ++d)
- sum += (gradients1[q*dim+d][j] * fe_val1.shape_grad(i,q)[d] *
- fe_val1.JxW(q));
- }
- dst[2+1](dof_indices1[i]) += sum;
- }
-
- // FE 0, Quad 1
- fe_val01.reinit (data.get_cell_iterator(cell,j,0));
- for (unsigned int i=0; i<dofs_per_cell0; ++i)
- {
- double sum = 0.;
- for (unsigned int q=0; q<n_q_points1; ++q)
- {
- sum += values1[q][j] * fe_val01.shape_value(i,q) * fe_val01.JxW(q);
- for (unsigned int d=0; d<dim; ++d)
- sum += (gradients1[q*dim+d][j] * fe_val01.shape_grad(i,q)[d] *
- fe_val01.JxW(q));
- }
- dst[4+1](dof_indices0[i]) += sum;
- }
- }
-
- // FE 0, Quad 0
+ {
+ // FE 0, Quad 0
+ // generate random numbers at quadrature
+ // points and test them with basis functions
+ // and their gradients
+ for (unsigned int q=0; q<n_q_points0; ++q)
+ {
+ values0[q][j] = rand()/(double)RAND_MAX;
+ for (unsigned int d=0; d<dim; ++d)
+ gradients0[q*dim+d][j] = -1. + 2. * (rand()/(double)RAND_MAX);
+ }
+ fe_val0.reinit (data.get_cell_iterator(cell,j,0));
+ data.get_cell_iterator(cell,j,0)->get_dof_indices(dof_indices0);
+
+ for (unsigned int i=0; i<dofs_per_cell0; ++i)
+ {
+ double sum = 0.;
+ for (unsigned int q=0; q<n_q_points0; ++q)
+ {
+ sum += values0[q][j] * fe_val0.shape_value(i,q) * fe_val0.JxW(q);
+ for (unsigned int d=0; d<dim; ++d)
+ sum += (gradients0[q*dim+d][j] * fe_val0.shape_grad(i,q)[d] *
+ fe_val0.JxW(q));
+ }
+ dst[0+1](dof_indices0[i]) += sum;
+ }
+
+ // FE 1, Quad 1
+ fe_val1.reinit (data.get_cell_iterator(cell,j,1));
+ data.get_cell_iterator(cell,j,1)->get_dof_indices(dof_indices1);
+
+ for (unsigned int q=0; q<n_q_points1; ++q)
+ {
+ values1[q][j] = rand()/(double)RAND_MAX;
+ for (unsigned int d=0; d<dim; ++d)
+ gradients1[q*dim+d][j] = -1. + 2. * (rand()/(double)RAND_MAX);
+ }
+ for (unsigned int i=0; i<dofs_per_cell1; ++i)
+ {
+ double sum = 0.;
+ for (unsigned int q=0; q<n_q_points1; ++q)
+ {
+ sum += values1[q][j] * fe_val1.shape_value(i,q) * fe_val1.JxW(q);
+ for (unsigned int d=0; d<dim; ++d)
+ sum += (gradients1[q*dim+d][j] * fe_val1.shape_grad(i,q)[d] *
+ fe_val1.JxW(q));
+ }
+ dst[2+1](dof_indices1[i]) += sum;
+ }
+
+ // FE 0, Quad 1
+ fe_val01.reinit (data.get_cell_iterator(cell,j,0));
+ for (unsigned int i=0; i<dofs_per_cell0; ++i)
+ {
+ double sum = 0.;
+ for (unsigned int q=0; q<n_q_points1; ++q)
+ {
+ sum += values1[q][j] * fe_val01.shape_value(i,q) * fe_val01.JxW(q);
+ for (unsigned int d=0; d<dim; ++d)
+ sum += (gradients1[q*dim+d][j] * fe_val01.shape_grad(i,q)[d] *
+ fe_val01.JxW(q));
+ }
+ dst[4+1](dof_indices0[i]) += sum;
+ }
+ }
+
+ // FE 0, Quad 0
for (unsigned int q=0; q<n_q_points0; ++q)
- {
- fe_eval0.submit_value (values0[q], q);
- Tensor<1,dim,vector_t> submit (false);
- for (unsigned int d=0; d<dim; ++d)
- submit[d] = gradients0[q*dim+d];
- fe_eval0.submit_gradient (submit, q);
- }
+ {
+ fe_eval0.submit_value (values0[q], q);
+ Tensor<1,dim,vector_t> submit (false);
+ for (unsigned int d=0; d<dim; ++d)
+ submit[d] = gradients0[q*dim+d];
+ fe_eval0.submit_gradient (submit, q);
+ }
fe_eval0.integrate (true,true);
fe_eval0.distribute_local_to_global (dst[0]);
- // FE 1, Quad 1
+ // FE 1, Quad 1
for (unsigned int q=0; q<n_q_points1; ++q)
- {
- fe_eval1.submit_value (values1[q], q);
- Tensor<1,dim,vector_t> submit (false);
- for (unsigned int d=0; d<dim; ++d)
- submit[d] = gradients1[q*dim+d];
- fe_eval1.submit_gradient (submit, q);
- }
+ {
+ fe_eval1.submit_value (values1[q], q);
+ Tensor<1,dim,vector_t> submit (false);
+ for (unsigned int d=0; d<dim; ++d)
+ submit[d] = gradients1[q*dim+d];
+ fe_eval1.submit_gradient (submit, q);
+ }
fe_eval1.integrate (true,true);
fe_eval1.distribute_local_to_global (dst[2]);
- // FE 0, Quad 1
+ // FE 0, Quad 1
for (unsigned int q=0; q<n_q_points1; ++q)
- {
- fe_eval01.submit_value (values1[q], q);
- Tensor<1,dim,vector_t> submit (false);
- for (unsigned int d=0; d<dim; ++d)
- submit[d] = gradients1[q*dim+d];
- fe_eval01.submit_gradient (submit, q);
- }
+ {
+ fe_eval01.submit_value (values1[q], q);
+ Tensor<1,dim,vector_t> submit (false);
+ for (unsigned int d=0; d<dim; ++d)
+ submit[d] = gradients1[q*dim+d];
+ fe_eval01.submit_gradient (submit, q);
+ }
fe_eval01.integrate (true,true);
fe_eval01.distribute_local_to_global (dst[4]);
}
template <int dim, int fe_degree, typename number>
void test ()
{
- // create hyper ball geometry and refine some
- // cells
+ // create hyper ball geometry and refine some
+ // cells
Triangulation<dim> tria;
GridGenerator::hyper_ball (tria);
static const HyperBallBoundary<dim> boundary;
cell = tria.begin_active ();
unsigned int counter = 0;
for (; cell!=endc; ++cell, ++counter)
- if (counter % (7-i) == 0)
- cell->set_refine_flag();
+ if (counter % (7-i) == 0)
+ cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
}
for (unsigned int no=0; no<2; ++no)
quad.push_back(QGauss<1>(fe_degree+1+no));
mf_data.reinit (dof, constraints, quad,
- typename MatrixFree<dim,number>::AdditionalData(MPI_COMM_SELF,MatrixFree<dim,number>::AdditionalData::none));
+ typename MatrixFree<dim,number>::AdditionalData(MPI_COMM_SELF,MatrixFree<dim,number>::AdditionalData::none));
}
- MatrixFreeTest<dim,fe_degree+1,number> mf (mf_data);
+ MatrixFreeTest<dim,fe_degree,number> mf (mf_data);
mf.test_functions(dst);
constraints[0]->condense(dst[1]);
std::ofstream logfile("integrate_functions_multife2/output");
-template <int dim, int n_dofs_1d, typename Number>
+template <int dim, int fe_degree, typename Number>
class MatrixFreeTest
{
public:
MatrixFreeTest(const MatrixFree<dim,Number> &data_in):
data (data_in),
fe_val0 (data.get_dof_handler(0).get_fe(),
- Quadrature<dim>(data.get_quad(0)),
- update_values | update_gradients | update_JxW_values),
+ Quadrature<dim>(data.get_quad(0)),
+ update_values | update_gradients | update_JxW_values),
fe_val01 (data.get_dof_handler(0).get_fe(),
- Quadrature<dim>(data.get_quad(1)),
- update_values | update_gradients | update_JxW_values),
+ Quadrature<dim>(data.get_quad(1)),
+ update_values | update_gradients | update_JxW_values),
fe_val1 (data.get_dof_handler(1).get_fe(),
- Quadrature<dim>(data.get_quad(1)),
- update_values | update_gradients | update_JxW_values)
+ Quadrature<dim>(data.get_quad(1)),
+ update_values | update_gradients | update_JxW_values)
{};
void operator () (const MatrixFree<dim,Number> &data,
- VectorType &dst,
- const VectorType &src,
- const std::pair<unsigned int,unsigned int> &cell_range) const;
+ VectorType &dst,
+ const VectorType &src,
+ const std::pair<unsigned int,unsigned int> &cell_range) const;
void test_functions (VectorType &dst) const
{
for (unsigned int comp=0; comp<dst.size(); ++comp)
dst[comp] = 0;
VectorType src_dummy;
- data.cell_loop (&MatrixFreeTest<dim,n_dofs_1d,Number>::operator(), this,
- dst, src_dummy);
+ data.cell_loop (&MatrixFreeTest<dim,fe_degree,Number>::operator(), this,
+ dst, src_dummy);
};
private:
-template <int dim, int n_dofs_1d, typename Number>
-void MatrixFreeTest<dim,n_dofs_1d,Number>::
+template <int dim, int fe_degree, typename Number>
+void MatrixFreeTest<dim,fe_degree,Number>::
operator () (const MatrixFree<dim,Number> &data,
- std::vector<Vector<Number> > &dst,
- const std::vector<Vector<Number> > &,
- const std::pair<unsigned int,unsigned int> &cell_range) const
+ std::vector<Vector<Number> > &dst,
+ const std::vector<Vector<Number> > &,
+ const std::pair<unsigned int,unsigned int> &cell_range) const
{
- FEEvaluation<dim,1,1,1,Number> fe_eval0 (data, 0, 0);
- FEEvaluation<dim,n_dofs_1d,n_dofs_1d,1,Number> fe_eval1 (data, 1, 1);
- FEEvaluation<dim,1,n_dofs_1d,1,Number> fe_eval01 (data, 0, 1);
+ FEEvaluation<dim,0,1,1,Number> fe_eval0 (data, 0, 0);
+ FEEvaluation<dim,fe_degree,fe_degree+1,1,Number> fe_eval1 (data, 1, 1);
+ FEEvaluation<dim,0,fe_degree+1,1,Number> fe_eval01 (data, 0, 1);
const unsigned int n_q_points0 = fe_eval0.n_q_points;
const unsigned int n_q_points1 = fe_eval1.n_q_points;
const unsigned int dofs_per_cell0 = fe_eval0.dofs_per_cell;
fe_eval1.reinit(cell);
fe_eval01.reinit(cell);
- // compare values with the ones the FEValues
- // gives us. Those are seen as reference
+ // compare values with the ones the FEValues
+ // gives us. Those are seen as reference
for (unsigned int j=0; j<data.n_components_filled(cell); ++j)
- {
- // FE 0, Quad 0
- // generate random numbers at quadrature
- // points and test them with basis functions
- // and their gradients
- for (unsigned int q=0; q<n_q_points0; ++q)
- {
- values0[q][j] = rand()/(double)RAND_MAX;
- for (unsigned int d=0; d<dim; ++d)
- gradients0[q*dim+d][j] = -1. + 2. * (rand()/(double)RAND_MAX);
- }
- fe_val0.reinit (data.get_cell_iterator(cell,j,0));
- data.get_cell_iterator(cell,j,0)->get_dof_indices(dof_indices0);
-
- for (unsigned int i=0; i<dofs_per_cell0; ++i)
- {
- double sum = 0.;
- for (unsigned int q=0; q<n_q_points0; ++q)
- {
- sum += values0[q][j] * fe_val0.shape_value(i,q) * fe_val0.JxW(q);
- for (unsigned int d=0; d<dim; ++d)
- sum += (gradients0[q*dim+d][j] * fe_val0.shape_grad(i,q)[d] *
- fe_val0.JxW(q));
- }
- dst[0+1](dof_indices0[i]) += sum;
- }
-
- // FE 1, Quad 1
- fe_val1.reinit (data.get_cell_iterator(cell,j,1));
- data.get_cell_iterator(cell,j,1)->get_dof_indices(dof_indices1);
-
- for (unsigned int q=0; q<n_q_points1; ++q)
- {
- values1[q][j] = rand()/(double)RAND_MAX;
- for (unsigned int d=0; d<dim; ++d)
- gradients1[q*dim+d][j] = -1. + 2. * (rand()/(double)RAND_MAX);
- }
- for (unsigned int i=0; i<dofs_per_cell1; ++i)
- {
- double sum = 0.;
- for (unsigned int q=0; q<n_q_points1; ++q)
- {
- sum += values1[q][j] * fe_val1.shape_value(i,q) * fe_val1.JxW(q);
- for (unsigned int d=0; d<dim; ++d)
- sum += (gradients1[q*dim+d][j] * fe_val1.shape_grad(i,q)[d] *
- fe_val1.JxW(q));
- }
- dst[2+1](dof_indices1[i]) += sum;
- }
-
- // FE 0, Quad 1
- fe_val01.reinit (data.get_cell_iterator(cell,j,0));
- for (unsigned int i=0; i<dofs_per_cell0; ++i)
- {
- double sum = 0.;
- for (unsigned int q=0; q<n_q_points1; ++q)
- {
- sum += values1[q][j] * fe_val01.shape_value(i,q) * fe_val01.JxW(q);
- for (unsigned int d=0; d<dim; ++d)
- sum += (gradients1[q*dim+d][j] * fe_val01.shape_grad(i,q)[d] *
- fe_val01.JxW(q));
- }
- dst[4+1](dof_indices0[i]) += sum;
- }
- }
-
- // FE 0, Quad 0
+ {
+ // FE 0, Quad 0
+ // generate random numbers at quadrature
+ // points and test them with basis functions
+ // and their gradients
+ for (unsigned int q=0; q<n_q_points0; ++q)
+ {
+ values0[q][j] = rand()/(double)RAND_MAX;
+ for (unsigned int d=0; d<dim; ++d)
+ gradients0[q*dim+d][j] = -1. + 2. * (rand()/(double)RAND_MAX);
+ }
+ fe_val0.reinit (data.get_cell_iterator(cell,j,0));
+ data.get_cell_iterator(cell,j,0)->get_dof_indices(dof_indices0);
+
+ for (unsigned int i=0; i<dofs_per_cell0; ++i)
+ {
+ double sum = 0.;
+ for (unsigned int q=0; q<n_q_points0; ++q)
+ {
+ sum += values0[q][j] * fe_val0.shape_value(i,q) * fe_val0.JxW(q);
+ for (unsigned int d=0; d<dim; ++d)
+ sum += (gradients0[q*dim+d][j] * fe_val0.shape_grad(i,q)[d] *
+ fe_val0.JxW(q));
+ }
+ dst[0+1](dof_indices0[i]) += sum;
+ }
+
+ // FE 1, Quad 1
+ fe_val1.reinit (data.get_cell_iterator(cell,j,1));
+ data.get_cell_iterator(cell,j,1)->get_dof_indices(dof_indices1);
+
+ for (unsigned int q=0; q<n_q_points1; ++q)
+ {
+ values1[q][j] = rand()/(double)RAND_MAX;
+ for (unsigned int d=0; d<dim; ++d)
+ gradients1[q*dim+d][j] = -1. + 2. * (rand()/(double)RAND_MAX);
+ }
+ for (unsigned int i=0; i<dofs_per_cell1; ++i)
+ {
+ double sum = 0.;
+ for (unsigned int q=0; q<n_q_points1; ++q)
+ {
+ sum += values1[q][j] * fe_val1.shape_value(i,q) * fe_val1.JxW(q);
+ for (unsigned int d=0; d<dim; ++d)
+ sum += (gradients1[q*dim+d][j] * fe_val1.shape_grad(i,q)[d] *
+ fe_val1.JxW(q));
+ }
+ dst[2+1](dof_indices1[i]) += sum;
+ }
+
+ // FE 0, Quad 1
+ fe_val01.reinit (data.get_cell_iterator(cell,j,0));
+ for (unsigned int i=0; i<dofs_per_cell0; ++i)
+ {
+ double sum = 0.;
+ for (unsigned int q=0; q<n_q_points1; ++q)
+ {
+ sum += values1[q][j] * fe_val01.shape_value(i,q) * fe_val01.JxW(q);
+ for (unsigned int d=0; d<dim; ++d)
+ sum += (gradients1[q*dim+d][j] * fe_val01.shape_grad(i,q)[d] *
+ fe_val01.JxW(q));
+ }
+ dst[4+1](dof_indices0[i]) += sum;
+ }
+ }
+
+ // FE 0, Quad 0
for (unsigned int q=0; q<n_q_points0; ++q)
- {
- fe_eval0.submit_value (values0[q], q);
- Tensor<1,dim,vector_t> submit (false);
- for (unsigned int d=0; d<dim; ++d)
- submit[d] = gradients0[q*dim+d];
- fe_eval0.submit_gradient (submit, q);
- }
+ {
+ fe_eval0.submit_value (values0[q], q);
+ Tensor<1,dim,vector_t> submit (false);
+ for (unsigned int d=0; d<dim; ++d)
+ submit[d] = gradients0[q*dim+d];
+ fe_eval0.submit_gradient (submit, q);
+ }
fe_eval0.integrate (true,true);
fe_eval0.distribute_local_to_global (dst[0]);
- // FE 1, Quad 1
+ // FE 1, Quad 1
for (unsigned int q=0; q<n_q_points1; ++q)
- {
- fe_eval1.submit_value (values1[q], q);
- Tensor<1,dim,vector_t> submit (false);
- for (unsigned int d=0; d<dim; ++d)
- submit[d] = gradients1[q*dim+d];
- fe_eval1.submit_gradient (submit, q);
- }
+ {
+ fe_eval1.submit_value (values1[q], q);
+ Tensor<1,dim,vector_t> submit (false);
+ for (unsigned int d=0; d<dim; ++d)
+ submit[d] = gradients1[q*dim+d];
+ fe_eval1.submit_gradient (submit, q);
+ }
fe_eval1.integrate (true,true);
fe_eval1.distribute_local_to_global (dst[2]);
- // FE 0, Quad 1
+ // FE 0, Quad 1
for (unsigned int q=0; q<n_q_points1; ++q)
- {
- fe_eval01.submit_value (values1[q], q);
- Tensor<1,dim,vector_t> submit (false);
- for (unsigned int d=0; d<dim; ++d)
- submit[d] = gradients1[q*dim+d];
- fe_eval01.submit_gradient (submit, q);
- }
+ {
+ fe_eval01.submit_value (values1[q], q);
+ Tensor<1,dim,vector_t> submit (false);
+ for (unsigned int d=0; d<dim; ++d)
+ submit[d] = gradients1[q*dim+d];
+ fe_eval01.submit_gradient (submit, q);
+ }
fe_eval01.integrate (true,true);
fe_eval01.distribute_local_to_global (dst[4]);
}
template <int dim, int fe_degree, typename number>
void test ()
{
- // create hyper ball geometry and refine some
- // cells
+ // create hyper ball geometry and refine some
+ // cells
Triangulation<dim> tria;
GridGenerator::hyper_ball (tria);
static const HyperBallBoundary<dim> boundary;
cell = tria.begin_active ();
unsigned int counter = 0;
for (; cell!=endc; ++cell, ++counter)
- if (counter % (7-i) == 0)
- cell->set_refine_flag();
+ if (counter % (7-i) == 0)
+ cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
}
quad.push_back (QGauss<1>(1));
quad.push_back (QGauss<1>(fe_degree+1));
mf_data.reinit (dof, constraints, quad,
- typename MatrixFree<dim,number>::AdditionalData(MPI_COMM_SELF,MatrixFree<dim,number>::AdditionalData::none));
+ typename MatrixFree<dim,number>::AdditionalData(MPI_COMM_SELF,MatrixFree<dim,number>::AdditionalData::none));
}
- MatrixFreeTest<dim,fe_degree+1,number> mf (mf_data);
+ MatrixFreeTest<dim,fe_degree,number> mf (mf_data);
mf.test_functions(dst);
constraints[0]->condense(dst[1]);
dof.distribute_dofs(fe);
ConstraintMatrix constraints;
VectorTools::interpolate_boundary_values (dof, 0, ZeroFunction<dim>(),
- constraints);
+ constraints);
constraints.close();
do_test<dim, fe_degree, double> (dof, constraints);
cell = tria.begin_active ();
unsigned int counter = 0;
for (; cell!=endc; ++cell, ++counter)
- if (counter % (7-i) == 0)
- cell->set_refine_flag();
+ if (counter % (7-i) == 0)
+ cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
}
ConstraintMatrix constraints;
DoFTools::make_hanging_node_constraints(dof, constraints);
VectorTools::interpolate_boundary_values (dof, 0, ZeroFunction<dim>(),
- constraints);
+ constraints);
constraints.close();
do_test<dim, fe_degree, double> (dof, constraints);
cell = tria.begin_active ();
unsigned int counter = 0;
for (; cell!=endc; ++cell, ++counter)
- if (counter % (7-i) == 0)
- cell->set_refine_flag();
+ if (counter % (7-i) == 0)
+ cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
}
endc = tria.end();
unsigned int counter = 0;
for (; cell!=endc; ++cell, ++counter)
- if (counter % (7-i) == 0)
- cell->set_refine_flag();
+ if (counter % (7-i) == 0)
+ cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
}
ConstraintMatrix constraints;
DoFTools::make_hanging_node_constraints(dof, constraints);
VectorTools::interpolate_boundary_values (dof, 0, ZeroFunction<dim>(),
- constraints);
+ constraints);
constraints.close();
do_test<dim, fe_degree, double> (dof, constraints);
cell = tria.begin_active ();
unsigned int counter = 0;
for (; cell!=endc; ++cell, ++counter)
- if (counter % (7-i) == 0)
- cell->set_refine_flag();
+ if (counter % (7-i) == 0)
+ cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
}
DoFHandler<dim> dof (tria);
dof.distribute_dofs(fe);
ConstraintMatrix constraints;
- // there should not be any hanging nodes or
- // boundary conditions for FE_DGQ as there are
- // only interior DoFs on the elements, but try
- // anyway
+ // there should not be any hanging nodes or
+ // boundary conditions for FE_DGQ as there are
+ // only interior DoFs on the elements, but try
+ // anyway
DoFTools::make_hanging_node_constraints(dof, constraints);
VectorTools::interpolate_boundary_values (dof, 0, ZeroFunction<dim>(),
- constraints);
+ constraints);
constraints.close();
do_test<dim, fe_degree, double> (dof, constraints);
- // test with coloring only as well
+ // test with coloring only as well
do_test<dim, fe_degree, double> (dof, constraints, 2);
}
endc = tria.end();
unsigned int counter = 0;
for (; cell!=endc; ++cell, ++counter)
- if (counter % (7-i) == 0)
- cell->set_refine_flag();
+ if (counter % (7-i) == 0)
+ cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
}
ConstraintMatrix constraints;
DoFTools::make_hanging_node_constraints(dof, constraints);
VectorTools::interpolate_boundary_values (dof, 0, ZeroFunction<dim>(),
- constraints);
+ constraints);
constraints.close();
do_test<dim, fe_degree, double> (dof, constraints);
endc = tria.end();
unsigned int counter = 0;
for (; cell!=endc; ++cell, ++counter)
- if (counter % (7-i) == 0)
- cell->set_refine_flag();
+ if (counter % (7-i) == 0)
+ cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
}
ConstraintMatrix constraints;
DoFTools::make_hanging_node_constraints(dof, constraints);
VectorTools::interpolate_boundary_values (dof, 0, ZeroFunction<dim>(),
- constraints);
+ constraints);
constraints.close();
do_test<dim, fe_degree, double> (dof, constraints);
-template <int dim, int n_dofs_1d, typename Number>
+template <int dim, int fe_degree, typename Number>
void
helmholtz_operator (const MatrixFree<dim,Number> &data,
- Vector<Number> &dst,
- const Vector<Number> &src,
- const std::pair<unsigned int,unsigned int> &cell_range)
+ Vector<Number> &dst,
+ const Vector<Number> &src,
+ const std::pair<unsigned int,unsigned int> &cell_range)
{
- FEEvaluation<dim,n_dofs_1d,n_dofs_1d,1,Number> fe_eval (data);
+ FEEvaluation<dim,fe_degree,fe_degree+1,1,Number> fe_eval (data);
const unsigned int n_q_points = fe_eval.n_q_points;
for(unsigned int cell=cell_range.first;cell<cell_range.second;++cell)
{
fe_eval.reinit (cell);
- // compare values with the ones the FEValues
- // gives us. Those are seen as reference
+ // compare values with the ones the FEValues
+ // gives us. Those are seen as reference
fe_eval.read_dof_values (src);
fe_eval.template evaluate (true, true, false);
for (unsigned int q=0; q<n_q_points; ++q)
- {
- fe_eval.submit_value (Number(10)*fe_eval.get_value(q),q);
- fe_eval.submit_gradient (fe_eval.get_gradient(q),q);
- }
+ {
+ fe_eval.submit_value (Number(10)*fe_eval.get_value(q),q);
+ fe_eval.submit_gradient (fe_eval.get_gradient(q),q);
+ }
fe_eval.template integrate (true,true);
fe_eval.distribute_local_to_global (dst);
}
-template <int dim, int n_dofs_1d, typename Number>
+template <int dim, int fe_degree, typename Number>
class MatrixFreeTest
{
public:
{};
void vmult (Vector<Number> &dst,
- const Vector<Number> &src) const
+ const Vector<Number> &src) const
{
dst = 0;
const std_cxx1x::function<void(const MatrixFree<dim,Number> &,
- Vector<Number> &,
- const Vector<Number> &,
- const std::pair<unsigned int,unsigned int>&)>
- wrap = helmholtz_operator<dim,n_dofs_1d,Number>;
+ Vector<Number> &,
+ const Vector<Number> &,
+ const std::pair<unsigned int,unsigned int>&)>
+ wrap = helmholtz_operator<dim,fe_degree,Number>;
data.cell_loop (wrap, dst, src);
};
template <int dim, int fe_degree, typename number>
void do_test (const DoFHandler<dim> &dof,
- const ConstraintMatrix&constraints,
- const unsigned int parallel_option = 0)
+ const ConstraintMatrix&constraints,
+ const unsigned int parallel_option = 0)
{
deallog << "Testing " << dof.get_fe().get_name() << std::endl;
typename MatrixFree<dim,number>::AdditionalData data;
if (parallel_option == 1)
data.tasks_parallel_scheme =
- MatrixFree<dim,number>::AdditionalData::partition_color;
+ MatrixFree<dim,number>::AdditionalData::partition_color;
else if (parallel_option == 2)
data.tasks_parallel_scheme =
- MatrixFree<dim,number>::AdditionalData::color;
+ MatrixFree<dim,number>::AdditionalData::color;
else
{
- Assert (parallel_option == 0, ExcInternalError());
- data.tasks_parallel_scheme =
- MatrixFree<dim,number>::AdditionalData::partition_partition;
+ Assert (parallel_option == 0, ExcInternalError());
+ data.tasks_parallel_scheme =
+ MatrixFree<dim,number>::AdditionalData::partition_partition;
}
data.tasks_block_size = 7;
mf_data.reinit (dof, constraints, quad, data);
}
- MatrixFreeTest<dim,fe_degree+1,number> mf (mf_data);
+ MatrixFreeTest<dim,fe_degree,number> mf (mf_data);
Vector<number> in (dof.n_dofs()), out (dof.n_dofs());
Vector<number> in_dist (dof.n_dofs());
Vector<number> out_dist (in_dist);
for (unsigned int i=0; i<dof.n_dofs(); ++i)
{
if(constraints.is_constrained(i))
- continue;
+ continue;
const double entry = rand()/(double)RAND_MAX;
in(i) = entry;
in_dist(i) = entry;
mf.vmult (out_dist, in_dist);
- // assemble sparse matrix with (\nabla v,
- // \nabla u) + (v, 10 * u)
+ // assemble sparse matrix with (\nabla v,
+ // \nabla u) + (v, 10 * u)
SparsityPattern sparsity;
{
CompressedSimpleSparsityPattern csp(dof.n_dofs(), dof.n_dofs());
QGauss<dim> quadrature_formula(fe_degree+1);
FEValues<dim> fe_values (dof.get_fe(), quadrature_formula,
- update_values | update_gradients |
- update_JxW_values);
+ update_values | update_gradients |
+ update_JxW_values);
const unsigned int dofs_per_cell = dof.get_fe().dofs_per_cell;
const unsigned int n_q_points = quadrature_formula.size();
endc = dof.end();
for (; cell!=endc; ++cell)
{
- cell_matrix = 0;
- fe_values.reinit (cell);
-
- for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- {
- for (unsigned int j=0; j<dofs_per_cell; ++j)
- cell_matrix(i,j) += ((fe_values.shape_grad(i,q_point) *
- fe_values.shape_grad(j,q_point)
- +
- 10. *
- fe_values.shape_value(i,q_point) *
- fe_values.shape_value(j,q_point)) *
- fe_values.JxW(q_point));
- }
-
- cell->get_dof_indices(local_dof_indices);
- constraints.distribute_local_to_global (cell_matrix,
- local_dof_indices,
- sparse_matrix);
+ cell_matrix = 0;
+ fe_values.reinit (cell);
+
+ for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ cell_matrix(i,j) += ((fe_values.shape_grad(i,q_point) *
+ fe_values.shape_grad(j,q_point)
+ +
+ 10. *
+ fe_values.shape_value(i,q_point) *
+ fe_values.shape_value(j,q_point)) *
+ fe_values.JxW(q_point));
+ }
+
+ cell->get_dof_indices(local_dof_indices);
+ constraints.distribute_local_to_global (cell_matrix,
+ local_dof_indices,
+ sparse_matrix);
}
}
void
local_apply (const MatrixFree<dim,Number> &data,
- VectorType &dst,
- const VectorType &src,
- const std::pair<unsigned int,unsigned int> &cell_range) const
+ VectorType &dst,
+ const VectorType &src,
+ const std::pair<unsigned int,unsigned int> &cell_range) const
{
typedef VectorizedArray<Number> vector_t;
- FEEvaluation<dim,degree+1,degree+1,dim,Number> phi (data);
+ FEEvaluation<dim,degree,degree+1,dim,Number> phi (data);
vector_t coeff = make_vectorized_array(global_coefficient);
for(unsigned int cell=cell_range.first;cell<cell_range.second;++cell)
{
- phi.reinit (cell);
- phi.read_dof_values (src);
- phi.evaluate (false,true,false);
+ phi.reinit (cell);
+ phi.read_dof_values (src);
+ phi.evaluate (false,true,false);
- for (unsigned int q=0; q<phi.n_q_points; ++q)
- phi.submit_curl (coeff * phi.get_curl(q), q);
+ for (unsigned int q=0; q<phi.n_q_points; ++q)
+ phi.submit_curl (coeff * phi.get_curl(q), q);
- phi.integrate (false,true);
- phi.distribute_local_to_global (dst);
+ phi.integrate (false,true);
+ phi.distribute_local_to_global (dst);
}
}
void vmult (VectorType &dst,
- const VectorType &src) const
+ const VectorType &src) const
{
AssertDimension (dst.size(), dim);
for (unsigned int d=0; d<dim; ++d)
dst[d] = 0;
data.cell_loop (&MatrixFreeTest<dim,degree,VectorType>::local_apply,
- this, dst, src);
+ this, dst, src);
};
private:
tria.set_boundary (0, boundary);
tria.refine_global(4-dim);
- // refine a few cells
+ // refine a few cells
for (unsigned int i=0; i<10-3*dim; ++i)
{
typename Triangulation<dim>::active_cell_iterator
- cell = tria.begin_active (),
- endc = tria.end();
+ cell = tria.begin_active (),
+ endc = tria.end();
unsigned int counter = 0;
for (; cell!=endc; ++cell, ++counter)
- if (counter % (7-i) == 0)
- cell->set_refine_flag();
+ if (counter % (7-i) == 0)
+ cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
}
BlockCompressedSimpleSparsityPattern csp (dim,dim);
for (unsigned int d=0; d<dim; ++d)
for (unsigned int e=0; e<dim; ++e)
- csp.block(d,e).reinit (dofs_per_block, dofs_per_block);
+ csp.block(d,e).reinit (dofs_per_block, dofs_per_block);
csp.collect_sizes();
vec2[i].reinit (vec1[0]);
}
- // assemble curl-curl operator
+ // assemble curl-curl operator
{
QGauss<dim> quadrature_formula(fe_degree+1);
FEValues<dim> fe_values (fe, quadrature_formula,
- update_values |
- update_JxW_values |
- update_gradients);
+ update_values |
+ update_JxW_values |
+ update_gradients);
const unsigned int dofs_per_cell = fe.dofs_per_cell;
const unsigned int n_q_points = quadrature_formula.size();
endc = dof_handler.end();
for (; cell!=endc; ++cell)
{
- fe_values.reinit (cell);
- local_matrix = 0;
-
- for (unsigned int q=0; q<n_q_points; ++q)
- {
- for (unsigned int k=0; k<dofs_per_cell; ++k)
- {
- const Tensor<2,dim> phi_grad = fe_values[sc].gradient(k,q);
- if (dim == 2)
- phi_curl[k][0] = phi_grad[1][0] - phi_grad[0][1];
- else
- {
- phi_curl[k][0] = phi_grad[2][1] - phi_grad[1][2];
- phi_curl[k][1] = phi_grad[0][2] - phi_grad[2][0];
- phi_curl[k][2] = phi_grad[1][0] - phi_grad[0][1];
- }
- }
-
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- {
- for (unsigned int j=0; j<=i; ++j)
- {
- local_matrix(i,j) += (phi_curl[i] * phi_curl[j] *
- global_coefficient)
- * fe_values.JxW(q);
- }
- }
- }
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- for (unsigned int j=i+1; j<dofs_per_cell; ++j)
- local_matrix(i,j) = local_matrix(j,i);
-
- cell->get_dof_indices (local_dof_indices);
- constraints.distribute_local_to_global (local_matrix,
- local_dof_indices,
- system_matrix);
+ fe_values.reinit (cell);
+ local_matrix = 0;
+
+ for (unsigned int q=0; q<n_q_points; ++q)
+ {
+ for (unsigned int k=0; k<dofs_per_cell; ++k)
+ {
+ const Tensor<2,dim> phi_grad = fe_values[sc].gradient(k,q);
+ if (dim == 2)
+ phi_curl[k][0] = phi_grad[1][0] - phi_grad[0][1];
+ else
+ {
+ phi_curl[k][0] = phi_grad[2][1] - phi_grad[1][2];
+ phi_curl[k][1] = phi_grad[0][2] - phi_grad[2][0];
+ phi_curl[k][2] = phi_grad[1][0] - phi_grad[0][1];
+ }
+ }
+
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ for (unsigned int j=0; j<=i; ++j)
+ {
+ local_matrix(i,j) += (phi_curl[i] * phi_curl[j] *
+ global_coefficient)
+ * fe_values.JxW(q);
+ }
+ }
+ }
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ for (unsigned int j=i+1; j<dofs_per_cell; ++j)
+ local_matrix(i,j) = local_matrix(j,i);
+
+ cell->get_dof_indices (local_dof_indices);
+ constraints.distribute_local_to_global (local_matrix,
+ local_dof_indices,
+ system_matrix);
}
}
- // first system_rhs with random numbers
+ // first system_rhs with random numbers
for (unsigned int i=0; i<dim; ++i)
for (unsigned int j=0; j<system_rhs.block(i).size(); ++j)
{
- const double val = -1. + 2.*(double)rand()/double(RAND_MAX);
- system_rhs.block(i)(j) = val;
+ const double val = -1. + 2.*(double)rand()/double(RAND_MAX);
+ system_rhs.block(i)(j) = val;
}
constraints.condense(system_rhs);
for (unsigned int i=0; i<dim; ++i)
vec1[i] = system_rhs.block(i);
- // setup matrix-free structure
+ // setup matrix-free structure
{
QGauss<1> quad(fe_degree+1);
mf_data.reinit (dof_handler_sca, constraints, quad,
- typename MatrixFree<dim>::AdditionalData
- (MPI_COMM_WORLD,
- MatrixFree<dim>::AdditionalData::none));
+ typename MatrixFree<dim>::AdditionalData
+ (MPI_COMM_WORLD,
+ MatrixFree<dim>::AdditionalData::none));
}
system_matrix.vmult (solution, system_rhs);
MatrixFreeTest<dim,fe_degree,VectorType> mf (mf_data);
mf.vmult (vec2, vec1);
- // Verification
+ // Verification
double error = 0.;
for (unsigned int i=0; i<dim; ++i)
for (unsigned int j=0; j<system_rhs.block(i).size(); ++j)
error += std::fabs (solution.block(i)(j)-vec2[i](j));
double relative = solution.block(0).l1_norm();
deallog << " Verification fe degree " << fe_degree << ": "
- << error/relative << std::endl << std::endl;
+ << error/relative << std::endl << std::endl;
}
cell = tria.begin_active ();
unsigned int counter = 0;
for (; cell!=endc; ++cell, ++counter)
- if (counter % (7-i) == 0)
- cell->set_refine_flag();
+ if (counter % (7-i) == 0)
+ cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
}
{};
void local_apply(const MatrixFree<dim,Number> &data,
- Vector<Number> &dst,
- const Vector<Number> &src,
- const std::pair<unsigned int,unsigned int> &cell_range) const
+ Vector<Number> &dst,
+ const Vector<Number> &src,
+ const std::pair<unsigned int,unsigned int> &cell_range) const
{
// ask MatrixFree for cell_range for different orders
std::pair<unsigned int,unsigned int> subrange_deg =
data.create_cell_subrange_hp (cell_range, 1);
if (subrange_deg.second > subrange_deg.first)
- helmholtz_operator<dim,2,Number> (data, dst, src,
- subrange_deg);
+ helmholtz_operator<dim,1,Number> (data, dst, src,
+ subrange_deg);
subrange_deg = data.create_cell_subrange_hp (cell_range, 2);
if (subrange_deg.second > subrange_deg.first)
- helmholtz_operator<dim,3,Number> (data, dst, src,
- subrange_deg);
+ helmholtz_operator<dim,2,Number> (data, dst, src,
+ subrange_deg);
subrange_deg = data.create_cell_subrange_hp (cell_range, 3);
if (subrange_deg.second > subrange_deg.first)
- helmholtz_operator<dim,4,Number> (data, dst, src,
- subrange_deg);
+ helmholtz_operator<dim,3,Number> (data, dst, src,
+ subrange_deg);
subrange_deg = data.create_cell_subrange_hp (cell_range, 4);
if (subrange_deg.second > subrange_deg.first)
- helmholtz_operator<dim,5,Number> (data, dst, src,
- subrange_deg);
+ helmholtz_operator<dim,4,Number> (data, dst, src,
+ subrange_deg);
subrange_deg = data.create_cell_subrange_hp (cell_range, 5);
if (subrange_deg.second > subrange_deg.first)
- helmholtz_operator<dim,6,Number> (data, dst, src,
- subrange_deg);
+ helmholtz_operator<dim,5,Number> (data, dst, src,
+ subrange_deg);
subrange_deg = data.create_cell_subrange_hp (cell_range, 6);
if (subrange_deg.second > subrange_deg.first)
- helmholtz_operator<dim,7,Number> (data, dst, src,
- subrange_deg);
+ helmholtz_operator<dim,6,Number> (data, dst, src,
+ subrange_deg);
subrange_deg = data.create_cell_subrange_hp (cell_range, 7);
if (subrange_deg.second > subrange_deg.first)
- helmholtz_operator<dim,8,Number> (data, dst, src,
- subrange_deg);
+ helmholtz_operator<dim,7,Number> (data, dst, src,
+ subrange_deg);
}
void vmult (Vector<Number> &dst,
- const Vector<Number> &src) const
+ const Vector<Number> &src) const
{
dst = 0;
data.cell_loop (&MatrixFreeTestHP<dim,Number>::local_apply, this, dst, src);
tria.set_boundary (0, boundary);
tria.refine_global(1);
- // refine a few cells
+ // refine a few cells
for (unsigned int i=0; i<11-3*dim; ++i)
{
typename Triangulation<dim>::active_cell_iterator
- cell = tria.begin_active (),
- endc = tria.end();
+ cell = tria.begin_active (),
+ endc = tria.end();
unsigned int counter = 0;
for (; cell!=endc; ++cell, ++counter)
- if (counter % (7-i) == 0)
- cell->set_refine_flag();
+ if (counter % (7-i) == 0)
+ cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
}
}
hp::DoFHandler<dim> dof(tria);
- // set the active FE index in a random order
+ // set the active FE index in a random order
{
typename hp::DoFHandler<dim>::active_cell_iterator
cell = dof.begin_active(),
endc = dof.end();
for (; cell!=endc; ++cell)
{
- const unsigned int fe_index = rand() % max_degree;
- cell->set_active_fe_index (fe_index);
+ const unsigned int fe_index = rand() % max_degree;
+ cell->set_active_fe_index (fe_index);
}
}
- // setup DoFs
+ // setup DoFs
dof.distribute_dofs(fe_collection);
ConstraintMatrix constraints;
DoFTools::make_hanging_node_constraints (dof,
- constraints);
+ constraints);
VectorTools::interpolate_boundary_values (dof,
- 0,
- ZeroFunction<dim>(),
- constraints);
+ 0,
+ ZeroFunction<dim>(),
+ constraints);
constraints.close ();
CompressedSimpleSparsityPattern csp (dof.n_dofs(),
- dof.n_dofs());
+ dof.n_dofs());
DoFTools::make_sparsity_pattern (dof, csp, constraints, false);
SparsityPattern sparsity;
sparsity.copy_from (csp);
//std::cout << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
//std::cout << "Number of constraints: " << constraints.n_constraints() << std::endl;
- // set up MatrixFree
+ // set up MatrixFree
MatrixFree<dim,number> mf_data;
typename MatrixFree<dim,number>::AdditionalData data;
data.tasks_parallel_scheme =
mf_data.reinit (dof, constraints, quadrature_collection_mf, data);
MatrixFreeTestHP<dim,number> mf (mf_data);
- // assemble sparse matrix with (\nabla v,
- // \nabla u) + (v, 10 * u)
+ // assemble sparse matrix with (\nabla v,
+ // \nabla u) + (v, 10 * u)
{
hp::FEValues<dim> hp_fe_values (fe_collection,
- quadrature_collection,
- update_values | update_gradients |
- update_JxW_values);
+ quadrature_collection,
+ update_values | update_gradients |
+ update_JxW_values);
FullMatrix<double> cell_matrix;
std::vector<unsigned int> local_dof_indices;
endc = dof.end();
for (; cell!=endc; ++cell)
{
- const unsigned int dofs_per_cell = cell->get_fe().dofs_per_cell;
-
- cell_matrix.reinit (dofs_per_cell, dofs_per_cell);
- cell_matrix = 0;
- hp_fe_values.reinit (cell);
- const FEValues<dim> &fe_values = hp_fe_values.get_present_fe_values ();
-
- for (unsigned int q_point=0;
- q_point<fe_values.n_quadrature_points;
- ++q_point)
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- {
- for (unsigned int j=0; j<dofs_per_cell; ++j)
- cell_matrix(i,j) += ((fe_values.shape_grad(i,q_point) *
- fe_values.shape_grad(j,q_point) +
- 10. * fe_values.shape_value(i,q_point) *
- fe_values.shape_value(j,q_point)) *
- fe_values.JxW(q_point));
- }
- local_dof_indices.resize (dofs_per_cell);
- cell->get_dof_indices (local_dof_indices);
-
- constraints.distribute_local_to_global (cell_matrix,
- local_dof_indices,
- system_matrix);
+ const unsigned int dofs_per_cell = cell->get_fe().dofs_per_cell;
+
+ cell_matrix.reinit (dofs_per_cell, dofs_per_cell);
+ cell_matrix = 0;
+ hp_fe_values.reinit (cell);
+ const FEValues<dim> &fe_values = hp_fe_values.get_present_fe_values ();
+
+ for (unsigned int q_point=0;
+ q_point<fe_values.n_quadrature_points;
+ ++q_point)
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ cell_matrix(i,j) += ((fe_values.shape_grad(i,q_point) *
+ fe_values.shape_grad(j,q_point) +
+ 10. * fe_values.shape_value(i,q_point) *
+ fe_values.shape_value(j,q_point)) *
+ fe_values.JxW(q_point));
+ }
+ local_dof_indices.resize (dofs_per_cell);
+ cell->get_dof_indices (local_dof_indices);
+
+ constraints.distribute_local_to_global (cell_matrix,
+ local_dof_indices,
+ system_matrix);
}
}
- // fill a right hand side vector with random
- // numbers in unconstrained degrees of freedom
+ // fill a right hand side vector with random
+ // numbers in unconstrained degrees of freedom
Vector<double> src (dof.n_dofs());
Vector<double> result_spmv(src), result_mf (src);
for (unsigned int i=0; i<dof.n_dofs(); ++i)
{
if (constraints.is_constrained(i) == false)
- src(i) = (double)rand()/RAND_MAX;
+ src(i) = (double)rand()/RAND_MAX;
}
- // now perform matrix-vector product and check
- // its correctness
+ // now perform matrix-vector product and check
+ // its correctness
system_matrix.vmult (result_spmv, src);
mf.vmult (result_mf, src);
FE_Q<dim> fe (fe_degree);
- // setup DoFs
+ // setup DoFs
MGDoFHandler<dim> dof(tria);
dof.distribute_dofs(fe);
ConstraintMatrix constraints;
VectorTools::interpolate_boundary_values (dof,
- 0,
- ZeroFunction<dim>(),
- constraints);
+ 0,
+ ZeroFunction<dim>(),
+ constraints);
constraints.close ();
//std::cout << "Number of cells: " << dof.get_tria().n_active_cells() << std::endl;
//std::cout << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
- // set up MatrixFree
+ // set up MatrixFree
QGauss<1> quad (fe_degree+1);
MatrixFree<dim> mf_data;
mf_data.reinit (dof, constraints, quad);
{
CompressedSimpleSparsityPattern csp (dof.n_dofs(), dof.n_dofs());
DoFTools::make_sparsity_pattern (static_cast<const DoFHandler<dim>&>(dof),
- csp, constraints, false);
+ csp, constraints, false);
sparsity.copy_from (csp);
}
system_matrix.reinit (sparsity);
- // setup MG levels
+ // setup MG levels
const unsigned int nlevels = tria.n_levels();
typedef MatrixFree<dim> MatrixFreeTestType;
MGLevelObject<MatrixFreeTestType> mg_matrices;
mg_ref_matrices[level].reinit (mg_sparsities[level]);
}
- // assemble sparse matrix with (\nabla v,
- // \nabla u) + (v, 10 * u) on the actual
- // discretization and on all levels
+ // assemble sparse matrix with (\nabla v,
+ // \nabla u) + (v, 10 * u) on the actual
+ // discretization and on all levels
{
QGauss<dim> quad (fe_degree+1);
FEValues<dim> fe_values (fe, quad,
- update_values | update_gradients |
- update_JxW_values);
+ update_values | update_gradients |
+ update_JxW_values);
const unsigned int n_quadrature_points = quad.size();
const unsigned int dofs_per_cell = fe.dofs_per_cell;
FullMatrix<double> cell_matrix (dofs_per_cell, dofs_per_cell);
endc = dof.end();
for (; cell!=endc; ++cell)
{
- cell_matrix = 0;
- fe_values.reinit (cell);
-
- for (unsigned int q_point=0; q_point<n_quadrature_points; ++q_point)
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- {
- for (unsigned int j=0; j<dofs_per_cell; ++j)
- cell_matrix(i,j) += ((fe_values.shape_grad(i,q_point) *
- fe_values.shape_grad(j,q_point) +
- 10. * fe_values.shape_value(i,q_point) *
- fe_values.shape_value(j,q_point)) *
- fe_values.JxW(q_point));
- }
- cell->get_dof_indices (local_dof_indices);
- constraints.distribute_local_to_global (cell_matrix,
- local_dof_indices,
- system_matrix);
+ cell_matrix = 0;
+ fe_values.reinit (cell);
+
+ for (unsigned int q_point=0; q_point<n_quadrature_points; ++q_point)
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ cell_matrix(i,j) += ((fe_values.shape_grad(i,q_point) *
+ fe_values.shape_grad(j,q_point) +
+ 10. * fe_values.shape_value(i,q_point) *
+ fe_values.shape_value(j,q_point)) *
+ fe_values.JxW(q_point));
+ }
+ cell->get_dof_indices (local_dof_indices);
+ constraints.distribute_local_to_global (cell_matrix,
+ local_dof_indices,
+ system_matrix);
}
// now to the MG assembly
endcm = dof.end();
for (; cellm!=endcm; ++cellm)
{
- cell_matrix = 0;
- fe_values.reinit (cellm);
-
- for (unsigned int q_point=0; q_point<n_quadrature_points; ++q_point)
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- {
- for (unsigned int j=0; j<dofs_per_cell; ++j)
- cell_matrix(i,j) += ((fe_values.shape_grad(i,q_point) *
- fe_values.shape_grad(j,q_point) +
- 10. * fe_values.shape_value(i,q_point) *
- fe_values.shape_value(j,q_point)) *
- fe_values.JxW(q_point));
- }
- cellm->get_mg_dof_indices (local_dof_indices);
- mg_constraints[cellm->level()]
- .distribute_local_to_global (cell_matrix,
- local_dof_indices,
- mg_ref_matrices[cellm->level()]);
+ cell_matrix = 0;
+ fe_values.reinit (cellm);
+
+ for (unsigned int q_point=0; q_point<n_quadrature_points; ++q_point)
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ cell_matrix(i,j) += ((fe_values.shape_grad(i,q_point) *
+ fe_values.shape_grad(j,q_point) +
+ 10. * fe_values.shape_value(i,q_point) *
+ fe_values.shape_value(j,q_point)) *
+ fe_values.JxW(q_point));
+ }
+ cellm->get_mg_dof_indices (local_dof_indices);
+ mg_constraints[cellm->level()]
+ .distribute_local_to_global (cell_matrix,
+ local_dof_indices,
+ mg_ref_matrices[cellm->level()]);
}
}
- // fill a right hand side vector with random
- // numbers in unconstrained degrees of freedom
+ // fill a right hand side vector with random
+ // numbers in unconstrained degrees of freedom
Vector<double> src (dof.n_dofs());
Vector<double> result_spmv(src), result_mf (src);
for (unsigned int i=0; i<dof.n_dofs(); ++i)
{
if (constraints.is_constrained(i) == false)
- src(i) = (double)rand()/RAND_MAX;
+ src(i) = (double)rand()/RAND_MAX;
}
- // now perform matrix-vector product and check
- // its correctness
+ // now perform matrix-vector product and check
+ // its correctness
system_matrix.vmult (result_spmv, src);
- MatrixFreeTest<dim,fe_degree+1,double> mf (mf_data);
+ MatrixFreeTest<dim,fe_degree,double> mf (mf_data);
mf.vmult (result_mf, src);
result_mf -= result_spmv;
Vector<double> result_spmv(src), result_mf (src);
for (unsigned int i=0; i<dof.n_dofs(level); ++i)
- {
- if (mg_constraints[level].is_constrained(i) == false)
- src(i) = (double)rand()/RAND_MAX;
- }
+ {
+ if (mg_constraints[level].is_constrained(i) == false)
+ src(i) = (double)rand()/RAND_MAX;
+ }
- // now perform matrix-vector product and check
- // its correctness
+ // now perform matrix-vector product and check
+ // its correctness
mg_ref_matrices[level].vmult (result_spmv, src);
- MatrixFreeTest<dim,fe_degree+1,double> mf_lev (mg_matrices[level]);
+ MatrixFreeTest<dim,fe_degree,double> mf_lev (mg_matrices[level]);
mf_lev.vmult (result_mf, src);
result_mf -= result_spmv;
const double diff_norm = result_mf.linfty_norm();
deallog << "Norm of difference MG level " << level
- << ": " << diff_norm << std::endl;
+ << ": " << diff_norm << std::endl;
}
deallog << std::endl;
}
void
local_apply (const MatrixFree<dim,Number> &data,
- VectorType &dst,
- const VectorType &src,
- const std::pair<unsigned int,unsigned int> &cell_range) const
+ VectorType &dst,
+ const VectorType &src,
+ const std::pair<unsigned int,unsigned int> &cell_range) const
{
typedef VectorizedArray<Number> vector_t;
- FEEvaluation<dim,degree_p+2,degree_p+2,dim,Number> velocity (data, 0);
- FEEvaluation<dim,degree_p+1,degree_p+2,1, Number> pressure (data, 1);
+ FEEvaluation<dim,degree_p+1,degree_p+2,dim,Number> velocity (data, 0);
+ FEEvaluation<dim,degree_p ,degree_p+2,1, Number> pressure (data, 1);
for(unsigned int cell=cell_range.first;cell<cell_range.second;++cell)
{
- velocity.reinit (cell);
- velocity.read_dof_values (src, 0);
- velocity.evaluate (false,true,false);
- pressure.reinit (cell);
- pressure.read_dof_values (src, dim);
- pressure.evaluate (true,false,false);
-
- for (unsigned int q=0; q<velocity.n_q_points; ++q)
- {
- SymmetricTensor<2,dim,vector_t> sym_grad_u =
- velocity.get_symmetric_gradient (q);
- vector_t pres = pressure.get_value(q);
- vector_t div = -velocity.get_divergence(q);
- pressure.submit_value (div, q);
-
- // subtract p * I
- for (unsigned int d=0; d<dim; ++d)
- sym_grad_u[d][d] -= pres;
-
- velocity.submit_symmetric_gradient(sym_grad_u, q);
- }
-
- velocity.integrate (false,true);
- velocity.distribute_local_to_global (dst, 0);
- pressure.integrate (true,false);
- pressure.distribute_local_to_global (dst, dim);
+ velocity.reinit (cell);
+ velocity.read_dof_values (src, 0);
+ velocity.evaluate (false,true,false);
+ pressure.reinit (cell);
+ pressure.read_dof_values (src, dim);
+ pressure.evaluate (true,false,false);
+
+ for (unsigned int q=0; q<velocity.n_q_points; ++q)
+ {
+ SymmetricTensor<2,dim,vector_t> sym_grad_u =
+ velocity.get_symmetric_gradient (q);
+ vector_t pres = pressure.get_value(q);
+ vector_t div = -velocity.get_divergence(q);
+ pressure.submit_value (div, q);
+
+ // subtract p * I
+ for (unsigned int d=0; d<dim; ++d)
+ sym_grad_u[d][d] -= pres;
+
+ velocity.submit_symmetric_gradient(sym_grad_u, q);
+ }
+
+ velocity.integrate (false,true);
+ velocity.distribute_local_to_global (dst, 0);
+ pressure.integrate (true,false);
+ pressure.distribute_local_to_global (dst, dim);
}
}
void vmult (VectorType &dst,
- const VectorType &src) const
+ const VectorType &src) const
{
AssertDimension (dst.size(), dim+1);
for (unsigned int d=0; d<dim+1; ++d)
dst[d] = 0;
data.cell_loop (&MatrixFreeTest<dim,degree_p,VectorType>::local_apply,
- this, dst, src);
+ this, dst, src);
};
private:
subdivisions[0] = 4;
const Point<dim> bottom_left = (dim == 2 ?
- Point<dim>(-2,-1) :
- Point<dim>(-2,0,-1));
+ Point<dim>(-2,-1) :
+ Point<dim>(-2,0,-1));
const Point<dim> top_right = (dim == 2 ?
- Point<dim>(2,0) :
- Point<dim>(2,1,0));
+ Point<dim>(2,0) :
+ Point<dim>(2,1,0));
GridGenerator::subdivided_hyper_rectangle (triangulation,
- subdivisions,
- bottom_left,
- top_right);
+ subdivisions,
+ bottom_left,
+ top_right);
}
triangulation.refine_global (4-dim);
for (unsigned int d=0; d<dim+1; ++d)
for (unsigned int e=0; e<dim+1; ++e)
- csp.block(d,e).reinit (dofs_per_block[d], dofs_per_block[e]);
+ csp.block(d,e).reinit (dofs_per_block[d], dofs_per_block[e]);
csp.collect_sizes();
vec1[dim].reinit (dofs_per_block[dim]);
vec2[dim].reinit (vec1[dim]);
- // this is from step-22
+ // this is from step-22
{
QGauss<dim> quadrature_formula(fe_degree+2);
FEValues<dim> fe_values (fe, quadrature_formula,
- update_values |
- update_JxW_values |
- update_gradients);
+ update_values |
+ update_JxW_values |
+ update_gradients);
const unsigned int dofs_per_cell = fe.dofs_per_cell;
const unsigned int n_q_points = quadrature_formula.size();
endc = dof_handler.end();
for (; cell!=endc; ++cell)
{
- fe_values.reinit (cell);
- local_matrix = 0;
-
- for (unsigned int q=0; q<n_q_points; ++q)
- {
- for (unsigned int k=0; k<dofs_per_cell; ++k)
- {
- phi_grads_u[k] = fe_values[velocities].symmetric_gradient (k, q);
- div_phi_u[k] = fe_values[velocities].divergence (k, q);
- phi_p[k] = fe_values[pressure].value (k, q);
- }
-
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- {
- for (unsigned int j=0; j<=i; ++j)
- {
- local_matrix(i,j) += (phi_grads_u[i] * phi_grads_u[j]
- - div_phi_u[i] * phi_p[j]
- - phi_p[i] * div_phi_u[j])
- * fe_values.JxW(q);
- }
- }
- }
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- for (unsigned int j=i+1; j<dofs_per_cell; ++j)
- local_matrix(i,j) = local_matrix(j,i);
-
- cell->get_dof_indices (local_dof_indices);
- constraints.distribute_local_to_global (local_matrix,
- local_dof_indices,
- system_matrix);
+ fe_values.reinit (cell);
+ local_matrix = 0;
+
+ for (unsigned int q=0; q<n_q_points; ++q)
+ {
+ for (unsigned int k=0; k<dofs_per_cell; ++k)
+ {
+ phi_grads_u[k] = fe_values[velocities].symmetric_gradient (k, q);
+ div_phi_u[k] = fe_values[velocities].divergence (k, q);
+ phi_p[k] = fe_values[pressure].value (k, q);
+ }
+
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ for (unsigned int j=0; j<=i; ++j)
+ {
+ local_matrix(i,j) += (phi_grads_u[i] * phi_grads_u[j]
+ - div_phi_u[i] * phi_p[j]
+ - phi_p[i] * div_phi_u[j])
+ * fe_values.JxW(q);
+ }
+ }
+ }
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ for (unsigned int j=i+1; j<dofs_per_cell; ++j)
+ local_matrix(i,j) = local_matrix(j,i);
+
+ cell->get_dof_indices (local_dof_indices);
+ constraints.distribute_local_to_global (local_matrix,
+ local_dof_indices,
+ system_matrix);
}
}
- // first system_rhs with random numbers
+ // first system_rhs with random numbers
for (unsigned int i=0; i<dim+1; ++i)
for (unsigned int j=0; j<system_rhs.block(i).size(); ++j)
{
- const double val = -1. + 2.*(double)rand()/double(RAND_MAX);
- system_rhs.block(i)(j) = val;
- vec1[i](j) = val;
+ const double val = -1. + 2.*(double)rand()/double(RAND_MAX);
+ system_rhs.block(i)(j) = val;
+ vec1[i](j) = val;
}
- // setup matrix-free structure
+ // setup matrix-free structure
{
std::vector<const DoFHandler<dim>*> dofs;
dofs.push_back(&dof_handler_u);
constraints.push_back (&dummy_constraints);
QGauss<1> quad(fe_degree+2);
mf_data.reinit (dofs, constraints, quad,
- typename MatrixFree<dim>::AdditionalData
- (MPI_COMM_WORLD,
- MatrixFree<dim>::AdditionalData::none));
+ typename MatrixFree<dim>::AdditionalData
+ (MPI_COMM_WORLD,
+ MatrixFree<dim>::AdditionalData::none));
}
system_matrix.vmult (solution, system_rhs);
MatrixFreeTest<dim,fe_degree,VectorType> mf (mf_data);
mf.vmult (vec2, vec1);
- // Verification
+ // Verification
double error = 0.;
for (unsigned int i=0; i<dim+1; ++i)
for (unsigned int j=0; j<system_rhs.block(i).size(); ++j)
error += std::fabs (solution.block(i)(j)-vec2[i](j));
double relative = solution.block(0).l1_norm();
deallog << " Verification fe degree " << fe_degree << ": "
- << error/relative << std::endl << std::endl;
+ << error/relative << std::endl << std::endl;
}
void
local_apply (const MatrixFree<dim,Number> &data,
- VectorType &dst,
- const VectorType &src,
- const std::pair<unsigned int,unsigned int> &cell_range) const
+ VectorType &dst,
+ const VectorType &src,
+ const std::pair<unsigned int,unsigned int> &cell_range) const
{
typedef VectorizedArray<Number> vector_t;
- FEEvaluation<dim,degree_p+2,degree_p+2,dim,Number> velocity (data, 0);
- FEEvaluation<dim,degree_p+1,degree_p+2,1, Number> pressure (data, 1);
+ FEEvaluation<dim,degree_p+1,degree_p+2,dim,Number> velocity (data, 0);
+ FEEvaluation<dim,degree_p, degree_p+2,1, Number> pressure (data, 1);
for(unsigned int cell=cell_range.first;cell<cell_range.second;++cell)
{
- velocity.reinit (cell);
- velocity.read_dof_values (src[0]);
- velocity.evaluate (false,true,false);
- pressure.reinit (cell);
- pressure.read_dof_values (src[1]);
- pressure.evaluate (true,false,false);
-
- for (unsigned int q=0; q<velocity.n_q_points; ++q)
- {
- SymmetricTensor<2,dim,vector_t> sym_grad_u =
- velocity.get_symmetric_gradient (q);
- vector_t pres = pressure.get_value(q);
- vector_t div = -velocity.get_divergence(q);
- pressure.submit_value (div, q);
-
- // subtract p * I
- for (unsigned int d=0; d<dim; ++d)
- sym_grad_u[d][d] -= pres;
-
- velocity.submit_symmetric_gradient(sym_grad_u, q);
- }
-
- velocity.integrate (false,true);
- velocity.distribute_local_to_global (dst[0]);
- pressure.integrate (true,false);
- pressure.distribute_local_to_global (dst[1]);
+ velocity.reinit (cell);
+ velocity.read_dof_values (src[0]);
+ velocity.evaluate (false,true,false);
+ pressure.reinit (cell);
+ pressure.read_dof_values (src[1]);
+ pressure.evaluate (true,false,false);
+
+ for (unsigned int q=0; q<velocity.n_q_points; ++q)
+ {
+ SymmetricTensor<2,dim,vector_t> sym_grad_u =
+ velocity.get_symmetric_gradient (q);
+ vector_t pres = pressure.get_value(q);
+ vector_t div = -velocity.get_divergence(q);
+ pressure.submit_value (div, q);
+
+ // subtract p * I
+ for (unsigned int d=0; d<dim; ++d)
+ sym_grad_u[d][d] -= pres;
+
+ velocity.submit_symmetric_gradient(sym_grad_u, q);
+ }
+
+ velocity.integrate (false,true);
+ velocity.distribute_local_to_global (dst[0]);
+ pressure.integrate (true,false);
+ pressure.distribute_local_to_global (dst[1]);
}
}
void vmult (VectorType &dst,
- const VectorType &src) const
+ const VectorType &src) const
{
AssertDimension (dst.size(), 2);
for (unsigned int d=0; d<2; ++d)
dst[d] = 0;
data.cell_loop (&MatrixFreeTest<dim,degree_p,VectorType>::local_apply,
- this, dst, src);
+ this, dst, src);
};
private:
{
Triangulation<dim> triangulation;
GridGenerator::hyper_shell (triangulation, Point<dim>(),
- 0.5, 1., 96, true);
+ 0.5, 1., 96, true);
static HyperShellBoundary<dim> boundary;
triangulation.set_boundary (0, boundary);
triangulation.set_boundary (1, boundary);
no_normal_flux_boundaries.insert (0);
no_normal_flux_boundaries.insert (1);
DoFTools::make_hanging_node_constraints (dof_handler,
- constraints);
+ constraints);
VectorTools::compute_no_normal_flux_constraints (dof_handler, 0,
- no_normal_flux_boundaries,
- constraints, mapping);
+ no_normal_flux_boundaries,
+ constraints, mapping);
constraints.close ();
DoFTools::make_hanging_node_constraints (dof_handler_u,
- constraints_u);
+ constraints_u);
VectorTools::compute_no_normal_flux_constraints (dof_handler_u, 0,
- no_normal_flux_boundaries,
- constraints_u, mapping);
+ no_normal_flux_boundaries,
+ constraints_u, mapping);
constraints_u.close ();
DoFTools::make_hanging_node_constraints (dof_handler_p,
- constraints_p);
+ constraints_p);
constraints_p.close ();
std::vector<unsigned int> dofs_per_block (2);
DoFTools::count_dofs_per_block (dof_handler, dofs_per_block,
- stokes_sub_blocks);
+ stokes_sub_blocks);
//std::cout << "Number of active cells: "
- // << triangulation.n_active_cells()
- // << std::endl
- // << "Number of degrees of freedom: "
- // << dof_handler.n_dofs()
- // << " (" << n_u << '+' << n_p << ')'
- // << std::endl;
+ // << triangulation.n_active_cells()
+ // << std::endl
+ // << "Number of degrees of freedom: "
+ // << dof_handler.n_dofs()
+ // << " (" << n_u << '+' << n_p << ')'
+ // << std::endl;
{
BlockCompressedSimpleSparsityPattern csp (2,2);
for (unsigned int d=0; d<2; ++d)
for (unsigned int e=0; e<2; ++e)
- csp.block(d,e).reinit (dofs_per_block[d], dofs_per_block[e]);
+ csp.block(d,e).reinit (dofs_per_block[d], dofs_per_block[e]);
csp.collect_sizes();
system_matrix.reinit (sparsity_pattern);
- // this is from step-22
+ // this is from step-22
{
QGauss<dim> quadrature_formula(fe_degree+2);
FEValues<dim> fe_values (mapping, fe, quadrature_formula,
- update_values |
- update_JxW_values |
- update_gradients);
+ update_values |
+ update_JxW_values |
+ update_gradients);
const unsigned int dofs_per_cell = fe.dofs_per_cell;
const unsigned int n_q_points = quadrature_formula.size();
endc = dof_handler.end();
for (; cell!=endc; ++cell)
{
- fe_values.reinit (cell);
- local_matrix = 0;
-
- for (unsigned int q=0; q<n_q_points; ++q)
- {
- for (unsigned int k=0; k<dofs_per_cell; ++k)
- {
- phi_grads_u[k] = fe_values[velocities].symmetric_gradient (k, q);
- div_phi_u[k] = fe_values[velocities].divergence (k, q);
- phi_p[k] = fe_values[pressure].value (k, q);
- }
-
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- {
- for (unsigned int j=0; j<=i; ++j)
- {
- local_matrix(i,j) += (phi_grads_u[i] * phi_grads_u[j]
- - div_phi_u[i] * phi_p[j]
- - phi_p[i] * div_phi_u[j])
- * fe_values.JxW(q);
- }
- }
- }
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- for (unsigned int j=i+1; j<dofs_per_cell; ++j)
- local_matrix(i,j) = local_matrix(j,i);
-
- cell->get_dof_indices (local_dof_indices);
- constraints.distribute_local_to_global (local_matrix,
- local_dof_indices,
- system_matrix);
+ fe_values.reinit (cell);
+ local_matrix = 0;
+
+ for (unsigned int q=0; q<n_q_points; ++q)
+ {
+ for (unsigned int k=0; k<dofs_per_cell; ++k)
+ {
+ phi_grads_u[k] = fe_values[velocities].symmetric_gradient (k, q);
+ div_phi_u[k] = fe_values[velocities].divergence (k, q);
+ phi_p[k] = fe_values[pressure].value (k, q);
+ }
+
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ for (unsigned int j=0; j<=i; ++j)
+ {
+ local_matrix(i,j) += (phi_grads_u[i] * phi_grads_u[j]
+ - div_phi_u[i] * phi_p[j]
+ - phi_p[i] * div_phi_u[j])
+ * fe_values.JxW(q);
+ }
+ }
+ }
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ for (unsigned int j=i+1; j<dofs_per_cell; ++j)
+ local_matrix(i,j) = local_matrix(j,i);
+
+ cell->get_dof_indices (local_dof_indices);
+ constraints.distribute_local_to_global (local_matrix,
+ local_dof_indices,
+ system_matrix);
}
}
vec2[d].reinit (vec1[d]);
}
- // fill system_rhs with random numbers
+ // fill system_rhs with random numbers
for (unsigned int j=0; j<system_rhs.block(0).size(); ++j)
if (constraints_u.is_constrained(j) == false)
{
- const double val = -1 + 2.*(double)rand()/double(RAND_MAX);
- system_rhs.block(0)(j) = val;
- vec1[0](j) = val;
+ const double val = -1 + 2.*(double)rand()/double(RAND_MAX);
+ system_rhs.block(0)(j) = val;
+ vec1[0](j) = val;
}
for (unsigned int j=0; j<system_rhs.block(1).size(); ++j)
if (constraints_p.is_constrained(j) == false)
{
- const double val = -1 + 2.*(double)rand()/double(RAND_MAX);
- system_rhs.block(1)(j) = val;
- vec1[1](j) = val;
+ const double val = -1 + 2.*(double)rand()/double(RAND_MAX);
+ system_rhs.block(1)(j) = val;
+ vec1[1](j) = val;
}
- // setup matrix-free structure
+ // setup matrix-free structure
{
std::vector<const DoFHandler<dim>*> dofs;
dofs.push_back(&dof_handler_u);
constraints.push_back (&constraints_u);
constraints.push_back (&constraints_p);
QGauss<1> quad(fe_degree+2);
- // no parallelism
+ // no parallelism
mf_data.reinit (mapping, dofs, constraints, quad,
- typename MatrixFree<dim>::AdditionalData
- (MPI_COMM_WORLD,
- MatrixFree<dim>::AdditionalData::none));
+ typename MatrixFree<dim>::AdditionalData
+ (MPI_COMM_WORLD,
+ MatrixFree<dim>::AdditionalData::none));
}
system_matrix.vmult (solution, system_rhs);
MatrixFreeTest<dim,fe_degree,VectorType> mf (mf_data);
mf.vmult (vec2, vec1);
- // Verification
+ // Verification
double error = 0.;
for (unsigned int i=0; i<2; ++i)
for (unsigned int j=0; j<solution.block(i).size(); ++j)
error += std::fabs (solution.block(i)(j)-vec2[i](j));
double relative = solution.l1_norm();
deallog << "Verification fe degree " << fe_degree << ": "
- << error/relative << std::endl << std::endl;
+ << error/relative << std::endl << std::endl;
}
double error_points = 0, abs_points = 0;
const unsigned int n_cells = mf_data.get_size_info().n_macro_cells;
- FEEvaluation<dim,fe_degree+1> fe_eval (mf_data);
+ FEEvaluation<dim,fe_degree> fe_eval (mf_data);
FEValues<dim> fe_values (mapping, fe, mf_data.get_quad(),
- update_quadrature_points);
+ update_quadrature_points);
typedef VectorizedArray<double> vector_t;
for (unsigned int cell=0; cell<n_cells; ++cell)
{
fe_eval.reinit(cell);
for (unsigned int j=0; j<mf_data.n_components_filled(cell); ++j)
- {
- fe_values.reinit (mf_data.get_cell_iterator(cell,j));
- for (unsigned int q=0; q<fe_eval.n_q_points; ++q)
- {
- abs_points += fe_values.quadrature_point(q).norm();
- for (unsigned int d=0; d<dim; ++d)
- error_points += std::fabs(fe_values.quadrature_point(q)[d]-
- fe_eval.quadrature_point(q)[d][j]);
- }
- }
+ {
+ fe_values.reinit (mf_data.get_cell_iterator(cell,j));
+ for (unsigned int q=0; q<fe_eval.n_q_points; ++q)
+ {
+ abs_points += fe_values.quadrature_point(q).norm();
+ for (unsigned int d=0; d<dim; ++d)
+ error_points += std::fabs(fe_values.quadrature_point(q)[d]-
+ fe_eval.quadrature_point(q)[d][j]);
+ }
+ }
}
deallog << "Norm of difference: " << error_points/abs_points
- << std::endl << std::endl;
+ << std::endl << std::endl;
}
DoFHandler<dim> dof (tria);
deallog << "Testing " << fe.get_name() << std::endl;
- // run test for several different meshes
+ // run test for several different meshes
for (unsigned int i=0; i<8-2*dim; ++i)
{
cell = tria.begin_active ();
endc = tria.end();
unsigned int counter = 0;
for (; cell!=endc; ++cell, ++counter)
- if (counter % (9-i) == 0)
- cell->set_refine_flag();
+ if (counter % (9-i) == 0)
+ cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
dof.distribute_dofs(fe);
ConstraintMatrix constraints;
DoFTools::make_hanging_node_constraints(dof, constraints);
VectorTools::interpolate_boundary_values (dof, 0, ZeroFunction<dim>(),
- constraints);
+ constraints);
constraints.close();
//std::cout << "Number of cells: " << dof.get_tria().n_active_cells() << std::endl;
MatrixFree<dim,number> mf_data, mf_data_color, mf_data_partition;
{
- const QGauss<1> quad (fe_degree+1);
- mf_data.reinit (dof, constraints, quad,
- typename MatrixFree<dim,number>::AdditionalData(MPI_COMM_SELF,MatrixFree<dim,number>::AdditionalData::none));
-
- // choose block size of 3 which introduces
- // some irregularity to the blocks (stress the
- // non-overlapping computation harder)
- mf_data_color.reinit (dof, constraints, quad,
- typename MatrixFree<dim,number>::AdditionalData
- (MPI_COMM_SELF,
- MatrixFree<dim,number>::AdditionalData::partition_color,
- 3));
- mf_data_partition.reinit (dof, constraints, quad,
- typename MatrixFree<dim,number>::AdditionalData
- (MPI_COMM_SELF,
- MatrixFree<dim,number>::AdditionalData::partition_partition,
- 3));
+ const QGauss<1> quad (fe_degree+1);
+ mf_data.reinit (dof, constraints, quad,
+ typename MatrixFree<dim,number>::AdditionalData(MPI_COMM_SELF,MatrixFree<dim,number>::AdditionalData::none));
+
+ // choose block size of 3 which introduces
+ // some irregularity to the blocks (stress the
+ // non-overlapping computation harder)
+ mf_data_color.reinit (dof, constraints, quad,
+ typename MatrixFree<dim,number>::AdditionalData
+ (MPI_COMM_SELF,
+ MatrixFree<dim,number>::AdditionalData::partition_color,
+ 3));
+ mf_data_partition.reinit (dof, constraints, quad,
+ typename MatrixFree<dim,number>::AdditionalData
+ (MPI_COMM_SELF,
+ MatrixFree<dim,number>::AdditionalData::partition_partition,
+ 3));
}
- MatrixFreeTest<dim,fe_degree+1,number> mf_ref (mf_data);
- MatrixFreeTest<dim,fe_degree+1,number> mf_color (mf_data_color);
- MatrixFreeTest<dim,fe_degree+1,number> mf_partition (mf_data_partition);
+ MatrixFreeTest<dim,fe_degree,number> mf_ref (mf_data);
+ MatrixFreeTest<dim,fe_degree,number> mf_color (mf_data_color);
+ MatrixFreeTest<dim,fe_degree,number> mf_partition (mf_data_partition);
Vector<number> in_dist (dof.n_dofs());
Vector<number> out_dist (in_dist), out_color (in_dist),
- out_partition(in_dist);
+ out_partition(in_dist);
for (unsigned int i=0; i<dof.n_dofs(); ++i)
- {
- if(constraints.is_constrained(i))
- continue;
- const double entry = rand()/(double)RAND_MAX;
- in_dist(i) = entry;
- }
+ {
+ if(constraints.is_constrained(i))
+ continue;
+ const double entry = rand()/(double)RAND_MAX;
+ in_dist(i) = entry;
+ }
mf_ref.vmult (out_dist, in_dist);
- // make 10 sweeps in order to get in some
- // variation to the threaded program
+ // make 10 sweeps in order to get in some
+ // variation to the threaded program
for (unsigned int sweep = 0; sweep < 10; ++sweep)
- {
- mf_color.vmult (out_color, in_dist);
- mf_partition.vmult (out_partition, in_dist);
+ {
+ mf_color.vmult (out_color, in_dist);
+ mf_partition.vmult (out_partition, in_dist);
- out_color -= out_dist;
- double diff_norm = out_color.linfty_norm();
- deallog << "Sweep " << sweep
- << ", error in partition/color: " << diff_norm
- << std::endl;
- out_partition -= out_dist;
- diff_norm = out_partition.linfty_norm();
- deallog << "Sweep " << sweep
- << ", error in partition/partition: " << diff_norm
- << std::endl;
- }
+ out_color -= out_dist;
+ double diff_norm = out_color.linfty_norm();
+ deallog << "Sweep " << sweep
+ << ", error in partition/color: " << diff_norm
+ << std::endl;
+ out_partition -= out_dist;
+ diff_norm = out_partition.linfty_norm();
+ deallog << "Sweep " << sweep
+ << ", error in partition/partition: " << diff_norm
+ << std::endl;
+ }
deallog << std::endl;
}
deallog << std::endl;
void
local_apply (const MatrixFree<dim,Number> &data,
- Vector<Number> &dst,
- const Vector<Number> &src,
- const std::pair<unsigned int,unsigned int> &cell_range) const
+ Vector<Number> &dst,
+ const Vector<Number> &src,
+ const std::pair<unsigned int,unsigned int> &cell_range) const
{
- // Ask MatrixFree for cell_range for different
- // orders
+ // Ask MatrixFree for cell_range for different
+ // orders
std::pair<unsigned int,unsigned int> subrange_deg =
data.create_cell_subrange_hp (cell_range, 1);
if (subrange_deg.second > subrange_deg.first)
- helmholtz_operator<dim,2,Number> (data, dst, src,
- subrange_deg);
+ helmholtz_operator<dim,1,Number> (data, dst, src,
+ subrange_deg);
subrange_deg = data.create_cell_subrange_hp (cell_range, 2);
if (subrange_deg.second > subrange_deg.first)
- helmholtz_operator<dim,3,Number> (data, dst, src,
- subrange_deg);
+ helmholtz_operator<dim,2,Number> (data, dst, src,
+ subrange_deg);
subrange_deg = data.create_cell_subrange_hp (cell_range, 3);
if (subrange_deg.second > subrange_deg.first)
- helmholtz_operator<dim,4,Number> (data, dst, src,
- subrange_deg);
+ helmholtz_operator<dim,3,Number> (data, dst, src,
+ subrange_deg);
subrange_deg = data.create_cell_subrange_hp (cell_range, 4);
if (subrange_deg.second > subrange_deg.first)
- helmholtz_operator<dim,5,Number> (data, dst, src,
- subrange_deg);
+ helmholtz_operator<dim,4,Number> (data, dst, src,
+ subrange_deg);
subrange_deg = data.create_cell_subrange_hp (cell_range, 5);
if (subrange_deg.second > subrange_deg.first)
- helmholtz_operator<dim,6,Number> (data, dst, src,
- subrange_deg);
+ helmholtz_operator<dim,5,Number> (data, dst, src,
+ subrange_deg);
subrange_deg = data.create_cell_subrange_hp (cell_range, 6);
if (subrange_deg.second > subrange_deg.first)
- helmholtz_operator<dim,7,Number> (data, dst, src,
- subrange_deg);
+ helmholtz_operator<dim,6,Number> (data, dst, src,
+ subrange_deg);
subrange_deg = data.create_cell_subrange_hp (cell_range, 7);
if (subrange_deg.second > subrange_deg.first)
- helmholtz_operator<dim,8,Number> (data, dst, src,
- subrange_deg);
+ helmholtz_operator<dim,7,Number> (data, dst, src,
+ subrange_deg);
}
void vmult (Vector<Number> &dst,
- const Vector<Number> &src) const
+ const Vector<Number> &src) const
{
dst = 0;
data.cell_loop (&MatrixFreeTestHP<dim,Number>::local_apply, this, dst, src);
create_mesh (tria);
tria.refine_global(2);
- // refine a few cells
+ // refine a few cells
for (unsigned int i=0; i<11-3*dim; ++i)
{
typename Triangulation<dim>::active_cell_iterator
- cell = tria.begin_active (),
- endc = tria.end();
+ cell = tria.begin_active (),
+ endc = tria.end();
for (; cell!=endc; ++cell)
- if (rand() % (7-i) == 0)
- cell->set_refine_flag();
+ if (rand() % (7-i) == 0)
+ cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
}
}
hp::DoFHandler<dim> dof(tria);
- // set the active FE index in a random order
+ // set the active FE index in a random order
{
typename hp::DoFHandler<dim>::active_cell_iterator
cell = dof.begin_active(),
endc = dof.end();
for (; cell!=endc; ++cell)
{
- const unsigned int fe_index = rand() % max_degree;
- cell->set_active_fe_index (fe_index);
+ const unsigned int fe_index = rand() % max_degree;
+ cell->set_active_fe_index (fe_index);
}
}
- // setup DoFs
+ // setup DoFs
dof.distribute_dofs(fe_collection);
ConstraintMatrix constraints;
DoFTools::make_hanging_node_constraints (dof,
- constraints);
+ constraints);
VectorTools::interpolate_boundary_values (dof,
- 0,
- ZeroFunction<dim>(),
- constraints);
+ 0,
+ ZeroFunction<dim>(),
+ constraints);
constraints.close ();
//std::cout << "Number of cells: " << dof.get_tria().n_active_cells() << std::endl;
//std::cout << "Number of degrees of freedom: " << dof.n_dofs() << std::endl;
//std::cout << "Number of constraints: " << constraints.n_constraints() << std::endl;
- // set up reference MatrixFree
+ // set up reference MatrixFree
MatrixFree<dim,number> mf_data;
typename MatrixFree<dim,number>::AdditionalData data;
data.tasks_parallel_scheme =
if (parallel_option == 0)
{
data.tasks_parallel_scheme =
- MatrixFree<dim,number>::AdditionalData::partition_partition;
+ MatrixFree<dim,number>::AdditionalData::partition_partition;
deallog << "Parallel option partition/partition" << std::endl;
}
else
{
data.tasks_parallel_scheme =
- MatrixFree<dim,number>::AdditionalData::partition_color;
+ MatrixFree<dim,number>::AdditionalData::partition_color;
deallog << "Parallel option partition/color" << std::endl;
}
data.tasks_block_size = 1;
mf_data_par.reinit (dof, constraints, quadrature_collection_mf, data);
MatrixFreeTestHP<dim,number> mf_par(mf_data_par);
- // fill a right hand side vector with random
- // numbers in unconstrained degrees of freedom
+ // fill a right hand side vector with random
+ // numbers in unconstrained degrees of freedom
Vector<number> src (dof.n_dofs());
Vector<number> result_ref(src), result_mf (src);
for (unsigned int i=0; i<dof.n_dofs(); ++i)
{
if (constraints.is_constrained(i) == false)
- src(i) = (double)rand()/RAND_MAX;
+ src(i) = (double)rand()/RAND_MAX;
}
- // now perform 50 matrix-vector products in
- // parallel and check their correctness (take
- // many of them to make sure that we hit an
- // error)
+ // now perform 50 matrix-vector products in
+ // parallel and check their correctness (take
+ // many of them to make sure that we hit an
+ // error)
mf.vmult (result_ref, src);
deallog << "Norm of difference: ";
for (unsigned int i=0; i<50; ++i)
template <int dim, int fe_degree>
void test ()
{
- // 'misuse' fe_degree for setting the parallel
- // option here
+ // 'misuse' fe_degree for setting the parallel
+ // option here
unsigned int parallel_option = 0;
if (fe_degree == 1)
parallel_option = 0;
#include <iostream>
-template <int dim, int n_dofs_1d, typename Number>
+template <int dim, int fe_degree, typename Number>
void
helmholtz_operator (const MatrixFree<dim,Number> &data,
- parallel::distributed::Vector<Number> &dst,
- const parallel::distributed::Vector<Number> &src,
- const std::pair<unsigned int,unsigned int> &cell_range)
+ parallel::distributed::Vector<Number> &dst,
+ const parallel::distributed::Vector<Number> &src,
+ const std::pair<unsigned int,unsigned int> &cell_range)
{
- FEEvaluation<dim,n_dofs_1d,n_dofs_1d,1,Number> fe_eval (data);
+ FEEvaluation<dim,fe_degree,fe_degree+1,1,Number> fe_eval (data);
const unsigned int n_q_points = fe_eval.n_q_points;
for(unsigned int cell=cell_range.first;cell<cell_range.second;++cell)
{
fe_eval.reinit (cell);
- // compare values with the ones the FEValues
- // gives us. Those are seen as reference
+ // compare values with the ones the FEValues
+ // gives us. Those are seen as reference
fe_eval.read_dof_values (src);
fe_eval.evaluate (true, true, false);
for (unsigned int q=0; q<n_q_points; ++q)
- {
- fe_eval.submit_value (Number(10)*fe_eval.get_value(q),q);
- fe_eval.submit_gradient (fe_eval.get_gradient(q),q);
- }
+ {
+ fe_eval.submit_value (Number(10)*fe_eval.get_value(q),q);
+ fe_eval.submit_gradient (fe_eval.get_gradient(q),q);
+ }
fe_eval.integrate (true,true);
fe_eval.distribute_local_to_global (dst);
}
-template <int dim, int n_dofs_1d, typename Number>
+template <int dim, int fe_degree, typename Number>
class MatrixFreeTest
{
public:
{};
void vmult (parallel::distributed::Vector<Number> &dst,
- const parallel::distributed::Vector<Number> &src) const
+ const parallel::distributed::Vector<Number> &src) const
{
dst = 0;
const std_cxx1x::function<void(const MatrixFree<dim,Number> &,
- parallel::distributed::Vector<Number>&,
- const parallel::distributed::Vector<Number>&,
- const std::pair<unsigned int,unsigned int>&)>
- wrap = helmholtz_operator<dim,n_dofs_1d,Number>;
+ parallel::distributed::Vector<Number>&,
+ const parallel::distributed::Vector<Number>&,
+ const std::pair<unsigned int,unsigned int>&)>
+ wrap = helmholtz_operator<dim,fe_degree,Number>;
data.cell_loop (wrap, dst, src);
};
for (; cell!=endc; ++cell)
if (cell->is_locally_owned())
if (cell->center().norm()<0.2)
- cell->set_refine_flag();
+ cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
if (dim < 3 && fe_degree < 2)
tria.refine_global(2);
cell = tria.begin_active ();
unsigned int counter = 0;
for (; cell!=endc; ++cell, ++counter)
- if (cell->is_locally_owned())
- if (counter % (7-i) == 0)
- cell->set_refine_flag();
+ if (cell->is_locally_owned())
+ if (counter % (7-i) == 0)
+ cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
}
mf_data.reinit (dof, constraints, quad, data);
}
- MatrixFreeTest<dim,fe_degree+1,number> mf (mf_data);
+ MatrixFreeTest<dim,fe_degree,number> mf (mf_data);
parallel::distributed::Vector<number> in, out, ref;
mf_data.initialize_dof_vector (in);
out.reinit (in);
for (unsigned int i=0; i<in.local_size(); ++i)
{
const unsigned int glob_index =
- owned_set.nth_index_in_set (i);
+ owned_set.nth_index_in_set (i);
if(constraints.is_constrained(glob_index))
- continue;
+ continue;
in.local_element(i) = (double)rand()/RAND_MAX;
}
mf.vmult (out, in);
- // assemble trilinos sparse matrix with
- // (\nabla v, \nabla u) + (v, 10 * u) for
- // reference
+ // assemble trilinos sparse matrix with
+ // (\nabla v, \nabla u) + (v, 10 * u) for
+ // reference
TrilinosWrappers::SparseMatrix sparse_matrix;
{
TrilinosWrappers::SparsityPattern csp (owned_set, MPI_COMM_WORLD);
DoFTools::make_sparsity_pattern (dof, csp, constraints, true,
- Utilities::MPI::this_mpi_process(MPI_COMM_WORLD));
+ Utilities::MPI::this_mpi_process(MPI_COMM_WORLD));
csp.compress();
sparse_matrix.reinit (csp);
}
QGauss<dim> quadrature_formula(fe_degree+1);
FEValues<dim> fe_values (dof.get_fe(), quadrature_formula,
- update_values | update_gradients |
- update_JxW_values);
+ update_values | update_gradients |
+ update_JxW_values);
const unsigned int dofs_per_cell = dof.get_fe().dofs_per_cell;
const unsigned int n_q_points = quadrature_formula.size();
for (; cell!=endc; ++cell)
if (cell->is_locally_owned())
{
- cell_matrix = 0;
- fe_values.reinit (cell);
-
- for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- {
- for (unsigned int j=0; j<dofs_per_cell; ++j)
- cell_matrix(i,j) += ((fe_values.shape_grad(i,q_point) *
- fe_values.shape_grad(j,q_point)
- +
- 10. *
- fe_values.shape_value(i,q_point) *
- fe_values.shape_value(j,q_point)) *
- fe_values.JxW(q_point));
- }
-
- cell->get_dof_indices(local_dof_indices);
- constraints.distribute_local_to_global (cell_matrix,
- local_dof_indices,
- sparse_matrix);
+ cell_matrix = 0;
+ fe_values.reinit (cell);
+
+ for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ cell_matrix(i,j) += ((fe_values.shape_grad(i,q_point) *
+ fe_values.shape_grad(j,q_point)
+ +
+ 10. *
+ fe_values.shape_value(i,q_point) *
+ fe_values.shape_value(j,q_point)) *
+ fe_values.JxW(q_point));
+ }
+
+ cell->get_dof_indices(local_dof_indices);
+ constraints.distribute_local_to_global (cell_matrix,
+ local_dof_indices,
+ sparse_matrix);
}
}
sparse_matrix.compress();
#include <iostream>
-template <int dim, int n_dofs_1d, typename Number>
+template <int dim, int fe_degree, typename Number>
void
helmholtz_operator (const MatrixFree<dim,Number> &data,
- parallel::distributed::Vector<Number> &dst,
- const parallel::distributed::Vector<Number> &src,
- const std::pair<unsigned int,unsigned int> &cell_range)
+ parallel::distributed::Vector<Number> &dst,
+ const parallel::distributed::Vector<Number> &src,
+ const std::pair<unsigned int,unsigned int> &cell_range)
{
- FEEvaluation<dim,n_dofs_1d,n_dofs_1d,1,Number> fe_eval (data);
+ FEEvaluation<dim,fe_degree,fe_degree+1,1,Number> fe_eval (data);
const unsigned int n_q_points = fe_eval.n_q_points;
for(unsigned int cell=cell_range.first;cell<cell_range.second;++cell)
{
fe_eval.reinit (cell);
- // compare values with the ones the FEValues
- // gives us. Those are seen as reference
+ // compare values with the ones the FEValues
+ // gives us. Those are seen as reference
fe_eval.read_dof_values (src);
fe_eval.evaluate (true, true, false);
for (unsigned int q=0; q<n_q_points; ++q)
- {
- fe_eval.submit_value (Number(10)*fe_eval.get_value(q),q);
- fe_eval.submit_gradient (fe_eval.get_gradient(q),q);
- }
+ {
+ fe_eval.submit_value (Number(10)*fe_eval.get_value(q),q);
+ fe_eval.submit_gradient (fe_eval.get_gradient(q),q);
+ }
fe_eval.integrate (true,true);
fe_eval.distribute_local_to_global (dst);
}
-template <int dim, int n_dofs_1d, typename Number>
+template <int dim, int fe_degree, typename Number>
class MatrixFreeTest
{
public:
{};
void vmult (parallel::distributed::Vector<Number> &dst,
- const parallel::distributed::Vector<Number> &src) const
+ const parallel::distributed::Vector<Number> &src) const
{
dst = 0;
const std_cxx1x::function<void(const MatrixFree<dim,Number> &,
- parallel::distributed::Vector<Number>&,
- const parallel::distributed::Vector<Number>&,
- const std::pair<unsigned int,unsigned int>&)>
- wrap = helmholtz_operator<dim,n_dofs_1d,Number>;
+ parallel::distributed::Vector<Number>&,
+ const parallel::distributed::Vector<Number>&,
+ const std::pair<unsigned int,unsigned int>&)>
+ wrap = helmholtz_operator<dim,fe_degree,Number>;
data.cell_loop (wrap, dst, src);
};
for (; cell!=endc; ++cell)
if (cell->is_locally_owned())
if (cell->center().norm()<0.2)
- cell->set_refine_flag();
+ cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
if (fe_degree < 2)
tria.refine_global(2);
cell = tria.begin_active ();
unsigned int counter = 0;
for (; cell!=endc; ++cell, ++counter)
- if (cell->is_locally_owned())
- if (counter % (7-i) == 0)
- cell->set_refine_flag();
+ if (cell->is_locally_owned())
+ if (counter % (7-i) == 0)
+ cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
}
mf_data.reinit (dof, constraints, quad, data);
}
- MatrixFreeTest<dim,fe_degree+1,number> mf (mf_data);
+ MatrixFreeTest<dim,fe_degree,number> mf (mf_data);
parallel::distributed::Vector<number> in, out, ref;
mf_data.initialize_dof_vector (in);
out.reinit (in);
for (unsigned int i=0; i<in.local_size(); ++i)
{
const unsigned int glob_index =
- owned_set.nth_index_in_set (i);
+ owned_set.nth_index_in_set (i);
if(constraints.is_constrained(glob_index))
- continue;
+ continue;
in.local_element(i) = (double)rand()/RAND_MAX;
}
typename MatrixFree<dim,number>::AdditionalData data;
data.mpi_communicator = MPI_COMM_WORLD;
if (parallel_option == 0)
- {
- data.tasks_parallel_scheme =
- MatrixFree<dim,number>::AdditionalData::partition_partition;
- deallog << "Parallel option: partition partition" << std::endl;
- }
+ {
+ data.tasks_parallel_scheme =
+ MatrixFree<dim,number>::AdditionalData::partition_partition;
+ deallog << "Parallel option: partition partition" << std::endl;
+ }
else if (parallel_option == 1)
- {
- data.tasks_parallel_scheme =
- MatrixFree<dim,number>::AdditionalData::partition_color;
- deallog << "Parallel option: partition color" << std::endl;
- }
+ {
+ data.tasks_parallel_scheme =
+ MatrixFree<dim,number>::AdditionalData::partition_color;
+ deallog << "Parallel option: partition color" << std::endl;
+ }
else if (parallel_option == 2)
- {
- data.tasks_parallel_scheme =
- MatrixFree<dim,number>::AdditionalData::color;
- deallog << "Parallel option: color" << std::endl;
- }
+ {
+ data.tasks_parallel_scheme =
+ MatrixFree<dim,number>::AdditionalData::color;
+ deallog << "Parallel option: color" << std::endl;
+ }
data.tasks_block_size = 3;
mf_data.reinit (dof, constraints, quad, data);
- MatrixFreeTest<dim, fe_degree+1, number> mf (mf_data);
+ MatrixFreeTest<dim, fe_degree, number> mf (mf_data);
MPI_Barrier(MPI_COMM_WORLD);
deallog << "Norm of difference:";
- // run 10 times to make a possible error more
- // likely to show up
+ // run 10 times to make a possible error more
+ // likely to show up
for (unsigned int run=0; run<10; ++run)
- {
- mf.vmult (out, in);
- out -= ref;
- const double diff_norm = out.linfty_norm();
- deallog << " " << diff_norm;
- }
+ {
+ mf.vmult (out, in);
+ out -= ref;
+ const double diff_norm = out.linfty_norm();
+ deallog << " " << diff_norm;
+ }
deallog << std::endl;
}
deallog << std::endl;
#include <iostream>
-template <int dim, int n_dofs_1d, typename Number>
+template <int dim, int fe_degree, typename Number>
void
helmholtz_operator (const MatrixFree<dim,Number> &data,
- std::vector<parallel::distributed::Vector<Number> > &dst,
- const std::vector<parallel::distributed::Vector<Number> > &src,
- const std::pair<unsigned int,unsigned int> &cell_range)
+ std::vector<parallel::distributed::Vector<Number> > &dst,
+ const std::vector<parallel::distributed::Vector<Number> > &src,
+ const std::pair<unsigned int,unsigned int> &cell_range)
{
- FEEvaluation<dim,n_dofs_1d,n_dofs_1d,2,Number> fe_eval (data);
+ FEEvaluation<dim,fe_degree,fe_degree+1,2,Number> fe_eval (data);
const unsigned int n_q_points = fe_eval.n_q_points;
for(unsigned int cell=cell_range.first;cell<cell_range.second;++cell)
{
fe_eval.reinit (cell);
- // compare values with the ones the FEValues
- // gives us. Those are seen as reference
+ // compare values with the ones the FEValues
+ // gives us. Those are seen as reference
fe_eval.read_dof_values (src);
fe_eval.evaluate (true, true, false);
for (unsigned int q=0; q<n_q_points; ++q)
- {
- fe_eval.submit_value (make_vectorized_array(Number(10))*
- fe_eval.get_value(q), q);
- fe_eval.submit_gradient (fe_eval.get_gradient(q),q);
- }
+ {
+ fe_eval.submit_value (make_vectorized_array(Number(10))*
+ fe_eval.get_value(q), q);
+ fe_eval.submit_gradient (fe_eval.get_gradient(q),q);
+ }
fe_eval.integrate (true,true);
fe_eval.distribute_local_to_global (dst);
}
-template <int dim, int n_dofs_1d, typename Number>
+template <int dim, int fe_degree, typename Number>
class MatrixFreeTest
{
public:
{};
void vmult (std::vector<parallel::distributed::Vector<Number> > &dst,
- const std::vector<parallel::distributed::Vector<Number> > &src) const
+ const std::vector<parallel::distributed::Vector<Number> > &src) const
{
for (unsigned int i=0; i<dst.size(); ++i)
dst[i] = 0;
const std_cxx1x::function<void(const MatrixFree<dim,Number> &,
- std::vector<parallel::distributed::Vector<Number> >&,
- const std::vector<parallel::distributed::Vector<Number> >&,
- const std::pair<unsigned int,unsigned int>&)>
- wrap = helmholtz_operator<dim,n_dofs_1d,Number>;
+ std::vector<parallel::distributed::Vector<Number> >&,
+ const std::vector<parallel::distributed::Vector<Number> >&,
+ const std::pair<unsigned int,unsigned int>&)>
+ wrap = helmholtz_operator<dim,fe_degree,Number>;
data.cell_loop (wrap, dst, src);
};
for (; cell!=endc; ++cell)
if (cell->is_locally_owned())
if (cell->center().norm()<0.2)
- cell->set_refine_flag();
+ cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
if (dim < 3 && fe_degree < 2)
tria.refine_global(2);
cell = tria.begin_active ();
unsigned int counter = 0;
for (; cell!=endc; ++cell, ++counter)
- if (cell->is_locally_owned())
- if (counter % (7-i) == 0)
- cell->set_refine_flag();
+ if (cell->is_locally_owned())
+ if (counter % (7-i) == 0)
+ cell->set_refine_flag();
tria.execute_coarsening_and_refinement();
}
mf_data.reinit (dof, constraints, quad, data);
}
- MatrixFreeTest<dim,fe_degree+1,number> mf (mf_data);
+ MatrixFreeTest<dim,fe_degree,number> mf (mf_data);
parallel::distributed::Vector<number> ref;
std::vector<parallel::distributed::Vector<number> > in(2), out(2);
for (unsigned int i=0; i<2; ++i)
for (unsigned int i=0; i<in[0].local_size(); ++i)
{
const unsigned int glob_index =
- owned_set.nth_index_in_set (i);
+ owned_set.nth_index_in_set (i);
if(constraints.is_constrained(glob_index))
- continue;
+ continue;
in[0].local_element(i) = (double)rand()/RAND_MAX;
in[1].local_element(i) = (double)rand()/RAND_MAX;
}
mf.vmult (out, in);
- // assemble trilinos sparse matrix with
- // (\nabla v, \nabla u) + (v, 10 * u) for
- // reference
+ // assemble trilinos sparse matrix with
+ // (\nabla v, \nabla u) + (v, 10 * u) for
+ // reference
TrilinosWrappers::SparseMatrix sparse_matrix;
{
TrilinosWrappers::SparsityPattern csp (owned_set, MPI_COMM_WORLD);
DoFTools::make_sparsity_pattern (dof, csp, constraints, true,
- Utilities::MPI::this_mpi_process(MPI_COMM_WORLD));
+ Utilities::MPI::this_mpi_process(MPI_COMM_WORLD));
csp.compress();
sparse_matrix.reinit (csp);
}
QGauss<dim> quadrature_formula(fe_degree+1);
FEValues<dim> fe_values (dof.get_fe(), quadrature_formula,
- update_values | update_gradients |
- update_JxW_values);
+ update_values | update_gradients |
+ update_JxW_values);
const unsigned int dofs_per_cell = dof.get_fe().dofs_per_cell;
const unsigned int n_q_points = quadrature_formula.size();
for (; cell!=endc; ++cell)
if (cell->is_locally_owned())
{
- cell_matrix = 0;
- fe_values.reinit (cell);
-
- for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- {
- for (unsigned int j=0; j<dofs_per_cell; ++j)
- cell_matrix(i,j) += ((fe_values.shape_grad(i,q_point) *
- fe_values.shape_grad(j,q_point)
- +
- 10. *
- fe_values.shape_value(i,q_point) *
- fe_values.shape_value(j,q_point)) *
- fe_values.JxW(q_point));
- }
-
- cell->get_dof_indices(local_dof_indices);
- constraints.distribute_local_to_global (cell_matrix,
- local_dof_indices,
- sparse_matrix);
+ cell_matrix = 0;
+ fe_values.reinit (cell);
+
+ for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ cell_matrix(i,j) += ((fe_values.shape_grad(i,q_point) *
+ fe_values.shape_grad(j,q_point)
+ +
+ 10. *
+ fe_values.shape_value(i,q_point) *
+ fe_values.shape_value(j,q_point)) *
+ fe_values.JxW(q_point));
+ }
+
+ cell->get_dof_indices(local_dof_indices);
+ constraints.distribute_local_to_global (cell_matrix,
+ local_dof_indices,
+ sparse_matrix);
}
}
sparse_matrix.compress();
{
global_size += set - i;
if (i<myid)
- my_start += set - i;
+ my_start += set - i;
}
- // each processor owns some indices and all
+ // each processor owns some indices and all
// are ghosting elements from three
// processors (the second). some entries
// are right around the border between two
IndexSet local_relevant(global_size);
local_relevant = local_owned;
unsigned int ghost_indices [10] = {1, 2, 13, set-2, set-1, set, set+1, 2*set,
- 2*set+1, 2*set+3};
+ 2*set+1, 2*set+3};
local_relevant.add_indices (&ghost_indices[0], &ghost_indices[0]+10);
Utilities::MPI::Partitioner v(local_owned, local_relevant, MPI_COMM_WORLD);
- // check number of ghosts everywhere (counted
- // the above)
+ // check number of ghosts everywhere (counted
+ // the above)
if (myid == 0)
{
AssertDimension (v.n_ghost_indices(), 5);
AssertDimension (v.n_ghost_indices(), 10);
}
- // count that 13 is ghost only on non-owning
- // processors
+ // count that 13 is ghost only on non-owning
+ // processors
if (myid == 0)
{
Assert (v.is_ghost_entry (13) == false, ExcInternalError());
Assert (v.is_ghost_entry (13) == true, ExcInternalError());
}
- // count that 27 is ghost nowhere
+ // count that 27 is ghost nowhere
Assert (v.is_ghost_entry (27) == false, ExcInternalError());
if (myid == 0)
{
Assert (v.in_local_range (27) == false, ExcInternalError());
}
- // element with number set is ghost
+ // element with number set is ghost
if (myid == 1)
{
Assert (v.is_ghost_entry (set) == false, ExcInternalError());
{
global_size += set - i;
if (i<myid)
- my_start += set - i;
+ my_start += set - i;
}
- // each processor owns some indices and all
+ // each processor owns some indices and all
// are ghosting elements from three
// processors (the second). some entries
// are right around the border between two
if (myid < 6)
{
unsigned int ghost_indices [10] = {1, 2, 13, set-2, set-1, set, set+1, 2*set,
- 2*set+1, 2*set+3};
+ 2*set+1, 2*set+3};
local_relevant.add_indices (&ghost_indices[0], &ghost_indices[0]+10);
}
Utilities::MPI::Partitioner v(local_owned, local_relevant, MPI_COMM_WORLD);
- // check number of import indices everywhere
- // (counted the above) times the number of
- // processors which have these as ghosts
+ // check number of import indices everywhere
+ // (counted the above) times the number of
+ // processors which have these as ghosts
const unsigned int n_procs_with_ghosts = std::min (numproc-1, 5U);
if (myid == 0)
{
{
global_size += set - i;
if (i<myid)
- my_start += set - i;
+ my_start += set - i;
}
- // each processor owns some indices and all
+ // each processor owns some indices and all
// are ghosting elements from three
// processors (the second). some entries
// are right around the border between two
IndexSet local_relevant(global_size);
local_relevant = local_owned;
unsigned int ghost_indices [10] = {1, 2, 13, set-2, set-1, set, set+1, 2*set,
- 2*set+1, 2*set+3};
+ 2*set+1, 2*set+3};
local_relevant.add_indices (&ghost_indices[0], &ghost_indices[0]+10);
Utilities::MPI::Partitioner v(local_owned, local_relevant, MPI_COMM_WORLD);
- // write the info on ghost processors and import indices to file
+ // write the info on ghost processors and import indices to file
{
std::ofstream file((std::string("parallel_partitioner_03/ncpu_") + Utilities::int_to_string(Utilities::MPI::n_mpi_processes (MPI_COMM_WORLD)) + "/dat." + Utilities::int_to_string(myid)).c_str());
file << "**** proc " << myid << std::endl;
file << "ghost targets: ";
for (unsigned int i=0; i<v.ghost_targets().size(); ++i)
file << "[" << v.ghost_targets()[i].first << "/"
- << v.ghost_targets()[i].second << "] ";
+ << v.ghost_targets()[i].second << "] ";
file << std::endl;
file << "import targets: ";
for (unsigned int i=0; i<v.import_targets().size(); ++i)
file << "[" << v.import_targets()[i].first << "/"
- << v.import_targets()[i].second << "] ";
+ << v.import_targets()[i].second << "] ";
file << std::endl;
file << "import indices:" << std::endl;
for (unsigned int i=0; i<v.import_indices().size(); ++i)
file << "[" << v.import_indices()[i].first << "/"
- << v.import_indices()[i].second << ")" << std::endl;
+ << v.import_indices()[i].second << ")" << std::endl;
file << "****" << std::endl;
}
{
global_size += set - i;
if (i<myid)
- my_start += set - i;
+ my_start += set - i;
}
- // each processor owns some indices and all
+ // each processor owns some indices and all
// are ghosting elements from three
// processors (the second). some entries
// are right around the border between two
IndexSet local_relevant(global_size);
local_relevant = local_owned;
unsigned int ghost_indices [10] = {1, 2, 13, set-2, set-1, set, set+1, 2*set,
- 2*set+1, 2*set+3};
+ 2*set+1, 2*set+3};
local_relevant.add_indices (&ghost_indices[0], &ghost_indices[0]+10);
Utilities::MPI::Partitioner v(local_owned, local_relevant, MPI_COMM_WORLD);
- // check locally owned range
+ // check locally owned range
for (unsigned int i=my_start; i<my_start+local_size; ++i)
{
AssertDimension (v.global_to_local(i), i-my_start);
AssertDimension (v.local_to_global(i-my_start), i);
}
- // check ghost indices
+ // check ghost indices
for (unsigned int i=0, count=0; i<10; ++i)
if (ghost_indices[i] < my_start || ghost_indices[i] >= my_start+local_size)
{
- AssertDimension (local_size+count, v.global_to_local(ghost_indices[i]));
- AssertDimension (ghost_indices[i], v.local_to_global(local_size+count));
- ++count;
+ AssertDimension (local_size+count, v.global_to_local(ghost_indices[i]));
+ AssertDimension (ghost_indices[i], v.local_to_global(local_size+count));
+ ++count;
}
- // check that loc->glob and glob->loc form an
- // identity operation
+ // check that loc->glob and glob->loc form an
+ // identity operation
for (unsigned int i=0; i<local_size+v.n_ghost_indices(); ++i)
AssertDimension (i, v.global_to_local(v.local_to_global(i)));
if (myid==0) deallog << "numproc=" << numproc << std::endl;
- // each processor owns 2 indices and all
+ // each processor owns 2 indices and all
// are ghosting element 1 (the second)
IndexSet local_owned(numproc*2);
local_owned.add_range(myid*2,myid*2+2);
Assert(v(myid*2) == myid*4.0, ExcInternalError());
Assert(v(myid*2+1) == myid*4.0+2.0, ExcInternalError());
- // check l2 norm
+ // check l2 norm
const double l2_norm = v.l2_norm();
if (myid == 0)
deallog << "L2 norm: " << l2_norm << std::endl;
if (myid==0) deallog << "numproc=" << numproc << std::endl;
- // each processor owns 2 indices and all
+ // each processor owns 2 indices and all
// are ghosting element 1 (the second)
IndexSet local_owned(numproc*2);
local_owned.add_range(myid*2,myid*2+2);
Assert(v(myid*2) == myid*4.0, ExcInternalError());
Assert(v(myid*2+1) == myid*4.0+2.0, ExcInternalError());
- // set ghost dof, compress
+ // set ghost dof, compress
v(1) = 7;
v.compress();
deallog << myid*2+1 << ":" << v(myid*2+1) << std::endl;
}
- // import ghosts onto all procs
+ // import ghosts onto all procs
v.update_ghost_values();
Assert (v(1) == 7. * numproc, ExcInternalError());
- // check l2 norm
+ // check l2 norm
const double l2_norm = v.l2_norm();
if (myid == 0)
deallog << "L2 norm: " << l2_norm << std::endl;
if (myid==0) deallog << "numproc=" << numproc << std::endl;
- // each processor owns 2 indices and all
+ // each processor owns 2 indices and all
// are ghosting element 1 (the second)
IndexSet local_owned(numproc*2);
local_owned.add_range(myid*2,myid*2+2);
Assert(v(myid*2) == myid*4.0, ExcInternalError());
Assert(v(myid*2+1) == myid*4.0+2.0, ExcInternalError());
- // set ghost dof on remote processors,
- // compress (no addition)
+ // set ghost dof on remote processors,
+ // compress (no addition)
if (myid > 0)
v(1) = 7;
v.compress(/* add_ghost_data = */ false);
deallog << myid*2+1 << ":" << v(myid*2+1) << std::endl;
}
- // import ghosts onto all procs
+ // import ghosts onto all procs
v.update_ghost_values();
Assert (v(1) == 7.0, ExcInternalError());
- // check l2 norm
+ // check l2 norm
const double l2_norm = v.l2_norm();
if (myid == 0)
deallog << "L2 norm: " << l2_norm << std::endl;
if (myid==0) deallog << "numproc=" << numproc << std::endl;
- // each processor owns 2 indices and all
+ // each processor owns 2 indices and all
// are ghosting element 1 (the second)
IndexSet local_owned(numproc*2);
local_owned.add_range(myid*2,myid*2+2);
Assert(v(myid*2) == myid*4.0, ExcInternalError());
Assert(v(myid*2+1) == myid*4.0+2.0, ExcInternalError());
- // set ghost dof on remote processors, no
- // compress called
+ // set ghost dof on remote processors, no
+ // compress called
if (myid > 0)
v(1) = 7;
if (myid > 0)
Assert (v(1) == 7.0, ExcInternalError());
- // reset to zero
+ // reset to zero
v = 0;
Assert(v(myid*2) == 0., ExcInternalError());
Assert(v(myid*2+1) == 0., ExcInternalError());
- // check that everything remains zero also
- // after compress
+ // check that everything remains zero also
+ // after compress
v.compress();
Assert(v(myid*2) == 0., ExcInternalError());
Assert(v(myid*2+1) == 0., ExcInternalError());
- // set element 1 on owning process to
- // something nonzero
+ // set element 1 on owning process to
+ // something nonzero
if (myid == 0)
v(1) = 2.;
if (myid > 0)
Assert (v(1) == 0., ExcInternalError());
- // check that all processors get the correct
- // value again, and that it is erased by
- // operator=
+ // check that all processors get the correct
+ // value again, and that it is erased by
+ // operator=
v.update_ghost_values();
Assert (v(1) == 2.0, ExcInternalError());
if (myid==0) deallog << "numproc=" << numproc << std::endl;
- // each processor owns 2 indices and all
+ // each processor owns 2 indices and all
// are ghosting element 1 (the second)
IndexSet local_owned(numproc*2);
local_owned.add_range(myid*2,myid*2+2);
Assert(v(myid*2) == myid*4.0, ExcInternalError());
Assert(v(myid*2+1) == myid*4.0+2.0, ExcInternalError());
- // set ghost dof on remote processors,
- // compress
+ // set ghost dof on remote processors,
+ // compress
if (myid > 0)
v(1) = 0;
v.compress();
- // check that nothing has changed
+ // check that nothing has changed
Assert(v(myid*2) == myid*4.0, ExcInternalError());
Assert(v(myid*2+1) == myid*4.0+2.0, ExcInternalError());
{
global_size += set - i;
if (i<myid)
- my_start += set - i;
+ my_start += set - i;
}
- // each processor owns some indices and all
+ // each processor owns some indices and all
// are ghosting elements from three
// processors (the second). some entries
// are right around the border between two
IndexSet local_relevant(global_size);
local_relevant = local_owned;
unsigned int ghost_indices [10] = {1, 2, 13, set-2, set-1, set, set+1, 2*set,
- 2*set+1, 2*set+3};
+ 2*set+1, 2*set+3};
local_relevant.add_indices (&ghost_indices[0], &ghost_indices[0]+10);
parallel::distributed::Vector<double> v(local_owned, local_relevant, MPI_COMM_WORLD);
- // set a few of the local elements
+ // set a few of the local elements
for (unsigned i=0; i<local_size; ++i)
v.local_element(i) = 2.0 * (i + my_start);
v.compress();
v.update_ghost_values();
- // check local values for correctness
+ // check local values for correctness
for (unsigned int i=0; i<local_size; ++i)
Assert (v.local_element(i) == 2.0 * (i + my_start), ExcInternalError());
- // check local values with two different
- // access operators
+ // check local values with two different
+ // access operators
for (unsigned int i=0; i<local_size; ++i)
Assert (v.local_element(i) == v(local_owned.nth_index_in_set (i)), ExcInternalError());
for (unsigned int i=0; i<local_size; ++i)
Assert (v.local_element(i) == v(i+my_start), ExcInternalError());
- // check non-local entries on all processors
+ // check non-local entries on all processors
for (unsigned int i=0; i<10; ++i)
Assert (v(ghost_indices[i])== 2. * ghost_indices[i], ExcInternalError());
- // compare direct access [] with access ()
+ // compare direct access [] with access ()
for (unsigned int i=0; i<10; ++i)
if (ghost_indices[i] < my_start)
Assert (v(ghost_indices[i])==v.local_element(local_size+i), ExcInternalError());
{
global_size += set - i;
if (i<myid)
- my_start += set - i;
+ my_start += set - i;
}
- // each processor owns some indices and all
+ // each processor owns some indices and all
// are ghosting elements from three
// processors (the second). some entries
// are right around the border between two
IndexSet local_relevant(global_size);
local_relevant = local_owned;
unsigned int ghost_indices [10] = {1, 2, 13, set-2, set-1, set, set+1, 2*set,
- 2*set+1, 2*set+3};
+ 2*set+1, 2*set+3};
local_relevant.add_indices (&ghost_indices[0], &ghost_indices[0]+10);
- // v has ghosts, w has none. set some entries
- // on w, copy into v and check if they are
- // there
+ // v has ghosts, w has none. set some entries
+ // on w, copy into v and check if they are
+ // there
parallel::distributed::Vector<double> v(local_owned, local_relevant, MPI_COMM_WORLD);
parallel::distributed::Vector<double> w(local_owned, local_owned, MPI_COMM_WORLD);
- // set a few of the local elements
+ // set a few of the local elements
for (unsigned i=0; i<local_size; ++i)
w.local_element(i) = 2.0 * (i + my_start);
v.copy_from(w);
v.update_ghost_values();
- // check local values for correctness
+ // check local values for correctness
for (unsigned int i=0; i<local_size; ++i)
Assert (v.local_element(i) == 2.0 * (i + my_start), ExcInternalError());
- // check local values with two different
- // access operators
+ // check local values with two different
+ // access operators
for (unsigned int i=0; i<local_size; ++i)
Assert (v.local_element(i) == v(local_owned.nth_index_in_set (i)), ExcInternalError());
for (unsigned int i=0; i<local_size; ++i)
Assert (v.local_element(i) == v(i+my_start), ExcInternalError());
- // check non-local entries on all processors
+ // check non-local entries on all processors
for (unsigned int i=0; i<10; ++i)
Assert (v(ghost_indices[i])== 2. * ghost_indices[i], ExcInternalError());
- // compare direct access local_element with access ()
+ // compare direct access local_element with access ()
for (unsigned int i=0; i<10; ++i)
if (ghost_indices[i] < my_start)
Assert (v(ghost_indices[i])==v.local_element(local_size+i), ExcInternalError());
Assert (v(ghost_indices[i])==v.local_element(local_size+i-5), ExcInternalError());
- // now the same again, but import ghosts
- // through the call to copy_from
+ // now the same again, but import ghosts
+ // through the call to copy_from
v.reinit (local_owned, local_relevant, MPI_COMM_WORLD);
v.copy_from(w, true);
- // check local values for correctness
+ // check local values for correctness
for (unsigned int i=0; i<local_size; ++i)
Assert (v.local_element(i) == 2.0 * (i + my_start), ExcInternalError());
- // check local values with two different
- // access operators
+ // check local values with two different
+ // access operators
for (unsigned int i=0; i<local_size; ++i)
Assert (v.local_element(i) == v(local_owned.nth_index_in_set (i)), ExcInternalError());
for (unsigned int i=0; i<local_size; ++i)
Assert (v.local_element(i) == v(i+my_start), ExcInternalError());
- // check non-local entries on all processors
+ // check non-local entries on all processors
for (unsigned int i=0; i<10; ++i)
Assert (v(ghost_indices[i])== 2. * ghost_indices[i], ExcInternalError());
- // compare direct access [] with access ()
+ // compare direct access [] with access ()
for (unsigned int i=0; i<10; ++i)
if (ghost_indices[i] < my_start)
Assert (v(ghost_indices[i])==v.local_element(local_size+i), ExcInternalError());
Assert (v(ghost_indices[i])==v.local_element(local_size+i-5), ExcInternalError());
- // now do not call import_ghosts and check
- // whether ghosts really are zero
+ // now do not call import_ghosts and check
+ // whether ghosts really are zero
v.reinit (local_owned, local_relevant, MPI_COMM_WORLD);
v.copy_from(w, false);
- // check non-local entries on all processors
+ // check non-local entries on all processors
for (unsigned int i=0; i<10; ++i)
if (local_owned.is_element (ghost_indices[i]) == false)
Assert (v(ghost_indices[i]) == 0., ExcInternalError());
{
global_size += set - i;
if (i<myid)
- my_start += set - i;
+ my_start += set - i;
}
- // each processor owns some indices and all
+ // each processor owns some indices and all
// are ghosting elements from three
// processors (the second). some entries
// are right around the border between two
IndexSet local_relevant(global_size);
local_relevant = local_owned;
unsigned int ghost_indices [10] = {1, 2, 13, set-2, set-1, set, set+1, 2*set,
- 2*set+1, 2*set+3};
+ 2*set+1, 2*set+3};
local_relevant.add_indices (&ghost_indices[0], &ghost_indices[0]+10);
parallel::distributed::Vector<double> v(local_owned, local_relevant, MPI_COMM_WORLD);
- // check number of ghosts everywhere (counted
- // the above)
+ // check number of ghosts everywhere (counted
+ // the above)
if (myid == 0)
{
AssertDimension (v.n_ghost_entries(), 5);
AssertDimension (v.n_ghost_entries(), 10);
}
- // count that 13 is ghost only on non-owning
- // processors
+ // count that 13 is ghost only on non-owning
+ // processors
if (myid == 0)
{
Assert (v.is_ghost_entry (13) == false, ExcInternalError());
Assert (v.is_ghost_entry (13) == true, ExcInternalError());
}
- // count that 27 is ghost nowhere
+ // count that 27 is ghost nowhere
Assert (v.is_ghost_entry (27) == false, ExcInternalError());
if (myid == 0)
{
Assert (v.in_local_range (27) == false, ExcInternalError());
}
- // element with number set is ghost
+ // element with number set is ghost
if (myid == 1)
{
Assert (v.is_ghost_entry (set) == false, ExcInternalError());
if (myid==0) deallog << "numproc=" << numproc << std::endl;
- // each processor owns 2 indices and all
+ // each processor owns 2 indices and all
// are ghosting element 1 (the second)
IndexSet local_owned(numproc*2);
local_owned.add_range(myid*2,myid*2+2);
v.compress();
v.update_ghost_values();
- // check that the value of the ghost is 1.0
+ // check that the value of the ghost is 1.0
Assert (v(1) == 1., ExcInternalError());
- // copy vector
+ // copy vector
w = v;
v *= 2.0;
if (myid==0) deallog << "numproc=" << numproc << std::endl;
- // global size: 20, local_size: 3 as long as
- // less than 20
+ // global size: 20, local_size: 3 as long as
+ // less than 20
const unsigned int local_size = 3;
const unsigned int global_size = std::min(20U, local_size * numproc);
const int my_start = std::min (local_size * myid, global_size);
IndexSet local_owned (global_size);
if (my_end > my_start)
local_owned.add_range(static_cast<unsigned int>(my_start),
- static_cast<unsigned int>(my_end));
+ static_cast<unsigned int>(my_end));
IndexSet local_relevant(global_size);
local_relevant = local_owned;
local_relevant.add_index (2);
parallel::distributed::Vector<double> v(local_owned, local_relevant,
- MPI_COMM_WORLD);
+ MPI_COMM_WORLD);
AssertDimension (actual_local_size, v.local_size());
parallel::distributed::Vector<double> w (v), x(v), y(v);
- // set local elements
+ // set local elements
for (int i=0; i<actual_local_size; ++i)
{
v.local_element(i) = i + my_start;
if (myid==0) deallog << "numproc=" << numproc << std::endl;
- // vector 0:
- // global size: 20, local_size: 3 as long as
- // less than 20
+ // vector 0:
+ // global size: 20, local_size: 3 as long as
+ // less than 20
const unsigned int local_size0 = 3;
const unsigned int global_size0 = std::min(20U, local_size0 * numproc);
const unsigned int my_start0 = std::min (local_size0 * myid, global_size0);
IndexSet local_owned0 (global_size0);
if (my_end0 > my_start0)
local_owned0.add_range(static_cast<unsigned int>(my_start0),
- static_cast<unsigned int>(my_end0));
+ static_cast<unsigned int>(my_end0));
IndexSet local_relevant0(global_size0);
local_relevant0 = local_owned0;
local_relevant0.add_index (2);
local_relevant0.add_index(8);
parallel::distributed::Vector<double> v0(local_owned0, local_relevant0,
- MPI_COMM_WORLD);
+ MPI_COMM_WORLD);
- // vector1: local size 4
+ // vector1: local size 4
const unsigned int local_size1 = 4;
const unsigned int global_size1 = local_size1 * numproc;
const int my_start1 = local_size1 * myid;
IndexSet local_owned1 (global_size1);
local_owned1.add_range(static_cast<unsigned int>(my_start1),
- static_cast<unsigned int>(my_end1));
+ static_cast<unsigned int>(my_end1));
IndexSet local_relevant1(global_size1);
local_relevant1 = local_owned1;
local_relevant1.add_index (0);
}
parallel::distributed::Vector<double> v1(local_owned1, local_relevant1,
- MPI_COMM_WORLD);
+ MPI_COMM_WORLD);
v0 = 1;
v1 = 2;
- // check assignment in initial state
+ // check assignment in initial state
for (unsigned int i=0; i<v0.local_size(); ++i)
Assert (v0.local_element(i) == 1., ExcNonEqual(v0.local_element(i),1.));
for (unsigned int i=0; i<v1.local_size(); ++i)
Assert (v1.local_element(i) == 2., ExcNonEqual(v1.local_element(i),2.));
- // check ghost elements in initial state
+ // check ghost elements in initial state
v0.update_ghost_values();
v1.update_ghost_values();
Assert (v0(2) == 1., ExcNonEqual(v0(2),1.));
Assert (v1(10) == 2., ExcNonEqual(v1(10),2.));
}
if (myid==0) deallog << "Initial set and ghost update OK" << std::endl;
+ MPI_Barrier (MPI_COMM_WORLD);
- // now swap v1 and v0
+ // now swap v1 and v0
v0.swap (v1);
AssertDimension (v0.local_size(), local_size1);
AssertDimension (v1.local_size(), actual_local_size0);
}
if (myid==0) deallog << "Ghost values after first swap OK" << std::endl;
- // now set the vectors to some different
- // values and check the ghost values again
+ // now set the vectors to some different
+ // values and check the ghost values again
v0 = 7.;
v1 = 42.;
v0.update_ghost_values();
}
if (myid==0) deallog << "Ghost values after re-set OK" << std::endl;
- // swap with an empty vector
+ // swap with an empty vector
parallel::distributed::Vector<double> v2;
v2.swap (v0);
AssertDimension (v0.size(), 0);