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