OGS 6.2.1-97-g73d1aeda3
ProcessOutput.cpp
Go to the documentation of this file.
1 
10 #include "ProcessOutput.h"
11 
12 #include "InfoLib/GitInfo.h"
13 #include "MathLib/LinAlg/LinAlg.h"
16 
17 #include "IntegrationPointWriter.h"
18 
19 
22 static void addOgsVersion(MeshLib::Mesh& mesh)
23 {
24  auto& ogs_version_field = *MeshLib::getOrCreateMeshProperty<char>(
25  mesh, "OGS_VERSION", MeshLib::MeshItemType::IntegrationPoint, 1);
26 
27  ogs_version_field.assign(GitInfoLib::GitInfo::ogs_version.begin(),
29 }
30 
32  double const t,
33  GlobalVector const& x,
34  NumLib::LocalToGlobalIndexMap const& dof_table,
36  std::string const& output_name,
37  MeshLib::Mesh& mesh)
38 {
39  DBUG(" secondary variable %s", output_name.c_str());
40 
41  auto& nodal_values_mesh = *MeshLib::getOrCreateMeshProperty<double>(
42  mesh, output_name, MeshLib::MeshItemType::Node,
43  var.fcts.num_components);
44  if (nodal_values_mesh.size() !=
45  mesh.getNumberOfNodes() * var.fcts.num_components)
46  {
47  OGS_FATAL(
48  "Nodal property `%s' does not have the right number of "
49  "components. Expected: %d, actual: %d",
50  output_name.c_str(),
51  mesh.getNumberOfNodes() * var.fcts.num_components,
52  nodal_values_mesh.size());
53  }
54 
55  std::unique_ptr<GlobalVector> result_cache;
56  auto const& nodal_values =
57  var.fcts.eval_field(t, x, dof_table, result_cache);
58 #ifdef USE_PETSC
59  std::size_t const global_vector_size =
60  nodal_values.getLocalSize() + nodal_values.getGhostSize();
61 #else
62  std::size_t const global_vector_size = nodal_values.size();
63 #endif
64  if (nodal_values_mesh.size() != global_vector_size)
65  {
66  OGS_FATAL(
67  "Secondary variable `%s' did not evaluate to the right "
68  "number of components. Expected: %d, actual: %d.",
69  var.name.c_str(), nodal_values_mesh.size(), global_vector_size);
70  }
71 
72  // Copy result
73  nodal_values.copyValues(nodal_values_mesh);
74 }
75 
77  double const t,
78  GlobalVector const& x,
79  NumLib::LocalToGlobalIndexMap const& dof_table,
81  std::string const& output_name,
82  MeshLib::Mesh& mesh)
83 {
84  if (!var.fcts.eval_residuals)
85  {
86  return;
87  }
88 
89  DBUG(" secondary variable %s residual", output_name.c_str());
90  auto const& property_name_res = output_name + "_residual";
91 
92  auto& residuals_mesh = *MeshLib::getOrCreateMeshProperty<double>(
93  mesh, property_name_res, MeshLib::MeshItemType::Cell,
94  var.fcts.num_components);
95  if (residuals_mesh.size() !=
96  mesh.getNumberOfElements() * var.fcts.num_components)
97  {
98  OGS_FATAL(
99  "Cell property `%s' does not have the right number of components. "
100  "Expected: %d, actual: %d",
101  property_name_res.c_str(),
102  mesh.getNumberOfElements() * var.fcts.num_components,
103  residuals_mesh.size());
104  }
105 
106  std::unique_ptr<GlobalVector> result_cache;
107  auto const& residuals =
108  var.fcts.eval_residuals(t, x, dof_table, result_cache);
109 #ifdef USE_PETSC
110  std::size_t const global_vector_size =
111  residuals.getLocalSize() + residuals.getGhostSize();
112 #else
113  std::size_t const global_vector_size = residuals.size();
114 #endif
115  if (residuals_mesh.size() != global_vector_size)
116  {
117  OGS_FATAL(
118  "The residual of secondary variable `%s' did not evaluate to the "
119  "right number of components. Expected: %d, actual: %d.",
120  var.name.c_str(), residuals_mesh.size(), global_vector_size);
121  }
122 
123  // Copy result
124  residuals.copyValues(residuals_mesh);
125 }
126 
127 namespace ProcessLib
128 {
130  const double t,
131  GlobalVector const& x,
132  MeshLib::Mesh& mesh,
133  NumLib::LocalToGlobalIndexMap const& dof_table,
134  std::vector<std::reference_wrapper<ProcessVariable>> const&
135  process_variables,
136  SecondaryVariableCollection const& secondary_variables,
137  bool const output_secondary_variable,
138  std::vector<std::unique_ptr<IntegrationPointWriter>> const&
139  integration_point_writer,
140  ProcessOutput const& process_output)
141 {
142  DBUG("Process output data.");
143 
144  addOgsVersion(mesh);
145 
146  // Copy result
147 #ifdef USE_PETSC
148  // TODO It is also possible directly to copy the data for single process
149  // variable to a mesh property. It needs a vector of global indices and
150  // some PETSc magic to do so.
151  std::vector<double> x_copy(x.getLocalSize() + x.getGhostSize());
152 #else
153  std::vector<double> x_copy(x.size());
154 #endif
155  x.copyValues(x_copy);
156 
157  auto const& output_variables = process_output.output_variables;
158  std::set<std::string> already_output;
159 
160  int global_component_offset = 0;
161  int global_component_offset_next = 0;
162 
163  const auto number_of_dof_variables = dof_table.getNumberOfVariables();
164  // primary variables
165  for (int variable_id = 0;
166  variable_id < static_cast<int>(process_variables.size());
167  ++variable_id)
168  {
169  ProcessVariable& pv = process_variables[variable_id];
170  int const n_components = pv.getNumberOfComponents();
171  // If (number_of_dof_variables==1), the case is either the staggered
172  // scheme being applied or a single PDE being solved.
173  const int sub_meshset_id =
174  (number_of_dof_variables == 1) ? 0 : variable_id;
175 
176  if (number_of_dof_variables > 1)
177  {
178  global_component_offset = global_component_offset_next;
179  global_component_offset_next += n_components;
180  }
181 
182  if (output_variables.find(pv.getName()) == output_variables.cend())
183  {
184  continue;
185  }
186 
187  already_output.insert(pv.getName());
188 
189  DBUG(" process variable %s", pv.getName().c_str());
190 
191  auto const num_comp = pv.getNumberOfComponents();
192  auto& output_data = *MeshLib::getOrCreateMeshProperty<double>(
193  mesh, pv.getName(), MeshLib::MeshItemType::Node, num_comp);
194 
195 
196  for (int component_id = 0; component_id < num_comp; ++component_id)
197  {
198  auto const& mesh_subset =
199  dof_table.getMeshSubset(sub_meshset_id, component_id);
200  auto const mesh_id = mesh_subset.getMeshID();
201  for (auto const* node : mesh_subset.getNodes())
202  {
204  node->getID());
205 
206  auto const global_component_id =
207  global_component_offset + component_id;
208  auto const index = dof_table.getLocalIndex(
209  l, global_component_id, x.getRangeBegin(), x.getRangeEnd());
210 
211  output_data[node->getID() * n_components + component_id] =
212  x_copy[index];
213  }
214  }
215  }
216 
217  if (output_secondary_variable)
218  {
219  for (auto const& external_variable_name : secondary_variables)
220  {
221  auto const& name = external_variable_name.first;
222  if (!already_output.insert(name).second)
223  {
224  // no insertion took place, output already done
225  continue;
226  }
227 
229  t, x, dof_table, secondary_variables.get(name), name, mesh);
230 
231  if (process_output.output_residuals)
232  {
234  t, x, dof_table, secondary_variables.get(name), name, mesh);
235  }
236  }
237  }
238 
239  addIntegrationPointWriter(mesh, integration_point_writer);
240 }
241 
242 void makeOutput(std::string const& file_name, MeshLib::Mesh const& mesh,
243  bool const compress_output, int const data_mode)
244 {
245  // Write output file
246  DBUG("Writing output to '%s'.", file_name.c_str());
247  MeshLib::IO::VtuInterface vtu_interface(&mesh, data_mode, compress_output);
248  vtu_interface.writeToFile(file_name);
249 }
250 
251 } // namespace ProcessLib
const unsigned num_components
Number of components of the variable.
void addIntegrationPointWriter(MeshLib::Mesh &mesh, std::vector< std::unique_ptr< IntegrationPointWriter >> const &integration_point_writer)
SecondaryVariableFunctions fcts
Functions used for computing the secondary variable.
bool const output_residuals
Tells if also to output extrapolation residuals.
Definition: ProcessOutput.h:26
std::set< std::string > output_variables
All variables that shall be output.
Definition: ProcessOutput.h:23
std::size_t getMeshID() const
return this mesh ID
Definition: MeshSubset.h:71
Implementation of the VtuInterface class.
Function const eval_field
Computes the value of the field at every node of the underlying mesh.
Stores information about a specific secondary variable.
GITINFOLIB_EXPORT const std::string ogs_version
Reads and writes VtkXMLUnstructuredGrid-files (vtu) to and from OGS data structures. This class is currently not inherited from Writer because VTK will implement writing to a string from 6.2 onwards.
Definition: VtuInterface.h:36
void makeOutput(std::string const &file_name, MeshLib::Mesh const &mesh, bool const compress_output, int const data_mode)
std::string const name
Name of the variable; used, e.g., for output.
void processOutputData(const double t, GlobalVector const &x, MeshLib::Mesh &mesh, NumLib::LocalToGlobalIndexMap const &dof_table, std::vector< std::reference_wrapper< ProcessVariable >> const &process_variables, SecondaryVariableCollection const &secondary_variables, bool const output_secondary_variable, std::vector< std::unique_ptr< IntegrationPointWriter >> const &integration_point_writer, ProcessOutput const &process_output)
Prepare the output data, i.e. add the solution to vtu data structure.
static void addSecondaryVariableResiduals(double const t, GlobalVector const &x, NumLib::LocalToGlobalIndexMap const &dof_table, ProcessLib::SecondaryVariable const &var, std::string const &output_name, MeshLib::Mesh &mesh)
std::string const & getName() const
int getNumberOfComponents() const
Returns the number of components of the process variable.
static void addSecondaryVariableNodes(double const t, GlobalVector const &x, NumLib::LocalToGlobalIndexMap const &dof_table, ProcessLib::SecondaryVariable const &var, std::string const &output_name, MeshLib::Mesh &mesh)
MeshLib::MeshSubset const & getMeshSubset(int const variable_id, int const component_id) const
Handles configuration of several secondary variables from the project file.
#define OGS_FATAL(fmt,...)
Definition: Error.h:63
static void addOgsVersion(MeshLib::Mesh &mesh)
GlobalIndexType getLocalIndex(MeshLib::Location const &l, std::size_t const comp_id, std::size_t const range_begin, std::size_t const range_end) const
Holds information about which variables to write to output files.
Definition: ProcessOutput.h:20