From 03de60897870d56e2308cdf812bf05520ecb5e91 Mon Sep 17 00:00:00 2001 From: Wolfgang Bangerth Date: Wed, 4 Sep 2019 16:27:40 -0600 Subject: [PATCH] Account for the fact that postprocessors always return real-valued data. --- .../numerics/data_out_dof_data.templates.h | 33 ++++++++++++------- source/numerics/data_out.cc | 32 +++++++++++++++--- 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/include/deal.II/numerics/data_out_dof_data.templates.h b/include/deal.II/numerics/data_out_dof_data.templates.h index f0d1459e45..3675e60d46 100644 --- a/include/deal.II/numerics/data_out_dof_data.templates.h +++ b/include/deal.II/numerics/data_out_dof_data.templates.h @@ -1291,24 +1291,31 @@ DataOut_DoFData::get_dataset_names() const { std::vector names; - // collect the names of dof and cell data - using data_iterator = typename std::vector>>:: - const_iterator; - for (data_iterator d = dof_data.begin(); d != dof_data.end(); ++d) + // Loop over all DoF-data datasets and push the names. If the + // vector underlying a data set is complex-valued, then + // expand it into its real and imaginary part. Note, however, + // that what comes back from a postprocess is *always* + // real-valued, regardless of what goes in, so we don't + // have this to do this name expansion for data sets that + // have a postprocessor. + for (auto d = dof_data.begin(); d != dof_data.end(); ++d) for (unsigned int i = 0; i < (*d)->names.size(); ++i) - if ((*d)->is_complex_valued() == false) + if ((*d)->is_complex_valued() == false || + ((*d)->postprocessor != nullptr)) names.push_back((*d)->names[i]); else { names.push_back((*d)->names[i] + "_re"); names.push_back((*d)->names[i] + "_im"); } - for (data_iterator d = cell_data.begin(); d != cell_data.end(); ++d) + + // Do the same as above for cell-type data + for (auto d = cell_data.begin(); d != cell_data.end(); ++d) { Assert((*d)->names.size() == 1, ExcInternalError()); - if ((*d)->is_complex_valued() == false) + if (((*d)->is_complex_valued() == false) || + ((*d)->postprocessor != nullptr)) names.push_back((*d)->names[0]); else { @@ -1352,10 +1359,14 @@ DataOut_DoFData:: { case DataComponentInterpretation::component_is_scalar: { - // just move one component forward by one, or two if the component - // happens to be complex-valued + // Just move one component forward by one (or two if the component + // happens to be complex-valued and we don't use a postprocessor + // -- postprocessors always return real-valued things) ++i; - output_component += ((*d)->is_complex_valued() ? 2 : 1); + output_component += + ((*d)->is_complex_valued() && ((*d)->postprocessor == nullptr) ? + 2 : + 1); break; } diff --git a/source/numerics/data_out.cc b/source/numerics/data_out.cc index 7dd2dbe345..669c669851 100644 --- a/source/numerics/data_out.cc +++ b/source/numerics/data_out.cc @@ -277,6 +277,9 @@ DataOut::build_one_patch( scratch_data.postprocessed_values[dataset]); } + // Now we need to copy the result of the postprocessor to + // the Patch object where it can then be further processes + // by the functions in DataOutBase for (unsigned int q = 0; q < n_q_points; ++q) for (unsigned int component = 0; component < this->dof_data[dataset]->n_output_variables; @@ -351,9 +354,17 @@ DataOut::build_one_patch( } } - // increment the counter for the actual data record + // Increment the counter for the actual data record. We need to + // move it forward a number of positions equal to the number + // of components of this data set; if the input consisted + // of a complex-valued quantity and if it is not further + // processed by a postprocessor, then we need two output + // slots for each input variable. offset += this->dof_data[dataset]->n_output_variables * - (this->dof_data[dataset]->is_complex_valued() ? 2 : 1); + (this->dof_data[dataset]->is_complex_valued() && + (this->dof_data[dataset]->postprocessor == nullptr) ? + 2 : + 1); } // then do the cell data. only compute the number of a cell if needed; @@ -565,13 +576,24 @@ DataOut::build_patches( this->patches.clear(); this->patches.resize(all_cells.size()); - // now create a default object for the WorkStream object to work with + // Now create a default object for the WorkStream object to work with. The + // first step is to count how many output data sets there will be. This is, + // in principle, just the number of components of each data set, but we + // need to allocate two entries per component if there are + // complex-valued input data (unless we use a postprocessor on this + // output -- all postprocessor outputs are real-valued) unsigned int n_datasets = 0; for (unsigned int i = 0; i < this->cell_data.size(); ++i) - n_datasets += (this->cell_data[i]->is_complex_valued() ? 2 : 1); + n_datasets += (this->cell_data[i]->is_complex_valued() && + (this->cell_data[i]->postprocessor == nullptr) ? + 2 : + 1); for (unsigned int i = 0; i < this->dof_data.size(); ++i) n_datasets += (this->dof_data[i]->n_output_variables * - (this->dof_data[i]->is_complex_valued() ? 2 : 1)); + (this->dof_data[i]->is_complex_valued() && + (this->dof_data[i]->postprocessor == nullptr) ? + 2 : + 1)); std::vector n_postprocessor_outputs(this->dof_data.size()); for (unsigned int dataset = 0; dataset < this->dof_data.size(); ++dataset) -- 2.39.5