1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2020 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 #ifndef LIBMESH_VARIABLE_H
19 #define LIBMESH_VARIABLE_H
20 
21 // Local Includes
22 #include "libmesh/libmesh_common.h"
23 #include "libmesh/fe_type.h"
24 #include "libmesh/id_types.h"
25 
26 // C++ includes
27 #include <set>
28 #include <string>
29 #include <vector>
30 
31 namespace libMesh
32 {
33 
34 // Forward Declaration
35 class System;
36 
37 /**
38  * This class defines the notion of a variable in the system.
39  * A variable is one of potentially several unknowns in the
40  * problem at hand.  A variable is described by a unique
41  * name, a finite element approximation family, and
42  * (optionally) a list of subdomains to which the
43  * variable is restricted.
44  *
45  * \author Roy Stogner
46  * \date 2010
47  * \brief A variable which is solved for in a System of equations.
48  */
49 class Variable
50 {
51 public:
52 
53   /**
54    * Constructor.  Omits the subdomain mapping, hence this
55    * constructor creates a variable which is active on
56    * all subdomains.
57    */
Variable(System * sys,const std::string & var_name,const unsigned int var_number,const unsigned int first_scalar_num,const FEType & var_type)58   Variable (System * sys,
59             const std::string & var_name,
60             const unsigned int var_number,
61             const unsigned int first_scalar_num,
62             const FEType & var_type) :
63     _sys(sys),
64     _name(var_name),
65     _active_subdomains(),
66     _number(var_number),
67     _first_scalar_number(first_scalar_num),
68     _type(var_type)
69   {}
70 
71   /**
72    * Constructor.  Takes a set which contains the subdomain
73    * indices for which this variable is active.
74    */
Variable(System * sys,const std::string & var_name,const unsigned int var_number,const unsigned int first_scalar_num,const FEType & var_type,const std::set<subdomain_id_type> & var_active_subdomains)75   Variable (System * sys,
76             const std::string & var_name,
77             const unsigned int var_number,
78             const unsigned int first_scalar_num,
79             const FEType & var_type,
80             const std::set<subdomain_id_type> & var_active_subdomains) :
81     _sys(sys),
82     _name(var_name),
83     _active_subdomains(var_active_subdomains),
84     _number(var_number),
85     _first_scalar_number(first_scalar_num),
86     _type(var_type)
87   {}
88 
89   /**
90    * \returns A pointer to the System this Variable is part of.
91    */
system()92   System * system() const
93   {
94     return _sys;
95   }
96 
97   /**
98    * \returns The user-specified name of the variable.
99    */
name()100   const std::string & name() const
101   { return _name; }
102 
103   /**
104    * \returns The rank of this variable in the system.
105    */
number()106   unsigned int number() const
107   { return _number; }
108 
109   /**
110    * \returns The index of the first scalar component of this variable in the
111    * system.
112    */
first_scalar_number()113   unsigned int first_scalar_number() const
114   { return _first_scalar_number; }
115 
116   /**
117    * \returns The \p FEType for this variable.
118    */
type()119   const FEType & type() const
120   { return _type; }
121 
122   /**
123    * \returns The number of components of this variable.
124    */
n_components()125   unsigned int n_components() const
126   { return type().family == SCALAR ? _type.order.get_order() : 1; }
127 
128   /**
129    * \returns \p true if this variable is active on subdomain \p sid,
130    * \p false otherwise.
131    *
132    * \note We interpret the special case of an empty \p
133    * _active_subdomains container as active everywhere, i.e. for all
134    * subdomains.
135    */
active_on_subdomain(subdomain_id_type sid)136   bool active_on_subdomain (subdomain_id_type sid) const
137   { return (_active_subdomains.empty() || _active_subdomains.count(sid));  }
138 
139   /**
140    * \returns \p true if this variable is active on all subdomains
141    * because it has no specified activity map.  This can be used
142    * to perform more efficient computations in some places.
143    */
implicitly_active()144   bool implicitly_active () const
145   { return _active_subdomains.empty(); }
146 
147   /**
148    * \returns The set of subdomain ids this variable lives on.
149    */
active_subdomains()150   const std::set<subdomain_id_type> & active_subdomains() const
151   { return _active_subdomains; }
152 
153 protected:
154   System *                _sys;
155   std::string             _name;
156   std::set<subdomain_id_type> _active_subdomains;
157   unsigned int            _number;
158   unsigned int            _first_scalar_number;
159   FEType                  _type;
160 };
161 
162 
163 
164 /**
165  * This class defines a logically grouped set of variables in
166  * the system.  \p VariableGroup is appropriate for representing
167  * several unknowns in the problem that are all approximated
168  * with the same finite element approximation family and
169  * (optionally) a list of subdomains to which the
170  * variables are restricted.
171  */
172 class VariableGroup : public Variable
173 {
174 public:
175   /**
176    * Constructor.  Omits the subdomain mapping, hence this
177    * constructor creates a variable which is active on
178    * all subdomains.
179    */
VariableGroup(System * sys,const std::vector<std::string> & var_names,const unsigned int var_number,const unsigned int first_scalar_num,const FEType & var_type)180   VariableGroup (System * sys,
181                  const std::vector<std::string> & var_names,
182                  const unsigned int var_number,
183                  const unsigned int first_scalar_num,
184                  const FEType & var_type) :
185     Variable (sys,
186               "var_group",
187               var_number,
188               first_scalar_num,
189               var_type),
190     _names(var_names)
191   {}
192 
193 
194   /**
195    * Constructor.  Takes a set which contains the subdomain
196    * indices for which this variable is active.
197    */
VariableGroup(System * sys,const std::vector<std::string> & var_names,const unsigned int var_number,const unsigned int first_scalar_num,const FEType & var_type,const std::set<subdomain_id_type> & var_active_subdomains)198   VariableGroup (System * sys,
199                  const std::vector<std::string> & var_names,
200                  const unsigned int var_number,
201                  const unsigned int first_scalar_num,
202                  const FEType & var_type,
203                  const std::set<subdomain_id_type> & var_active_subdomains) :
204 
205     Variable (sys,
206               "var_group",
207               var_number,
208               first_scalar_num,
209               var_type,
210               var_active_subdomains),
211     _names(var_names)
212   {}
213 
214   /**
215    * \returns The number of variables in this \p VariableGroup
216    */
n_variables()217   unsigned int n_variables () const
218   { return cast_int<unsigned int>(_names.size()); }
219 
220   /**
221    * \returns A \p Variable object constructed for an individual member
222    * of our group.
223    */
variable(unsigned int v)224   Variable variable (unsigned int v) const
225   {
226     libmesh_assert_less (v, this->n_variables());
227     return Variable (this->system(),
228                      this->name(v),
229                      this->number(v),
230                      this->first_scalar_number(v),
231                      this->type(),
232                      this->active_subdomains());
233   }
234 
235   /**
236    * Support vg(v).
237    *
238    * \returns A \p Variable for v.
239    */
operator()240   Variable operator() (unsigned int v) const
241   { return this->variable(v); }
242 
243   /**
244    * \returns The user-specified name of the variable.
245    */
name(unsigned int v)246   const std::string & name(unsigned int v) const
247   {
248     libmesh_assert_less (v, this->n_variables());
249     return _names[v];
250   }
251 
252   /**
253    * \returns The rank of this variable in the system.
254    */
number(unsigned int v)255   unsigned int number(unsigned int v) const
256   {
257     libmesh_assert_less (v, this->n_variables());
258     return _number + v;
259   }
260 
261   // Don't let number(uint) hide number()
262   using Variable::number;
263 
264   /**
265    * \returns The index of the first scalar component of this variable in the
266    * system.
267    */
first_scalar_number(unsigned int v)268   unsigned int first_scalar_number(unsigned int v) const
269   {
270     libmesh_assert_less (v, this->n_variables());
271     return _first_scalar_number+v;
272   }
273 
274   /**
275    * Appends a variable to the group.  Really only can be used by \p System in
276    * a very limited window of opportunity - after the user specifies variables
277    * but before the system is initialized.
278    */
append(const std::string & var_name)279   void append (const std::string & var_name)
280   { _names.push_back (var_name); }
281 
282 protected:
283   std::vector<std::string> _names;
284 };
285 
286 } // namespace libMesh
287 
288 #endif // LIBMESH_VARIABLE_H
289