Line data Source code
1 : // The libMesh Finite Element Library.
2 : // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 :
4 : // This library is free software; you can redistribute it and/or
5 : // modify it under the terms of the GNU Lesser General Public
6 : // License as published by the Free Software Foundation; either
7 : // version 2.1 of the License, or (at your option) any later version.
8 :
9 : // This library is distributed in the hope that it will be useful,
10 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : // Lesser General Public License for more details.
13 :
14 : // You should have received a copy of the GNU Lesser General Public
15 : // License along with this library; if not, write to the Free Software
16 : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 :
18 :
19 : // Local includes
20 : #include "libmesh/distributed_mesh.h"
21 : #include "libmesh/equation_systems.h"
22 : #include "libmesh/libmesh_logging.h"
23 : #include "libmesh/mesh_output.h"
24 : #include "libmesh/unstructured_mesh.h"
25 : #include "libmesh/numeric_vector.h"
26 :
27 : namespace libMesh
28 : {
29 :
30 : template <class MT>
31 79822 : void MeshOutput<MT>::write_equation_systems (const std::string & fname,
32 : const EquationSystems & es,
33 : const std::set<std::string> * system_names)
34 : {
35 4940 : LOG_SCOPE("write_equation_systems()", "MeshOutput");
36 :
37 : // We may need to gather and/or renumber a DistributedMesh to output
38 : // it, making that const qualifier in our constructor a dirty lie
39 79822 : MT & my_mesh = const_cast<MT &>(*_obj);
40 :
41 : // If we're asked to write data that's associated with a different
42 : // mesh, output files full of garbage are the result.
43 2470 : libmesh_assert_equal_to(&es.get_mesh(), _obj);
44 :
45 : // A non-parallel format, non-renumbered mesh may not have a contiguous
46 : // numbering, and that needs to be fixed before we can build a solution vector.
47 158936 : if (!_is_parallel_format &&
48 155778 : (my_mesh.max_elem_id() != my_mesh.n_elem() ||
49 79114 : my_mesh.max_node_id() != my_mesh.n_nodes()))
50 : {
51 : // If we were allowed to renumber then we should have already
52 : // been properly renumbered...
53 0 : libmesh_assert(!my_mesh.allow_renumbering());
54 :
55 0 : libmesh_do_once(libMesh::out <<
56 : "Warning: This MeshOutput subclass only supports meshes which are contiguously renumbered!"
57 : << std::endl;);
58 :
59 0 : my_mesh.allow_renumbering(true);
60 :
61 0 : my_mesh.renumber_nodes_and_elements();
62 :
63 : // Not sure what good going back to false will do here, the
64 : // renumbering horses have already left the barn...
65 0 : my_mesh.allow_renumbering(false);
66 : }
67 :
68 79822 : if (!_is_parallel_format)
69 : {
70 84014 : MeshSerializer serialize(const_cast<MT &>(*_obj), !_is_parallel_format, _serial_only_needed_on_proc_0);
71 :
72 : // Build the list of variable names that will be written.
73 7350 : std::vector<std::string> names;
74 79114 : es.build_variable_names (names, nullptr, system_names);
75 :
76 : // Build the nodal solution values & get the variable
77 : // names from the EquationSystems object
78 4900 : std::vector<Number> soln;
79 79114 : es.build_solution_vector (soln, system_names,
80 74214 : this->get_add_sides());
81 :
82 79114 : this->write_nodal_data (fname, soln, names);
83 74214 : }
84 : else // _is_parallel_format
85 708 : this->write_nodal_data (fname, es, system_names);
86 79822 : }
87 :
88 : template <class MT>
89 1207 : void MeshOutput<MT>::write_discontinuous_equation_systems (const std::string & fname,
90 : const EquationSystems & es,
91 : const std::set<std::string> * system_names)
92 : {
93 68 : LOG_SCOPE("write_discontinuous_equation_systems()", "MeshOutput");
94 :
95 : // We may need to gather and/or renumber a DistributedMesh to output
96 : // it, making that const qualifier in our constructor a dirty lie
97 1207 : MT & my_mesh = const_cast<MT &>(*_obj);
98 :
99 : // If we're asked to write data that's associated with a different
100 : // mesh, output files full of garbage are the result.
101 34 : libmesh_assert_equal_to(&es.get_mesh(), _obj);
102 :
103 : // A non-renumbered mesh may not have a contiguous numbering, and
104 : // that needs to be fixed before we can build a solution vector.
105 2414 : if (my_mesh.max_elem_id() != my_mesh.n_elem() ||
106 1207 : my_mesh.max_node_id() != my_mesh.n_nodes())
107 : {
108 : // If we were allowed to renumber then we should have already
109 : // been properly renumbered...
110 0 : libmesh_assert(!my_mesh.allow_renumbering());
111 :
112 0 : libmesh_do_once(libMesh::out <<
113 : "Warning: This MeshOutput subclass only supports meshes which are contiguously renumbered!"
114 : << std::endl;);
115 :
116 0 : my_mesh.allow_renumbering(true);
117 :
118 0 : my_mesh.renumber_nodes_and_elements();
119 :
120 : // Not sure what good going back to false will do here, the
121 : // renumbering horses have already left the barn...
122 0 : my_mesh.allow_renumbering(false);
123 : }
124 :
125 1275 : MeshSerializer serialize(const_cast<MT &>(*_obj), !_is_parallel_format, _serial_only_needed_on_proc_0);
126 :
127 : // Build the list of variable names that will be written.
128 102 : std::vector<std::string> names;
129 1207 : es.build_variable_names (names, nullptr, system_names);
130 :
131 1207 : if (!_is_parallel_format)
132 : {
133 : // Build the nodal solution values & get the variable
134 : // names from the EquationSystems object
135 68 : std::vector<Number> soln;
136 1207 : es.build_discontinuous_solution_vector (soln, system_names,
137 : nullptr, false, /* defaults */
138 1139 : this->get_add_sides());
139 :
140 1207 : this->write_nodal_data_discontinuous (fname, soln, names);
141 : }
142 : else // _is_parallel_format
143 : {
144 0 : libmesh_not_implemented();
145 : }
146 1207 : }
147 :
148 : template <class MT>
149 0 : void MeshOutput<MT>::write_nodal_data (const std::string & fname,
150 : const NumericVector<Number> & parallel_soln,
151 : const std::vector<std::string> & names)
152 : {
153 : // This is the fallback implementation for parallel I/O formats that
154 : // do not yet implement proper writing in parallel, and instead rely
155 : // on the full solution vector being available on all processors.
156 0 : std::vector<Number> soln;
157 0 : parallel_soln.localize(soln);
158 0 : this->write_nodal_data(fname, soln, names);
159 0 : }
160 :
161 : template <class MT>
162 0 : void MeshOutput<MT>::write_nodal_data (const std::string & fname,
163 : const EquationSystems & es,
164 : const std::set<std::string> * system_names)
165 : {
166 0 : std::vector<std::string> names;
167 0 : es.build_variable_names (names, nullptr, system_names);
168 :
169 0 : std::unique_ptr<NumericVector<Number>> parallel_soln =
170 : es.build_parallel_solution_vector(system_names);
171 :
172 0 : this->write_nodal_data (fname, *parallel_soln, names);
173 0 : }
174 :
175 :
176 :
177 :
178 : // Instantiate for our Mesh types. If this becomes too cumbersome later,
179 : // move any functions in this file to the header file instead.
180 : template class LIBMESH_EXPORT MeshOutput<MeshBase>;
181 : template class LIBMESH_EXPORT MeshOutput<UnstructuredMesh>;
182 : template class LIBMESH_EXPORT MeshOutput<DistributedMesh>;
183 :
184 : } // namespace libMesh
|