From: Wolfgang Bangerth Date: Sat, 13 Oct 2007 05:03:05 +0000 (+0000) Subject: Implement the data structures to deal with vector-valued output. X-Git-Tag: v8.0.0~9761 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=af04cd83085c642320504e4d3927811ae3102963;p=dealii.git Implement the data structures to deal with vector-valued output. git-svn-id: https://svn.dealii.org/trunk@15312 0785d39b-7218-0410-832d-ea1e28bc413d --- diff --git a/deal.II/deal.II/include/numerics/data_out.h b/deal.II/deal.II/include/numerics/data_out.h index 9a9cf15b41..8dff86c212 100644 --- a/deal.II/deal.II/include/numerics/data_out.h +++ b/deal.II/deal.II/include/numerics/data_out.h @@ -198,14 +198,65 @@ class DataOut_DoFData : public DataOutInterface * add_data_vector() for the * method used). */ - enum DataVectorType { - /// Data vector entries are associated to degrees of freedom + enum DataVectorType + { + /** + * Data vector entries are + * associated to degrees of freedom + */ type_dof_data, - /// Data vector entries are one per grid cell + + /** + * Data vector entries are one per + * grid cell + */ type_cell_data, - /// Find out automatically + + /** + * Find out automatically + */ type_automatic }; + + /** + * The members of this enum are used to + * describe the logical interpretation of + * what the various components of a + * vector-valued data set mean. For + * example, if one has a finite element + * for the Stokes equations in 2d, + * representing components (u,v,p), one + * would like to indicate that the first + * two, u and v, represent a logical + * vector so that later on when we + * generate graphical output we can hand + * them off to a visualization program + * that will automatically know to render + * them as a vector field, rather than as + * two separate and independent scalar + * fields. + * + * By passing a set of enums of the + * current kind to the + * DataOut_DoFData::add_data_vector + * functions, this can be achieved. + */ + enum DataComponentInterpretation + { + /** + * Indicates that a component of a + * data set corresponds to a scalar + * field independent of the others. + */ + component_is_scalar, + + /** + * Indicates that a component of a + * data set is part of a + * vector-valued quantity. + */ + component_is_part_of_vector + }; /** * Constructor @@ -531,6 +582,17 @@ class DataOut_DoFData : public DataOutInterface * Exception */ DeclException0 (ExcIncompatiblePatchLists); + + DeclException2 (ExcInvalidVectorDeclaration, + int, std::string, + << "When declaring that a number of components in a data\n" + << "set to be output logically form a vector instead of\n" + << "simply a set of scalar fields, you need to specify\n" + << "this for all relevant components. Furthermore,\n" + << "vectors must always consist of exactly \n" + << "components. However, the vector component at\n" + << "position " << arg1 << " with name <" << arg2 + << " does not satisfy these conditions."); protected: /** @@ -671,6 +733,17 @@ class DataOut_DoFData : public DataOutInterface */ const std::vector names; + /** + * A vector that for each of the + * n_output_variables variables of + * the current data set indicates + * whether they are scalar fields, + * parts of a vector-field, or any of + * the other supported kinds of data. + */ + const std::vector + data_component_interpretation; + /** * Pointer to a DataPostprocessing * object which shall be applied to @@ -862,15 +935,15 @@ class DataOut_DoFData : public DataOutInterface * classes. */ std::vector patches; - + /** * Function by which the base * class's functions get to know * what patches they shall write * to a file. */ - virtual const std::vector & - get_patches () const; + virtual + const std::vector & get_patches () const; /** * Virtual function through @@ -878,8 +951,18 @@ class DataOut_DoFData : public DataOutInterface * obtained by the output functions * of the base class. */ - virtual std::vector get_dataset_names () const; + virtual + std::vector get_dataset_names () const; + /** + * Overload of the respective + * DataOutBase::get_vector_data_ranges() + * function. + */ + virtual + std::vector > + get_vector_data_ranges () const; + /** * Make all template siblings * friends. Needed for the @@ -1179,7 +1262,10 @@ merge_patches (const DataOut_DoFData &source, // names Assert (get_dataset_names() == source.get_dataset_names(), ExcIncompatibleDatasetNames()); - // make sure patches are compatible + // make sure patches are compatible. we'll + // assume that if the first respective + // patches are ok that all the other ones + // are ok as well Assert (patches[0].n_subdivisions == source_patches[0].n_subdivisions, ExcIncompatiblePatchLists()); Assert (patches[0].data.n_rows() == source_patches[0].data.n_rows(), @@ -1187,6 +1273,28 @@ merge_patches (const DataOut_DoFData &source, Assert (patches[0].data.n_cols() == source_patches[0].data.n_cols(), ExcIncompatiblePatchLists()); + // check equality of the vector data + // specifications + Assert (get_vector_data_ranges().size() == + source.get_vector_data_ranges().size(), + ExcMessage ("Both sources need to declare the same components " + "as vectors.")); + for (unsigned int i=0; i() == + source.get_vector_data_ranges()[i].template get<0>(), + ExcMessage ("Both sources need to declare the same components " + "as vectors.")); + Assert (get_vector_data_ranges()[i].template get<1>() == + source.get_vector_data_ranges()[i].template get<1>(), + ExcMessage ("Both sources need to declare the same components " + "as vectors.")); + Assert (get_vector_data_ranges()[i].template get<2>() == + source.get_vector_data_ranges()[i].template get<2>(), + ExcMessage ("Both sources need to declare the same components " + "as vectors.")); + } + // merge patches. store old number // of elements, since we need to // adjust patch numbers, etc diff --git a/deal.II/deal.II/source/numerics/data_out.cc b/deal.II/deal.II/source/numerics/data_out.cc index 7d0f0a4e50..0d828aa9e7 100644 --- a/deal.II/deal.II/source/numerics/data_out.cc +++ b/deal.II/deal.II/source/numerics/data_out.cc @@ -41,12 +41,20 @@ DataEntryBase::DataEntryBase (const std::vector &names_in, const DataPostprocessor *data_postprocessor) : names(names_in), + data_component_interpretation (names.size(), + component_is_scalar), postprocessor(data_postprocessor), n_output_variables(names.size()) { +//TODO this function should check that the number of names we have here equals the number of components to be obtained from the postprocessor Assert(!data_postprocessor || data_postprocessor->n_output_variables()==names.size(), - ExcDimensionMismatch(data_postprocessor->n_output_variables(),names.size())); + ExcDimensionMismatch(data_postprocessor->n_output_variables(), + names.size())); + Assert (!data_postprocessor || + names.size() == data_component_interpretation.size(), + ExcDimensionMismatch(data_component_interpretation.size(), + names.size())); } @@ -436,13 +444,104 @@ get_dataset_names () const { Assert ((*d)->names.size() == 1, ExcInternalError()); names.push_back ((*d)->names[0]); - }; + } return names; } +template +std::vector > +DataOut_DoFData::get_vector_data_ranges () const +{ + std::vector > + ranges; + + // collect the ranges of dof + // and cell data + typedef + typename std::vector >::const_iterator + data_iterator; + + unsigned int output_component = 0; + for (data_iterator d=dof_data.begin(); + d!=dof_data.end(); ++d) + for (unsigned int i=0; i<(*d)->n_output_variables; + ++i, ++output_component) + // see what kind of data we have + // here. note that for the purpose of + // the current function all we care + // about is vector data + if ((*d)->data_component_interpretation[i] == + component_is_part_of_vector) + { + // ensure that there is a + // continuous number of next + // space_dim components that all + // deal with vectors + Assert (i+patch_space_dim <= + (*d)->n_output_variables, + ExcInvalidVectorDeclaration (i, + (*d)->names[i])); + for (unsigned int dd=1; dddata_component_interpretation[i+dd] + == + component_is_part_of_vector, + ExcInvalidVectorDeclaration (i, + (*d)->names[i])); + + // all seems alright, so figure out + // whether there is a common name + // to these components. if not, + // leave the name empty and let the + // output format writer decide what + // to do here + std::string name = (*d)->names[i]; + for (unsigned int dd=1; ddnames[i+dd]) + { + name = ""; + break; + } + + // finally add a corresponding + // range + boost::tuple + range (output_component, + output_component+patch_space_dim-1, + name); + + ranges.push_back (range); + + // increase the 'component' counter + // by the appropriate amount + output_component += patch_space_dim-1; + } + + // note that we do not have to traverse the + // list of cell data here because cell data + // is one value per (logical) cell and + // therefore cannot be a vector + + // as a final check, the 'component' + // counter should be at the total number of + // components added up now +#ifdef DEBUG + unsigned int n_output_components = 0; + for (data_iterator d=dof_data.begin(); + d!=dof_data.end(); ++d) + n_output_components = (*d)->n_output_variables; + Assert (output_component == n_output_components, + ExcInternalError()); +#endif + + return ranges; +} + + + template const std::vector< dealii::DataOutBase::Patch > &