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 :
20 : #ifndef LIBMESH_FREQUENCY_SYSTEM_H
21 : #define LIBMESH_FREQUENCY_SYSTEM_H
22 :
23 : #include "libmesh/libmesh_config.h"
24 :
25 : // Frequency domain solutions only possible with complex arithmetic
26 : #if defined(LIBMESH_USE_COMPLEX_NUMBERS)
27 :
28 : // Local Includes
29 : #include "libmesh/linear_implicit_system.h"
30 :
31 : // C++ includes
32 : #include <string>
33 : #include <vector>
34 :
35 : namespace libMesh
36 : {
37 :
38 : /**
39 : * \p FrequencySystem provides a specific system class
40 : * for frequency-dependent (linear) systems.
41 : * Generally two solution flavors are possible:
42 : *
43 : * - Fast solution of moderately-sized systems:
44 : * For moderate numbers of dof, it is possible to keep
45 : * frequency-independent matrices in memory. For this,
46 : * simply provide multiple frequencies prior to \p ini().
47 : * Also provide functions \p _assemble_fptr and \p _solve_fptr
48 : * that should compute the element contributions, and simply add
49 : * these contributions to give the frequency-dependent overall
50 : * matrix, respectively. For details see the examples section.
51 : *
52 : * - Solution of large systems:
53 : * When there is not enough space to keep the frequency-independent
54 : * contributions in memory, the user need only provide a function
55 : * \p _solve_fptr which assembles the overall, frequency-dependent
56 : * matrix for the current frequency given in the parameter section
57 : * of \p EquationSystems<FrequencySystem> named "current frequency".
58 : * For this to work, only provide one frequency.
59 : *
60 : * \author Daniel Dreyer
61 : * \date 2003
62 : */
63 : class FrequencySystem : public LinearImplicitSystem
64 : {
65 : public:
66 :
67 : /**
68 : * Constructor.
69 : */
70 : FrequencySystem (EquationSystems & es,
71 : const std::string & name_in,
72 : const unsigned int number_in);
73 : /**
74 : * Special functions.
75 : * - This class has the same restrictions/defaults as its base class.
76 : * - The destructor is defaulted out-of-line.
77 : */
78 : FrequencySystem (const FrequencySystem &) = delete;
79 : FrequencySystem & operator= (const FrequencySystem &) = delete;
80 : FrequencySystem (FrequencySystem &&) = default;
81 : FrequencySystem & operator= (FrequencySystem &&) = delete;
82 : virtual ~FrequencySystem ();
83 :
84 : /**
85 : * Clear all the data structures associated with
86 : * the system, but leave the frequencies untouched.
87 : * The frequencies belong to the \p EquationSystems
88 : * object.
89 : */
90 : virtual void clear () override;
91 :
92 : /**
93 : * The full clear method also clears the frequencies
94 : * (stored as parameters of the \p EquationSystems
95 : * object).
96 : */
97 : void clear_all ();
98 :
99 : /**
100 : * Assemble the linear system. Does not
101 : * actually call the solver.
102 : */
103 : virtual void assemble () override;
104 :
105 : /**
106 : * Solves the system for all frequencies.
107 : */
108 : virtual void solve () override;
109 :
110 : /**
111 : * Solves the linear system for the
112 : * \f$ [ \texttt{n\_start, n\_stop} ]^{th} \f$
113 : * frequencies. The solution vectors are stored in automatically
114 : * allocated vectors named \p solution_nnnn. For access to these vectors,
115 : * see \p System. When calling this, the frequency range should
116 : * already be set.
117 : */
118 : void solve (const unsigned int n_start,
119 : const unsigned int n_stop);
120 :
121 : /**
122 : * \returns \p "Frequency". Helps in identifying
123 : * the system type in an equation system file.
124 : */
125 2 : virtual std::string system_type () const override { return "Frequency"; }
126 :
127 :
128 : //--------------------------------------------------------
129 : // Methods specific to the FrequencySystem
130 : //
131 :
132 : /**
133 : * Set the frequency range for which the
134 : * system should be solved. \p n_freq frequencies
135 : * are created, where the lowest and highest frequencies
136 : * are \p base_freq, and \p base_freq+freq_step*(n_freq-1),
137 : * respectively. Calls to this of the form
138 : * \p set_frequencies_by_steps(30.) lets this object
139 : * solve the system for only this single frequency.
140 : * By default, the solution for each frequency is copied
141 : * to a separate \p NumericVector. This feature
142 : * can be disabled with \p allocate_solution_duplicates=false.
143 : */
144 : void set_frequencies_by_steps (const Number base_freq,
145 : const Number freq_step=0.,
146 : const unsigned int n_freq=1,
147 : const bool allocate_solution_duplicates=true);
148 :
149 : /**
150 : * Set the frequency range for which the system should
151 : * be solved. \p n_freq frequencies are equally
152 : * distributed in the interval
153 : * \f$ [ \texttt{min\_freq, max\_freq} ] \f$ .
154 : * By default, the solution for each frequency is copied
155 : * to a separate \p NumericVector. This feature
156 : * can be disabled with \p allocate_solution_duplicates=false.
157 : */
158 : void set_frequencies_by_range (const Number min_freq,
159 : const Number max_freq,
160 : const unsigned int n_freq,
161 : const bool allocate_solution_duplicates=true);
162 :
163 : /**
164 : * Set the frequency range by simply copying the values
165 : * from \p frequencies.
166 : * By default, the solution for each frequency is copied
167 : * to a separate \p NumericVector. This feature
168 : * can be disabled with \p allocate_solution_duplicates=false.
169 : */
170 : void set_frequencies (const std::vector<Real> & frequencies,
171 : const bool allocate_solution_duplicates=true);
172 :
173 :
174 : void set_frequencies (const std::vector<Number> & frequencies,
175 : const bool allocate_solution_duplicates=true);
176 :
177 : /**
178 : * \returns The number of frequencies to solve
179 : */
180 : unsigned int n_frequencies () const;
181 :
182 : /**
183 : * Register a required user function to use in assembling/solving the system.
184 : * It is intended to compute frequency-dependent data. For proper
185 : * work of \p FrequencySystem, at least this function has to be provided
186 : * by the user.
187 : */
188 : void attach_solve_function(void fptr(EquationSystems & es,
189 : const std::string & name));
190 :
191 : /**
192 : * Function that computes frequency-dependent data of the system.
193 : */
194 : void (* solve_system) (EquationSystems & es,
195 : const std::string & name);
196 :
197 : /**
198 : * \returns The number of iterations and the final residual.
199 : */
200 : std::pair<unsigned int, Real> get_rval (unsigned int n) const;
201 :
202 : /**
203 : * \returns A string of the form \p "frequency_x", where \p x is
204 : * the integer \p n. Useful for identifying frequencies and
205 : * solution vectors in the parameters set of \p _equation_systems.
206 : */
207 : std::string form_freq_param_name(const unsigned int n) const;
208 :
209 : /**
210 : * \returns A string of the form \p "solution_x", where \p x is
211 : * the integer \p n. Useful for identifying frequencies and
212 : * solution vectors in the vectors map of \p System.
213 : */
214 : std::string form_solu_vec_name(const unsigned int n) const;
215 :
216 :
217 : protected:
218 :
219 :
220 : /**
221 : * Initializes the member data fields associated with
222 : * the system, so that, e.g., \p assemble() may be used.
223 : * The frequencies have to be set prior to calling
224 : * \p init().
225 : */
226 : virtual void init_data () override;
227 :
228 : /**
229 : * Sets the current frequency to the \p n-th entry in the vector
230 : * \p _frequencies.
231 : */
232 : void set_current_frequency(unsigned int n);
233 :
234 : /**
235 : * true when we have frequencies to solve for.
236 : * Setting the frequencies is the first step after
237 : * creating/adding a \p FrequencySystem.
238 : */
239 : bool _finished_set_frequencies;
240 :
241 : /**
242 : * when the solution for each frequency should be
243 : * stored in an additional vector, then this \p bool
244 : * is \p true, otherwise \p false.
245 : * \p _keep_solution_duplicates is implicitly set
246 : * through the \p set_frequencies methods.
247 : */
248 : bool _keep_solution_duplicates;
249 :
250 : /**
251 : * true when we have finished the \p init() phase.
252 : * This is the second step, and requires that
253 : * frequencies have already been set.
254 : */
255 : bool _finished_init;
256 :
257 : /**
258 : * true when we have finished the \p assemble() phase.
259 : * This is the third step and requires that
260 : * a) frequencies have already been set, and
261 : * b) the system has been initialized.
262 : *
263 : * In this linear, frequency-dependent setting,
264 : * the overall system matrices \p mass, \p damping
265 : * and \p stiffness only have to be assembled once,
266 : * before multiple solutions may be obtained for
267 : * different frequencies.
268 : */
269 : bool _finished_assemble;
270 :
271 : /**
272 : * The number of iterations and the final residual
273 : * when the Ax=b is solved for multiple frequencies.
274 : */
275 : std::vector<std::pair<unsigned int, Real>> vec_rval;
276 :
277 : };
278 :
279 :
280 :
281 : // ------------------------------------------------------------
282 : // FrequencySystem inline methods
283 : inline
284 : std::pair<unsigned int, Real> FrequencySystem::get_rval (unsigned int n) const
285 : {
286 : libmesh_assert_less (n, vec_rval.size());
287 :
288 : return vec_rval[n];
289 : }
290 :
291 :
292 : } // namespace libMesh
293 :
294 : #endif // if defined(LIBMESH_USE_COMPLEX_NUMBERS)
295 :
296 : #endif // LIBMESH_FREQUENCY_SYSTEM_H
|