libMesh
frequency_system.C
Go to the documentation of this file.
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 
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 
35 namespace 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
184  es.parameters.set<Number>(this->form_freq_param_name(n)) =
185  base_freq + Number(n) * freq_step;
186 
187  // build storage for solution vector, if wanted
188  if (this->_keep_solution_duplicates)
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
222  es.parameters.set<Number>(this->form_freq_param_name(n)) =
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
226  if (this->_keep_solution_duplicates)
228  }
229 
231 
232  // set the current frequency
233  this->set_current_frequency(0);
234 }
235 
236 
237 
238 void 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
261  if (this->_keep_solution_duplicates)
263  }
264 
266 
267  // set the current frequency
268  this->set_current_frequency(0);
269 }
270 
271 
272 void 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
295  if (this->_keep_solution_duplicates)
297  }
298 
300 
301  // set the current frequency
302  this->set_current_frequency(0);
303 }
304 
305 
306 
307 
308 unsigned int FrequencySystem::n_frequencies () const
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 
326 void FrequencySystem::solve (const unsigned int n_start,
327  const unsigned int n_stop)
328 {
329  // Assemble the linear system, if not already done
330  if (!_finished_assemble)
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 
367  if (this->_keep_solution_duplicates)
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 
382  solve_system = fptr;
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 
400 std::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 
412 std::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)
std::string name(const ElemQuality q)
This function returns a string containing some name for q.
Definition: elem_quality.C:42
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 void assemble() override
Prepares matrix and _dof_map for matrix assembly.
virtual void solve() override
Solves the system for all frequencies.
This is the EquationSystems class.
void clear_all()
The full clear method also clears the frequencies (stored as parameters of the EquationSystems object...
void(* solve_system)(EquationSystems &es, const std::string &name)
Function that computes frequency-dependent data of the system.
bool have_parameter(std::string_view) const
Definition: parameters.h:395
boost::multiprecision::float128 real(const boost::multiprecision::float128 in)
virtual void assemble() override
Assemble the linear system.
unsigned int _n_linear_iterations
The number of linear iterations required to solve the linear system Ax=b.
virtual std::pair< unsigned int, Real > get_linear_solve_parameters() const
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and linear solvers ...
const EquationSystems & get_equation_systems() const
Definition: system.h:721
bool _keep_solution_duplicates
when the solution for each frequency should be stored in an additional vector, then this bool is true...
NumericVector< Number > * rhs
The system matrix.
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.
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:768
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.
The libMesh namespace provides an interface to certain functionality in the library.
std::string form_freq_param_name(const unsigned int n) const
FrequencySystem(EquationSystems &es, const std::string &name_in, const unsigned int number_in)
Constructor.
Parameters parameters
Parameters for the system. If a parameter is not provided, it should be retrieved from the EquationSy...
Definition: system.h:1526
Number fptr(const Point &p, const Parameters &, const std::string &libmesh_dbg_var(sys_name), const std::string &unknown_name)
Definition: projection.C:80
bool _finished_assemble
true when we have finished the assemble() phase.
const T & get(std::string_view) const
Definition: parameters.h:426
virtual void init_data() override
Initializes new data members of the system.
virtual void init_data() override
Initializes the member data fields associated with the system, so that, e.g., assemble() may be used...
void remove(std::string_view)
Removes the specified parameter from the list, if it exists.
Definition: parameters.h:484
bool _finished_init
true when we have finished the init() phase.
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
Definition: system.h:1593
libmesh_assert(ctx)
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.
Real _final_linear_residual
The final residual for the linear system Ax=b.
virtual void clear() override
Clear all the data structures associated with the system, but leave the frequencies untouched...
unsigned int n_frequencies() const
T & set(const std::string &)
Definition: parameters.h:469
SparseMatrix< Number > * matrix
The system matrix.
bool _finished_set_frequencies
true when we have frequencies to solve for.
Parameters parameters
Data structure holding arbitrary parameters.
void set_current_frequency(unsigned int n)
Sets the current frequency to the n-th entry in the vector _frequencies.
virtual void clear() override
Clear all the data structures associated with the system.
const std::string & name() const
Definition: system.h:2342
std::unique_ptr< LinearSolver< Number > > linear_solver
This class handles all the details of interfacing with various linear algebra packages like PETSc or ...
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:117
std::string form_solu_vec_name(const unsigned int n) const
const NumericVector< Number > & get_vector(std::string_view vec_name) const
Definition: system.C:943
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...