OGS
AddProcessDataToMesh.cpp
Go to the documentation of this file.
1
12
13#include "InfoLib/GitInfo.h"
18#ifdef USE_PETSC
20#endif
22
25static void addOgsVersion(MeshLib::Mesh& mesh)
26{
27 auto& ogs_version_field = *MeshLib::getOrCreateMeshProperty<char>(
30
31 ogs_version_field.assign(GitInfoLib::GitInfo::ogs_version.begin(),
33}
34
36 double const t,
37 std::vector<GlobalVector*> const& x,
38 std::vector<NumLib::LocalToGlobalIndexMap const*> const& dof_tables,
40 std::string const& output_name,
41 MeshLib::Mesh& mesh)
42{
43 DBUG(" secondary variable {:s}", output_name);
44
45 auto& nodal_values_mesh = *MeshLib::getOrCreateMeshProperty<double>(
46 mesh, output_name, MeshLib::MeshItemType::Node,
48 if (nodal_values_mesh.size() !=
50 {
52 "Nodal property `{:s}' does not have the right number of "
53 "components. Expected: {:d}, actual: {:d}",
54 output_name,
56 nodal_values_mesh.size());
57 }
58
59 std::unique_ptr<GlobalVector> result_cache;
60 auto const& nodal_values =
61 var.fcts.eval_field(t, x, dof_tables, result_cache);
62
63#ifdef USE_PETSC
64 std::size_t const global_vector_size =
65 nodal_values.getLocalSize() + nodal_values.getGhostSize();
66#else
67 std::size_t const global_vector_size = nodal_values.size();
68#endif
69 if (nodal_values_mesh.size() != global_vector_size)
70 {
72 "Secondary variable `{:s}' did not evaluate to the right number of "
73 "components. Expected: {:d}, actual: {:d}.",
74 var.name, nodal_values_mesh.size(), global_vector_size);
75 }
76
77 // Copy result
78 nodal_values.copyValues(nodal_values_mesh);
79}
80
82 double const t,
83 std::vector<GlobalVector*> const& x,
84 std::vector<NumLib::LocalToGlobalIndexMap const*> const& dof_table,
86 std::string const& output_name,
87 MeshLib::Mesh& mesh)
88{
89 if (!var.fcts.eval_residuals)
90 {
91 return;
92 }
93
94 DBUG(" secondary variable {:s} residual", output_name);
95 auto const& property_name_res = output_name + "_residual";
96
97 auto& residuals_mesh = *MeshLib::getOrCreateMeshProperty<double>(
98 mesh, property_name_res, MeshLib::MeshItemType::Cell,
100 if (residuals_mesh.size() !=
102 {
103 OGS_FATAL(
104 "Cell property `{:s}' does not have the right number of "
105 "components. Expected: {:d}, actual: {:d}",
106 property_name_res,
108 residuals_mesh.size());
109 }
110
111 std::unique_ptr<GlobalVector> result_cache;
112 auto const& residuals =
113 var.fcts.eval_residuals(t, x, dof_table, result_cache);
114#ifdef USE_PETSC
115 std::size_t const global_vector_size =
116 residuals.getLocalSize() + residuals.getGhostSize();
117#else
118 std::size_t const global_vector_size = residuals.size();
119#endif
120 if (residuals_mesh.size() != global_vector_size)
121 {
122 OGS_FATAL(
123 "The residual of secondary variable `{:s}' did not evaluate to the "
124 "right number of components. Expected: {:d}, actual: {:d}.",
125 var.name, residuals_mesh.size(), global_vector_size);
126 }
127
128 // Copy result
129 residuals.copyValues(residuals_mesh);
130}
131
132static std::vector<double> copySolutionVector(GlobalVector const& x)
133{
134 std::vector<double> x_copy;
135 x.copyValues(x_copy);
136 return x_copy;
137}
138
140 [[maybe_unused]] MeshLib::Mesh const& mesh,
141 [[maybe_unused]] NumLib::LocalToGlobalIndexMap const& dof_table,
142 [[maybe_unused]] NumLib::LocalToGlobalIndexMap const& bulk_mesh_dof_table)
143{
144#ifdef USE_PETSC
145
146 if (&bulk_mesh_dof_table != &dof_table)
147 {
148 auto const bulk_id_string =
150 if (!mesh.getProperties().existsPropertyVector<std::size_t>(
151 bulk_id_string))
152 {
153 OGS_FATAL(
154 "The required bulk node ids map does not exist in "
155 "the boundary mesh '{:s}' or has the wrong data "
156 "type (should be equivalent to C++ data type "
157 "std::size_t which is an unsigned integer of size "
158 "{:d} or UInt64 in vtk terminology).",
159 mesh.getName(), sizeof(std::size_t));
160 }
161 return mesh.getProperties().getPropertyVector<std::size_t>(
162 bulk_id_string);
163 }
164#endif
165
166 return nullptr;
167}
168
170 std::size_t const mesh_id, std::size_t const node_id,
171 [[maybe_unused]] bool const is_ghost_node, int const global_component_id,
172 GlobalVector const& x, NumLib::LocalToGlobalIndexMap const& dof_table,
173 [[maybe_unused]] NumLib::LocalToGlobalIndexMap const& bulk_mesh_dof_table,
174 [[maybe_unused]] MeshLib::PropertyVector<std::size_t> const* const
175 bulk_node_id_map)
176{
177#ifdef USE_PETSC
178 if (is_ghost_node && &bulk_mesh_dof_table != &dof_table)
179 {
180 auto const bulk_node_id = (*bulk_node_id_map)[node_id];
181 std::size_t const bulk_mesh_id = 0;
182
183 MeshLib::Location const loc(bulk_mesh_id, MeshLib::MeshItemType::Node,
184 bulk_node_id);
185
186 // early return!
187 return bulk_mesh_dof_table.getLocalIndex(
188 loc, global_component_id, x.getRangeBegin(), x.getRangeEnd());
189 }
190#endif
191
192 MeshLib::Location const loc(mesh_id, MeshLib::MeshItemType::Node, node_id);
193
194 return dof_table.getLocalIndex(loc, global_component_id, x.getRangeBegin(),
195 x.getRangeEnd());
196}
197
198static bool isGhostNode([[maybe_unused]] MeshLib::Mesh const& mesh,
199 [[maybe_unused]] std::size_t const node_id)
200{
201#ifndef USE_PETSC
202 return false;
203#else
204 return static_cast<MeshLib::NodePartitionedMesh const&>(mesh).isGhostNode(
205 node_id);
206#endif
207}
208
238static std::set<std::string> addPrimaryVariablesToMesh(
239 MeshLib::Mesh& mesh,
240 GlobalVector const& x,
241 std::vector<std::reference_wrapper<ProcessLib::ProcessVariable>> const&
242 process_variables,
243 std::set<std::string> const& output_variables,
244 NumLib::LocalToGlobalIndexMap const& dof_table,
245 NumLib::LocalToGlobalIndexMap const& bulk_mesh_dof_table)
246{
247 if (dof_table.getNumberOfVariables() !=
248 bulk_mesh_dof_table.getNumberOfVariables() ||
249 dof_table.getNumberOfGlobalComponents() !=
250 bulk_mesh_dof_table.getNumberOfGlobalComponents())
251 {
252 OGS_FATAL(
253 "The d.o.f. table for the passed mesh must have the same number of "
254 "variables and global components as the d.o.f. table for the full "
255 "simulation domain. But the values differ: {} != {} (variables) or "
256 "{} != {} (global components).",
257 dof_table.getNumberOfVariables(),
258 bulk_mesh_dof_table.getNumberOfVariables(),
259 dof_table.getNumberOfGlobalComponents(),
260 bulk_mesh_dof_table.getNumberOfGlobalComponents());
261 }
262
263 auto const number_of_dof_variables = dof_table.getNumberOfVariables();
264
265 if (number_of_dof_variables != static_cast<int>(process_variables.size()))
266 {
267 OGS_FATAL(
268 "The number of variables in the d.o.f. table differs from the "
269 "number of primary variables of the process {} != {}.",
270 number_of_dof_variables, process_variables.size());
271 }
272
273 auto const x_copy = copySolutionVector(x);
274 std::set<std::string> names_of_already_output_variables;
275
276 int global_component_offset_next = 0;
277
278 auto const* const bulk_node_id_map = getBulkNodeIdMapForPetscIfNecessary(
279 mesh, dof_table, bulk_mesh_dof_table);
280
281 for (int variable_id = 0; variable_id < number_of_dof_variables;
282 ++variable_id)
283 {
284 auto const& pv = process_variables[variable_id].get();
285 auto const n_components = pv.getNumberOfGlobalComponents();
286
287 // increase global component offset even if we do not add anything in
288 // this iteration
289 int global_component_offset = global_component_offset_next;
290 global_component_offset_next += n_components;
291
292 if (!output_variables.empty() &&
293 !output_variables.contains(pv.getName()))
294 {
295 continue;
296 }
297
298 names_of_already_output_variables.insert(pv.getName());
299
300 DBUG(" process variable {:s}", pv.getName());
301
302 auto& output_data = *MeshLib::getOrCreateMeshProperty<double>(
303 mesh, pv.getName(), MeshLib::MeshItemType::Node, n_components);
304
305 // mesh subsets are the same for all components
306 int const dummy_component_id = 0;
307 auto const& mesh_subset =
308 dof_table.getMeshSubset(variable_id, dummy_component_id);
309 auto const mesh_id = mesh_subset.getMeshID();
310
311 for (auto const* node : mesh_subset.getNodes())
312 {
313 auto const node_id = node->getID();
314 auto const is_ghost_node = isGhostNode(mesh, node_id);
315
316 for (int component_id = 0; component_id < n_components;
317 ++component_id)
318 {
319 auto const global_component_id =
320 global_component_offset + component_id;
321
322 auto const in_index = getIndexForComponentInSolutionVector(
323 mesh_id, node_id, is_ghost_node, global_component_id, x,
324 dof_table, bulk_mesh_dof_table, bulk_node_id_map);
325
326 // per node ordering of components
327 auto const out_index = node_id * n_components + component_id;
328
329 // request for index of linear quantities at higher order nodes
330 // results in returning NumLib::MeshComponentMap::nop
331 if (in_index == NumLib::MeshComponentMap::nop)
332 {
333 output_data[out_index] = 0;
334 continue;
335 }
336
337 output_data[out_index] = x_copy[in_index];
338 }
339 }
340 }
341
342 return names_of_already_output_variables;
343}
344
346 ProcessLib::SecondaryVariableCollection const& secondary_variables,
347 std::set<std::string>& names_of_already_output_variables, const double t,
348 std::vector<GlobalVector*> const& xs, MeshLib::Mesh& mesh,
349 std::vector<NumLib::LocalToGlobalIndexMap const*> const& dof_tables,
350 bool const output_residuals)
351{
352 for (auto const& external_variable_name : secondary_variables)
353 {
354 auto const& name = external_variable_name.first;
355 if (!names_of_already_output_variables.insert(name).second)
356 {
357 // no insertion took place, output already done
358 continue;
359 }
360
361 addSecondaryVariableNodes(t, xs, dof_tables,
362 secondary_variables.get(name), name, mesh);
363
364 if (output_residuals)
365 {
367 t, xs, dof_tables, secondary_variables.get(name), name, mesh);
368 }
369 }
370}
371
372namespace ProcessLib
373{
374void addProcessDataToMesh(const double t,
375 std::vector<GlobalVector*> const& xs,
376 int const process_id,
377 ProcessOutputData const& process_output_data,
378 bool const output_secondary_variables,
379 OutputDataSpecification const& process_output)
380{
381 DBUG("Process output data.");
382
383 auto const& pod = process_output_data;
384 auto const& process_variables = pod.getProcessVariables(process_id);
385 auto const& secondary_variables = pod.getSecondaryVariables();
386 auto const* const integration_point_writers =
387 pod.getIntegrationPointWriters();
388 auto const& bulk_mesh_dof_table = pod.getBulkMeshDofTable(process_id);
389 auto const& output_mesh_dof_table = pod.getOutputMeshDofTable(process_id);
390 auto& output_mesh = pod.getOutputMesh();
391
392 auto const& output_variables = process_output.output_variables;
393
394 addOgsVersion(output_mesh);
395
396 auto names_of_already_output_variables = addPrimaryVariablesToMesh(
397 output_mesh, *xs[process_id], process_variables, output_variables,
398 output_mesh_dof_table, bulk_mesh_dof_table);
399
400 if (output_secondary_variables)
401 {
402 auto const& output_mesh_dof_tables =
403 pod.getOutputMeshDofTablesOfAllProcesses();
404
405 addSecondaryVariablesToMesh(secondary_variables,
406 names_of_already_output_variables, t, xs,
407 output_mesh, output_mesh_dof_tables,
408 process_output.output_residuals);
409 }
410
411 if (integration_point_writers)
412 {
413 addIntegrationPointDataToMesh(output_mesh, *integration_point_writers);
414 }
415}
416} // namespace ProcessLib
static std::vector< double > copySolutionVector(GlobalVector const &x)
static void addSecondaryVariableResiduals(double const t, std::vector< GlobalVector * > const &x, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_table, ProcessLib::SecondaryVariable const &var, std::string const &output_name, MeshLib::Mesh &mesh)
static GlobalIndexType getIndexForComponentInSolutionVector(std::size_t const mesh_id, std::size_t const node_id, bool const is_ghost_node, int const global_component_id, GlobalVector const &x, NumLib::LocalToGlobalIndexMap const &dof_table, NumLib::LocalToGlobalIndexMap const &bulk_mesh_dof_table, MeshLib::PropertyVector< std::size_t > const *const bulk_node_id_map)
MeshLib::PropertyVector< std::size_t > const * getBulkNodeIdMapForPetscIfNecessary(MeshLib::Mesh const &mesh, NumLib::LocalToGlobalIndexMap const &dof_table, NumLib::LocalToGlobalIndexMap const &bulk_mesh_dof_table)
static std::set< std::string > addPrimaryVariablesToMesh(MeshLib::Mesh &mesh, GlobalVector const &x, std::vector< std::reference_wrapper< ProcessLib::ProcessVariable > > const &process_variables, std::set< std::string > const &output_variables, NumLib::LocalToGlobalIndexMap const &dof_table, NumLib::LocalToGlobalIndexMap const &bulk_mesh_dof_table)
static void addSecondaryVariableNodes(double const t, std::vector< GlobalVector * > const &x, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_tables, ProcessLib::SecondaryVariable const &var, std::string const &output_name, MeshLib::Mesh &mesh)
static void addSecondaryVariablesToMesh(ProcessLib::SecondaryVariableCollection const &secondary_variables, std::set< std::string > &names_of_already_output_variables, const double t, std::vector< GlobalVector * > const &xs, MeshLib::Mesh &mesh, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_tables, bool const output_residuals)
static bool isGhostNode(MeshLib::Mesh const &mesh, std::size_t const node_id)
static void addOgsVersion(MeshLib::Mesh &mesh)
#define OGS_FATAL(...)
Definition Error.h:26
Git information.
GlobalMatrix::IndexType GlobalIndexType
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:30
Definition of mesh class for partitioned mesh (by node) for parallel computing within the framework o...
Global vector based on Eigen vector.
Definition EigenVector.h:25
IndexType getRangeEnd() const
return an end index of the active data range
Definition EigenVector.h:48
void copyValues(std::vector< double > &u) const
static constexpr IndexType getRangeBegin()
return a start index of the active data range
Definition EigenVector.h:45
std::size_t getMeshID() const
return this mesh ID
Definition MeshSubset.h:76
const std::string getName() const
Get name of the mesh.
Definition Mesh.h:103
std::size_t getNumberOfNodes() const
Get the number of nodes.
Definition Mesh.h:100
std::size_t getNumberOfElements() const
Get the number of elements.
Definition Mesh.h:97
MeshLib::MeshSubset const & getMeshSubset(int const variable_id, int const component_id) const
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
static constexpr NUMLIB_EXPORT GlobalIndexType const nop
Holds all data of a process that are needed for output.
std::vector< std::reference_wrapper< ProcessVariable > > const & getProcessVariables(int const process_id) const
Handles configuration of several secondary variables from the project file.
SecondaryVariable const & get(std::string const &external_name) const
Returns the secondary variable with the given external name.
const std::string OGS_VERSION
Definition GitInfo.cpp:20
GITINFOLIB_EXPORT const std::string ogs_version
constexpr std::string_view getBulkIDString(MeshItemType mesh_item_type)
Definition Properties.h:188
void addProcessDataToMesh(const double t, std::vector< GlobalVector * > const &xs, int const process_id, ProcessOutputData const &process_output_data, bool const output_secondary_variables, OutputDataSpecification const &process_output)
Holds information about which variables to write to output files.
bool output_residuals
Tells if also to output extrapolation residuals.
std::set< std::string > output_variables
All variables that shall be output.
Function const eval_field
Computes the value of the field at every node of the underlying mesh.
const unsigned num_components
Number of components of the variable.
Stores information about a specific secondary variable.
SecondaryVariableFunctions fcts
Functions used for computing the secondary variable.
std::string const name
Name of the variable; used, e.g., for output.