libMesh
Loading...
Searching...
No Matches
frequency_system.C
Go to the documentation of this file.
1// The libMesh Finite Element Library.
2// Copyright (C) 2002-2026 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
20// Local includes
21#include "libmesh/libmesh_config.h"
22
23// This class is only enabled in complex numbers builds
24#if defined(LIBMESH_USE_COMPLEX_NUMBERS)
25
26// Local includes
27#include "libmesh/frequency_system.h"
28
29#include "libmesh/equation_systems.h"
30#include "libmesh/int_range.h"
31#include "libmesh/libmesh_logging.h"
32#include "libmesh/linear_solver.h"
33#include "libmesh/numeric_vector.h"
34
35namespace libMesh
36{
37
39 const std::string & name_in,
40 const unsigned int number_in) :
41 LinearImplicitSystem (es, name_in, number_in),
42 solve_system (nullptr),
43 _finished_set_frequencies (false),
44 _keep_solution_duplicates (true),
45 _finished_init (false),
46 _finished_assemble (false)
47{
48 // default value for wave speed & fluid density
49 //_equation_systems.parameters.set<Real>("wave speed") = 340.;
50 //_equation_systems.parameters.set<Real>("rho") = 1.225;
51}
52
53
54
56
57
58
60{
62
65 _finished_init = false;
66 _finished_assemble = false;
67
68 // We have to distinguish between the
69 // simple straightforward "clear()"
70 // and the clear that also touches the
71 // EquationSystems parameters "current frequency" etc.
72 // Namely, when reading from file (through equation_systems_io.C
73 // methods), the param's are read in, then the systems.
74 // Prior to reading a system, this system gets cleared...
75 // And there, all the previously loaded frequency parameters
76 // would get lost...
77}
78
79
80
82{
83 this->clear ();
84
86
87 // clear frequencies in the parameters section of the
88 // EquationSystems object
89 if (es.parameters.have_parameter<unsigned int> ("n_frequencies"))
90 {
91 unsigned int n_freq = es.parameters.get<unsigned int>("n_frequencies");
92 for (unsigned int n=0; n < n_freq; n++)
93 es.parameters.remove(this->form_freq_param_name(n));
94 es.parameters.remove("current frequency");
95 }
96}
97
98
99
100
102{
103 // initialize parent data and additional solution vectors
105
106 // Log how long initializing the system takes
107 LOG_SCOPE("init()", "FrequencySystem");
108
109 EquationSystems & es =
110 this->get_equation_systems();
111
112 // make sure we have frequencies to solve for
114 {
115 // not supported for now
116 if (parameters.have_parameter<unsigned int> ("n_frequencies"))
117 libmesh_not_implemented_msg("ERROR: Setting the n_frequencies parameter on the system is not supported");
118
119 // when this system was read from file, check
120 // if this has a "n_frequencies" parameter,
121 // and initialize us with these.
122 if (es.parameters.have_parameter<unsigned int> ("n_frequencies"))
123 {
124#ifndef NDEBUG
125 const unsigned int n_freq =
126 es.parameters.get<unsigned int>("n_frequencies");
127
128 libmesh_assert_greater (n_freq, 0);
129#endif
131
132 this->set_current_frequency(0.);
133 }
134 else
135 libmesh_error_msg("ERROR: Need to set frequencies before calling init().");
136 }
137
138 _finished_init = true;
139}
140
141
142
144{
146
147 libmesh_error_msg_if(_finished_assemble, "ERROR: Matrices already assembled.");
148
149 // Log how long assemble() takes
150 LOG_SCOPE("assemble()", "FrequencySystem");
151
152 // prepare matrix with the help of the _dof_map,
153 // fill with sparsity pattern, initialize the
154 // additional matrices
156
157 //matrix.print ();
158 //rhs.print ();
159
160 _finished_assemble = true;
161}
162
163
164
166 const Number freq_step,
167 const unsigned int n_freq,
168 const bool allocate_solution_duplicates)
169{
170 this->_keep_solution_duplicates = allocate_solution_duplicates;
171
172 // sanity check
173 libmesh_error_msg_if(_finished_set_frequencies, "ERROR: frequencies already initialized.");
174
175 EquationSystems & es =
176 this->get_equation_systems();
177
178 // store number of frequencies as parameter
179 es.parameters.set<unsigned int>("n_frequencies") = n_freq;
180
181 for (unsigned int n=0; n<n_freq; n++)
182 {
183 // remember frequencies as parameters
185 base_freq + Number(n) * freq_step;
186
187 // build storage for solution vector, if wanted
189 this->add_vector(this->form_solu_vec_name(n));
190 }
191
193
194 // set the current frequency
195 this->set_current_frequency(0);
196}
197
198
199
201 const Number max_freq,
202 const unsigned int n_freq,
203 const bool allocate_solution_duplicates)
204{
205 this->_keep_solution_duplicates = allocate_solution_duplicates;
206
207 // sanity checks. Only look at the real part.
208 libmesh_assert_greater_equal (std::real(max_freq), std::real(min_freq));
209 libmesh_assert_greater (n_freq, 0);
210 libmesh_error_msg_if(_finished_set_frequencies, "ERROR: frequencies already initialized.");
211
212 EquationSystems & es =
213 this->get_equation_systems();
214
215 // store number of frequencies as parameter
216 es.parameters.set<unsigned int>("n_frequencies") = n_freq;
217
218 // set frequencies, build solution storage
219 for (unsigned int n=0; n<n_freq; n++)
220 {
221 // remember frequencies as parameters
223 min_freq + static_cast<Number>(n)*(max_freq-min_freq)/static_cast<Number>(n_freq-1);
224
225 // build storage for solution vector, if wanted
228 }
229
231
232 // set the current frequency
233 this->set_current_frequency(0);
234}
235
236
237
238void FrequencySystem::set_frequencies (const std::vector<Real> & frequencies,
239 const bool allocate_solution_duplicates)
240{
241 libmesh_deprecated();
242 this->_keep_solution_duplicates = allocate_solution_duplicates;
243
244 // sanity checks
245 libmesh_assert(!frequencies.empty());
246 libmesh_error_msg_if(_finished_set_frequencies, "ERROR: frequencies already initialized.");
247
248 EquationSystems & es =
249 this->get_equation_systems();
250
251 // store number of frequencies as parameter
252 es.parameters.set<unsigned int>("n_frequencies") = frequencies.size();
253
254 // set frequencies, build solution storage
255 for (auto n : index_range(frequencies))
256 {
257 // remember frequencies as parameters
258 es.parameters.set<Number>(this->form_freq_param_name(n)) = static_cast<Number>(frequencies[n]);
259
260 // build storage for solution vector, if wanted
263 }
264
266
267 // set the current frequency
268 this->set_current_frequency(0);
269}
270
271
272void FrequencySystem::set_frequencies (const std::vector<Number> & frequencies,
273 const bool allocate_solution_duplicates)
274{
275 libmesh_deprecated();
276 this->_keep_solution_duplicates = allocate_solution_duplicates;
277
278 // sanity checks
279 libmesh_assert(!frequencies.empty());
280 libmesh_error_msg_if(_finished_set_frequencies, "ERROR: frequencies already initialized.");
281
282 EquationSystems & es =
283 this->get_equation_systems();
284
285 // store number of frequencies as parameter
286 es.parameters.set<unsigned int>("n_frequencies") = frequencies.size();
287
288 // set frequencies, build solution storage
289 for (auto n : index_range(frequencies))
290 {
291 // remember frequencies as parameters
292 es.parameters.set<Number>(this->form_freq_param_name(n)) = frequencies[n];
293
294 // build storage for solution vector, if wanted
297 }
298
300
301 // set the current frequency
302 this->set_current_frequency(0);
303}
304
305
306
307
309{
311 return this->get_equation_systems().parameters.get<unsigned int>("n_frequencies");
312}
313
314
315
317{
318 libmesh_assert_greater (this->n_frequencies(), 0);
319
320 // Solve for all the specified frequencies
321 this->solve (0, this->n_frequencies()-1);
322}
323
324
325
326void FrequencySystem::solve (const unsigned int n_start,
327 const unsigned int n_stop)
328{
329 // Assemble the linear system, if not already done
331 this->assemble ();
332
333 // the user-supplied solve method _has_ to be provided by the user
335
336 // existence & range checks
337 libmesh_assert_greater (this->n_frequencies(), 0);
338 libmesh_assert_less (n_stop, this->n_frequencies());
339
340 EquationSystems & es =
341 this->get_equation_systems();
342
343 // Get the user-specified linear solver tolerance,
344 // the user-specified maximum # of linear solver iterations,
345 // the user-specified wave speed
346 const auto [maxits, tol] = this->get_linear_solve_parameters();
347
348 // start solver loop
349 for (unsigned int n=n_start; n<= n_stop; n++)
350 {
351 // set the current frequency
352 this->set_current_frequency(n);
353
354 // Call the user-supplied pre-solve method
355 LOG_CALL("user_pre_solve()", "FrequencySystem", this->solve_system(es, this->name()));
356
357 // Solve the linear system for this specific frequency
358 const std::pair<unsigned int, Real> rval =
359 linear_solver->solve (*matrix, *solution, *rhs, tol, maxits);
360
362 vec_rval.push_back(rval);
363
368 this->get_vector(this->form_solu_vec_name(n)) = *solution;
369 }
370
371 // sanity check
372 //libmesh_assert_equal_to (vec_rval.size(), (n_stop-n_start+1));
373}
374
375
376
378 const std::string & name))
379{
381
383}
384
385
386
388{
389 libmesh_assert_less (n, n_frequencies());
390
391 EquationSystems & es =
392 this->get_equation_systems();
393
394 es.parameters.set<Number>("current frequency") =
395 es.parameters.get<Number>(this->form_freq_param_name(n));
396}
397
398
399
400std::string FrequencySystem::form_freq_param_name(const unsigned int n) const
401{
402 libmesh_assert_less (n, 9999);
403 std::string nstr = std::to_string(n);
404 constexpr std::size_t digits = 4;
405 const int zeros = digits - std::min(digits,nstr.size());
406 nstr.insert(0, zeros, '0');
407 return "frequency "+nstr;
408}
409
410
411
412std::string FrequencySystem::form_solu_vec_name(const unsigned int n) const
413{
414 libmesh_assert_less (n, 9999);
415 std::string nstr = std::to_string(n);
416 constexpr std::size_t digits = 4;
417 const int zeros = digits - std::min(digits,nstr.size());
418 nstr.insert(0, zeros, '0');
419 return "solution "+nstr;
420}
421
422} // namespace libMesh
423
424
425#endif // if defined(LIBMESH_USE_COMPLEX_NUMBERS)
This is the EquationSystems class.
Parameters parameters
Data structure holding arbitrary parameters.
NumericVector< Number > * rhs
The system matrix.
bool _finished_init
true when we have finished the init() phase.
bool _keep_solution_duplicates
when the solution for each frequency should be stored in an additional vector, then this bool is true...
bool _finished_assemble
true when we have finished the assemble() phase.
std::string form_freq_param_name(const unsigned int n) const
virtual void clear() override
Clear all the data structures associated with the system, but leave the frequencies untouched.
virtual void solve() override
Solves the system for all frequencies.
unsigned int n_frequencies() const
virtual void init_data() override
Initializes the member data fields associated with the system, so that, e.g., assemble() may be used.
void set_current_frequency(unsigned int n)
Sets the current frequency to the n-th entry in the vector _frequencies.
std::vector< std::pair< unsigned int, Real > > vec_rval
The number of iterations and the final residual when the Ax=b is solved for multiple frequencies.
bool _finished_set_frequencies
true when we have frequencies to solve for.
void set_frequencies_by_range(const Number min_freq, const Number max_freq, const unsigned int n_freq, const bool allocate_solution_duplicates=true)
Set the frequency range for which the system should be solved.
virtual void assemble() override
Assemble the linear system.
void clear_all()
The full clear method also clears the frequencies (stored as parameters of the EquationSystems object...
FrequencySystem(EquationSystems &es, const std::string &name_in, const unsigned int number_in)
Constructor.
std::string form_solu_vec_name(const unsigned int n) const
void set_frequencies_by_steps(const Number base_freq, const Number freq_step=0., const unsigned int n_freq=1, const bool allocate_solution_duplicates=true)
Set the frequency range for which the system should be solved.
void(* solve_system)(EquationSystems &es, const std::string &name)
Function that computes frequency-dependent data of the system.
void set_frequencies(const std::vector< Real > &frequencies, const bool allocate_solution_duplicates=true)
Set the frequency range by simply copying the values from frequencies.
void attach_solve_function(void fptr(EquationSystems &es, const std::string &name))
Register a required user function to use in assembling/solving the system.
virtual std::pair< unsigned int, Real > get_linear_solve_parameters() const
SparseMatrix< Number > * matrix
The system matrix.
std::unique_ptr< LinearSolver< Number > > linear_solver
This class handles all the details of interfacing with various linear algebra packages like PETSc or ...
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and linear solvers ...
virtual void init_data() override
Initializes new data members of the system.
unsigned int _n_linear_iterations
The number of linear iterations required to solve the linear system Ax=b.
Real _final_linear_residual
The final residual for the linear system Ax=b.
virtual void assemble() override
Prepares matrix and _dof_map for matrix assembly.
virtual void clear() override
Clear all the data structures associated with the system.
void remove(std::string_view)
Removes the specified parameter from the list, if it exists.
Definition parameters.h:509
bool have_parameter(std::string_view) const
Definition parameters.h:420
T & set(const std::string &)
Definition parameters.h:494
const T & get(std::string_view) const
Definition parameters.h:451
const std::string & name() const
Definition system.h:2385
NumericVector< Number > & add_vector(std::string_view vec_name, const bool projections=true, const ParallelType type=PARALLEL)
Adds the additional vector vec_name to this system.
Definition system.C:756
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
Definition system.h:1655
Parameters parameters
Parameters for the system. If a parameter is not provided, it should be retrieved from the EquationSy...
Definition system.h:1588
const EquationSystems & get_equation_systems() const
Definition system.h:767
const NumericVector< Number > & get_vector(std::string_view vec_name) const
Definition system.C:931
The libMesh namespace provides an interface to certain functionality in the library.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition int_range.h:153
libmesh_assert(ctx)
boost::multiprecision::float128 real(const boost::multiprecision::float128 in)
Number fptr(const Point &p, const Parameters &, const std::string &libmesh_dbg_var(sys_name), const std::string &unknown_name)
Definition projection.C:81