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 
19 
20 #ifndef LIBMESH_DOF_MAP_H
21 #define LIBMESH_DOF_MAP_H
22 
23 // Local Includes
24 #include "libmesh/libmesh_common.h"
25 #include "libmesh/reference_counted_object.h"
26 #include "libmesh/libmesh.h" // libMesh::invalid_uint
27 #include "libmesh/variable.h"
28 #include "libmesh/threads.h"
29 #include "libmesh/threads_allocators.h"
30 #include "libmesh/elem_range.h"
31 #include "libmesh/ghosting_functor.h"
32 #include "libmesh/sparsity_pattern.h"
33 #include "libmesh/parallel_object.h"
34 #include "libmesh/point.h"
35 
36 #ifdef LIBMESH_FORWARD_DECLARE_ENUMS
37 namespace libMesh
38 {
39 enum Order : int;
40 }
41 #else
42 #include "libmesh/enum_order.h"
43 #endif
44 
45 // C++ Includes
46 #include <algorithm>
47 #include <cstddef>
48 #include <iterator>
49 #include <map>
50 #include <string>
51 #include <vector>
52 #include <memory>
53 
54 namespace libMesh
55 {
56 
57 // Forward Declarations
58 class CouplingMatrix;
59 class DefaultCoupling;
60 class DirichletBoundary;
61 class DirichletBoundaries;
62 class DofMap;
63 class DofObject;
64 class Elem;
65 class FEType;
66 class MeshBase;
67 class PeriodicBoundaryBase;
68 class PeriodicBoundaries;
69 class System;
70 class NonlinearImplicitSystem;
71 template <typename T> class DenseVectorBase;
72 template <typename T> class DenseVector;
73 template <typename T> class DenseMatrix;
74 template <typename T> class SparseMatrix;
75 template <typename T> class NumericVector;
76 
77 
78 
79 // ------------------------------------------------------------
80 // Do we need constraints for anything?
81 
82 #if defined(LIBMESH_ENABLE_AMR) ||              \
83   defined(LIBMESH_ENABLE_PERIODIC) ||           \
84   defined(LIBMESH_ENABLE_DIRICHLET)
85 #  define LIBMESH_ENABLE_CONSTRAINTS 1
86 #endif
87 
88 // ------------------------------------------------------------
89 // AMR constraint matrix types
90 
91 #ifdef LIBMESH_ENABLE_CONSTRAINTS
92 /**
93  * A row of the Dof constraint matrix.
94  */
95 typedef std::map<dof_id_type, Real,
96                  std::less<dof_id_type>,
97                  Threads::scalable_allocator<std::pair<const dof_id_type, Real>>> DofConstraintRow;
98 
99 /**
100  * The constraint matrix storage format.
101  * We're using a class instead of a typedef to allow forward
102  * declarations and future flexibility.  Don't delete this from
103  * a pointer-to-std-map; the destructor isn't virtual!
104  */
105 class DofConstraints : public std::map<dof_id_type,
106                                        DofConstraintRow,
107                                        std::less<dof_id_type>,
108                                        Threads::scalable_allocator<std::pair<const dof_id_type, DofConstraintRow>>>
109 {
110 };
111 
112 /**
113  * Storage for DofConstraint right hand sides for a particular
114  * problem.  Each dof id with a non-zero constraint offset
115  * stores it in such a structure.
116  */
117 class DofConstraintValueMap :
118     public std::map<dof_id_type, Number,
119                     std::less<dof_id_type>,
120                     Threads::scalable_allocator<std::pair<const dof_id_type, Number>>>
121 {
122 };
123 
124 /**
125  * Storage for DofConstraint right hand sides for all adjoint
126  * problems.
127  */
128 class AdjointDofConstraintValues :
129     public std::map<unsigned int, DofConstraintValueMap,
130                     std::less<unsigned int>,
131                     Threads::scalable_allocator
132                     <std::pair<const unsigned int, DofConstraintValueMap>>>
133 {
134 };
135 
136 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
137 /**
138  * A row of the Node constraint mapping.  Currently this just
139  * stores the topology of the constrained Nodes, but for forward
140  * compatibility we also include coefficients, so we could add
141  * Lagrange-positioned-node constraints later.
142  */
143 typedef std::map<const Node *, Real,
144                  std::less<const Node *>,
145                  Threads::scalable_allocator<std::pair<const Node * const, Real>>> NodeConstraintRow;
146 
147 /**
148  * The Node constraint storage format.
149  * We're using a class instead of a typedef to allow forward
150  * declarations and future flexibility.  Don't delete this from
151  * a pointer-to-std-map; the destructor isn't virtual!
152  */
153 class NodeConstraints : public std::map<const Node *,
154                                         std::pair<NodeConstraintRow,Point>,
155                                         std::less<const Node *>,
156                                         Threads::scalable_allocator<std::pair<const Node * const, std::pair<NodeConstraintRow,Point>>>>
157 {
158 };
159 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
160 
161 #endif // LIBMESH_ENABLE_CONSTRAINTS
162 
163 
164 
165 /**
166  * This class handles the numbering of degrees of freedom on a mesh.
167  * For systems of equations the class supports a fixed number of variables.
168  * The degrees of freedom are numbered such that sequential, contiguous blocks
169  * belong to distinct processors.  This is so that the resulting data
170  * structures will work well with parallel linear algebra packages.
171  *
172  * \author Benjamin S. Kirk
173  * \date 2002-2007
174  * \brief Manages the degrees of freedom (DOFs) in a simulation.
175  */
176 class DofMap : public ReferenceCountedObject<DofMap>,
177                public ParallelObject
178 {
179 public:
180 
181   /**
182    * Constructor.  Requires the number of the system for which we
183    * will be numbering degrees of freedom & the parent object
184    * we are contained in, which defines our communication space.
185    */
186   explicit
187   DofMap(const unsigned int sys_number,
188          MeshBase & mesh);
189 
190   /**
191    * Destructor.
192    */
193   ~DofMap();
194 
195   /**
196    * Abstract base class to be used to add user-defined implicit
197    * degree of freedom couplings.
198    */
199   class AugmentSparsityPattern
200   {
201   public:
~AugmentSparsityPattern()202     virtual ~AugmentSparsityPattern () {}
203 
204     /**
205      * User-defined function to augment the sparsity pattern.
206      */
207     virtual void augment_sparsity_pattern (SparsityPattern::Graph & sparsity,
208                                            std::vector<dof_id_type> & n_nz,
209                                            std::vector<dof_id_type> & n_oz) = 0;
210   };
211 
212   /**
213    * Abstract base class to be used to add user-defined parallel
214    * degree of freedom couplings.
215    */
216   class AugmentSendList
217   {
218   public:
~AugmentSendList()219     virtual ~AugmentSendList () {}
220 
221     /**
222      * User-defined function to augment the send list.
223      */
224     virtual void augment_send_list (std::vector<dof_id_type> & send_list) = 0;
225   };
226 
227   /**
228    * Additional matrices may be handled with this \p DofMap.
229    * They are initialized to the same sparsity structure as
230    * the major matrix.
231    */
232   void attach_matrix (SparseMatrix<Number> & matrix);
233 
234   /**
235    * Matrices should not be attached more than once.  We can test for
236    * an already-attached matrix if necessary using \p is_attached
237    */
238   bool is_attached (SparseMatrix<Number> & matrix);
239 
240   /**
241    * Distribute dofs on the current mesh.  Also builds the send list for
242    * processor \p proc_id, which defaults to 0 for ease of use in serial
243    * applications.
244    */
245   void distribute_dofs (MeshBase &);
246 
247   /**
248    * Computes the sparsity pattern for the matrices corresponding to
249    * \p proc_id and sends that data to Linear Algebra packages for
250    * preallocation of sparse matrices.
251    */
252   void compute_sparsity (const MeshBase &);
253 
254   /**
255    * Clears the sparsity pattern
256    */
257   void clear_sparsity();
258 
259   /**
260    * Remove any default ghosting functor(s).  User-added ghosting
261    * functors will be unaffected.
262    *
263    * Unless user-added equivalent ghosting functors exist, removing
264    * the default coupling functor is only safe for explicit solves,
265    * and removing the default algebraic ghosting functor is only safe
266    * for codes where no evaluations on neighbor cells (e.g. no jump
267    * error estimators) are done.
268    *
269    * Defaults can be restored manually via add_default_ghosting(), or
270    * automatically if clear() returns the DofMap to a default state.
271    */
272   void remove_default_ghosting();
273 
274   /**
275    * Add the default functor(s) for coupling and algebraic ghosting.
276    * User-added ghosting functors will be unaffected.
277    */
278   void add_default_ghosting();
279 
280   /**
281    * Adds a functor which can specify coupling requirements for
282    * creation of sparse matrices.
283    * Degree of freedom pairs which match the elements and variables
284    * returned by these functors will be added to the sparsity pattern,
285    * and the degrees of freedom which live on other processors will be
286    * added to the send_list for use on ghosted vectors, and the
287    * elements which live on other processors will be ghosted on a
288    * distributed mesh.
289    *
290    * GhostingFunctor memory must be managed by the code which calls
291    * this function; the GhostingFunctor lifetime is expected to extend
292    * until either the functor is removed or the DofMap is destructed.
293    *
294    * When \p to_mesh is true, the \p coupling_functor is also added to
295    * our associated mesh, to ensure that coupled elements do not get
296    * lost during mesh distribution.  (if coupled elements were
297    * *already* lost there's no getting them back after the fact,
298    * sorry)
299    *
300    * If \p to_mesh is false, no change to mesh ghosting is made;
301    * the Mesh must already have ghosting functor(s) specifying a
302    * superset of \p coupling_functor or this is a horrible bug.
303    */
304   void add_coupling_functor(GhostingFunctor & coupling_functor,
305                             bool to_mesh = true);
306 
307   /**
308    * Adds a functor which can specify coupling requirements for
309    * creation of sparse matrices.
310    *
311    * GhostingFunctor memory when using this method is managed by the
312    * shared_ptr mechanism.
313    */
314   void add_coupling_functor(std::shared_ptr<GhostingFunctor> coupling_functor,
315                             bool to_mesh = true)
316   { _shared_functors[coupling_functor.get()] = coupling_functor;
317     this->add_coupling_functor(*coupling_functor, to_mesh); }
318 
319   /**
320    * Removes a functor which was previously added to the set of
321    * coupling functors, from both this DofMap and from the underlying
322    * mesh.
323    */
324   void remove_coupling_functor(GhostingFunctor & coupling_functor);
325 
326   /**
327    * Beginning of range of coupling functors
328    */
coupling_functors_begin()329   std::set<GhostingFunctor *>::const_iterator coupling_functors_begin() const
330   { return _coupling_functors.begin(); }
331 
332   /**
333    * End of range of coupling functors
334    */
coupling_functors_end()335   std::set<GhostingFunctor *>::const_iterator coupling_functors_end() const
336   { return _coupling_functors.end(); }
337 
338   /**
339    * Default coupling functor
340    */
default_coupling()341   DefaultCoupling & default_coupling() { return *_default_coupling; }
342 
343   /**
344    * Adds a functor which can specify algebraic ghosting requirements
345    * for use with distributed vectors.  Degrees of freedom on other
346    * processors which match the elements and variables returned by
347    * these functors will be added to the send_list, and the elements
348    * on other processors will be ghosted on a distributed mesh, so
349    * that the elements can always be found and the solutions on them
350    * will always be evaluable.
351    *
352    * GhostingFunctor memory must be managed by the code which calls
353    * this function; the GhostingFunctor lifetime is expected to extend
354    * until either the functor is removed or the DofMap is destructed.
355    *
356    * When \p to_mesh is true, the \p coupling_functor is also added to
357    * our associated mesh, to ensure that evaluable elements do not get
358    * lost during mesh distribution.  (if evaluable elements were
359    * *already* lost there's no getting them back after the fact,
360    * sorry)
361    *
362    * If \p to_mesh is false, no change to mesh ghosting is made;
363    * the Mesh must already have ghosting functor(s) specifying a
364    * superset of \p evaluable_functor or this is a horrible bug.
365    */
366   void add_algebraic_ghosting_functor(GhostingFunctor & evaluable_functor,
367                                       bool to_mesh = true);
368 
369   /**
370    * Adds a functor which can specify algebraic ghosting requirements
371    * for use with distributed vectors.
372    *
373    * GhostingFunctor memory when using this method is managed by the
374    * shared_ptr mechanism.
375    */
376   void add_algebraic_ghosting_functor(std::shared_ptr<GhostingFunctor> evaluable_functor,
377                                       bool to_mesh = true)
378   { _shared_functors[evaluable_functor.get()] = evaluable_functor;
379     this->add_algebraic_ghosting_functor(*evaluable_functor, to_mesh); }
380 
381   /**
382    * Removes a functor which was previously added to the set of
383    * algebraic ghosting functors, from both this DofMap and from the
384    * underlying mesh.
385    */
386   void remove_algebraic_ghosting_functor(GhostingFunctor & evaluable_functor);
387 
388   /**
389    * Beginning of range of algebraic ghosting functors
390    */
algebraic_ghosting_functors_begin()391   std::set<GhostingFunctor *>::const_iterator algebraic_ghosting_functors_begin() const
392   { return _algebraic_ghosting_functors.begin(); }
393 
394   /**
395    * End of range of algebraic ghosting functors
396    */
algebraic_ghosting_functors_end()397   std::set<GhostingFunctor *>::const_iterator algebraic_ghosting_functors_end() const
398   { return _algebraic_ghosting_functors.end(); }
399 
400   /**
401    * Default algebraic ghosting functor
402    */
default_algebraic_ghosting()403   DefaultCoupling & default_algebraic_ghosting() { return *_default_evaluating; }
404 
405   /**
406    * Attach an object to use to populate the
407    * sparsity pattern with extra entries.
408    *
409    * Care must be taken that when adding entries they are sorted into the Rows
410    *
411    * Further, you _must_ modify n_nz and n_oz properly!
412    *
413    * This is an advanced function... use at your own peril!
414    */
attach_extra_sparsity_object(DofMap::AugmentSparsityPattern & asp)415   void attach_extra_sparsity_object (DofMap::AugmentSparsityPattern & asp)
416   {
417     _augment_sparsity_pattern = &asp;
418   }
419 
420   /**
421    * Attach a function pointer to use as a callback to populate the
422    * sparsity pattern with extra entries.
423    *
424    * Care must be taken that when adding entries they are sorted into the Rows
425    *
426    * Further, you _must_ modify n_nz and n_oz properly!
427    *
428    * This is an advanced function... use at your own peril!
429    */
430   void attach_extra_sparsity_function(void (*func)(SparsityPattern::Graph & sparsity,
431                                                    std::vector<dof_id_type> & n_nz,
432                                                    std::vector<dof_id_type> & n_oz,
433                                                    void *),
434                                       void * context = nullptr)
435   { _extra_sparsity_function = func; _extra_sparsity_context = context; }
436 
437   /**
438    * Attach an object to populate the send_list with extra entries.
439    * This should only add to the send list, but no checking is done
440    * to enforce this behavior.
441    *
442    * This is an advanced function... use at your own peril!
443    */
attach_extra_send_list_object(DofMap::AugmentSendList & asl)444   void attach_extra_send_list_object (DofMap::AugmentSendList & asl)
445   {
446     _augment_send_list = &asl;
447   }
448 
449   /**
450    * Attach a function pointer to use as a callback to populate the
451    * send_list with extra entries.
452    */
453   void attach_extra_send_list_function(void (*func)(std::vector<dof_id_type> &, void *),
454                                        void * context = nullptr)
455   { _extra_send_list_function = func; _extra_send_list_context = context; }
456 
457   /**
458    * Takes the \p _send_list vector (which may have duplicate entries)
459    * and sorts it.  The duplicate entries are then removed, resulting in
460    * a sorted \p _send_list with unique entries.  Also calls any user-provided
461    * methods for adding to the send list.
462    */
463   void prepare_send_list ();
464 
465   /**
466    * Clears the \p _send_list vector. This should be done in order to completely
467    * rebuild the send_list from scratch rather than merely adding to the existing
468    * send_list.
469    */
clear_send_list()470   void clear_send_list ()
471   {
472     _send_list.clear();
473   }
474 
475   /**
476    * Clears the \p _send_list vector and then rebuilds it. This may be needed
477    * in special situations, for example when an algebraic coupling functor cannot
478    * be added to the \p DofMap until after it is completely setup. Then this method
479    * can be used to rebuild the send_list once the algebraic coupling functor is
480    * added. Note that while this will recommunicate constraints with the updated
481    * send_list, this does assume no new constraints have been added since the previous
482    * reinit_constraints call.
483    */
484   void reinit_send_list (MeshBase & mesh);
485 
486 
487   /**
488    * \returns A constant reference to the \p _send_list for this processor.
489    *
490    * The \p _send_list contains the global indices of all the
491    * variables in the global solution vector that influence the
492    * current processor.  This information can be used for gathers at
493    * each solution step to retrieve solution values needed for
494    * computation.
495    */
get_send_list()496   const std::vector<dof_id_type> & get_send_list() const { return _send_list; }
497 
498   /**
499    * \returns A constant reference to the \p _n_nz list for this processor.
500    *
501    * The vector contains the bandwidth of the on-processor coupling for each
502    * row of the global matrix that the current processor owns.  This
503    * information can be used to preallocate space for a parallel sparse matrix.
504    */
get_n_nz()505   const std::vector<dof_id_type> & get_n_nz() const
506   {
507     libmesh_assert(_n_nz);
508     return *_n_nz;
509   }
510 
511   /**
512    * \returns A constant reference to the \p _n_oz list for this processor.
513    *
514    * The vector contains the bandwidth of the off-processor coupling for each
515    * row of the global matrix that the current processor owns.  This
516    * information can be used to preallocate space for a parallel sparse matrix.
517    */
get_n_oz()518   const std::vector<dof_id_type> & get_n_oz() const
519   {
520     libmesh_assert(_n_oz);
521     return *_n_oz;
522   }
523 
524   // /**
525   //  * Add an unknown of order \p order and finite element type
526   //  * \p type to the system of equations.
527   //  */
528   // void add_variable (const Variable & var);
529 
530   /**
531    * Add a group of unknowns of order \p order and finite element type
532    * \p type to the system of equations.
533    */
534   void add_variable_group (const VariableGroup & var_group);
535 
536   /**
537    * Specify whether or not we perform an extra (opt-mode enabled) check
538    * for constraint loops. If a constraint loop is present then
539    * the system constraints are not valid, so if \p error_on_constraint_loop
540    * is true we will throw an error in this case.
541    *
542    * \note We previously referred to these types of constraints as
543    * "cyclic" but that has now been deprecated, and these will now
544    * instead be referred to as "constraint loops" in libMesh.
545    */
546   void set_error_on_cyclic_constraint(bool error_on_cyclic_constraint);
547   void set_error_on_constraint_loop(bool error_on_constraint_loop);
548 
549   /**
550    * \returns The \p VariableGroup description object for group \p g.
551    */
552   const VariableGroup & variable_group (const unsigned int c) const;
553 
554   /**
555    * \returns The variable description object for variable \p c.
556    */
557   const Variable & variable (const unsigned int c) const;
558 
559   /**
560    * \returns The approximation order for variable \p c.
561    */
562   Order variable_order (const unsigned int c) const;
563 
564   /**
565    * \returns The approximation order for \p VariableGroup \p vg.
566    */
567   Order variable_group_order (const unsigned int vg) const;
568 
569   /**
570    * \returns The finite element type for variable \p c.
571    */
572   const FEType & variable_type (const unsigned int c) const;
573 
574   /**
575    * \returns The finite element type for \p VariableGroup \p vg.
576    */
577   const FEType & variable_group_type (const unsigned int vg) const;
578 
579   /**
580    * \returns The number of variables in the global solution vector. Defaults
581    * to 1, should be 1 for a scalar equation, 3 for 2D incompressible Navier
582    * Stokes (u,v,p), etc...
583    */
n_variable_groups()584   unsigned int n_variable_groups() const
585   { return cast_int<unsigned int>(_variable_groups.size()); }
586 
587   /**
588    * \returns The number of variables in the global solution vector. Defaults
589    * to 1, should be 1 for a scalar equation, 3 for 2D incompressible Navier
590    * Stokes (u,v,p), etc...
591    */
n_variables()592   unsigned int n_variables() const
593   { return cast_int<unsigned int>(_variables.size()); }
594 
595   /**
596    * \returns \p true if the variables are capable of being stored in a blocked
597    * form.  Presently, this means that there can only be one variable group,
598    * and that the group has more than one variable.
599    */
has_blocked_representation()600   bool has_blocked_representation() const
601   {
602     return ((this->n_variable_groups() == 1) && (this->n_variables() > 1));
603   }
604 
605   /**
606    * \returns The block size, if the variables are amenable to block storage.
607    * Otherwise 1.
608    * This routine was originally designed to enable a blocked storage, but
609    * it turns out this information is still super useful for solvers even when
610    * we do not use the blocked storage (e.g., MATMPIBAIJ in PETSc). For example (in PCHMG),
611    * for a system of PDEs, to construct an efficient multilevel preconditioner, we coarsen
612    * the matrix of one single PDE instead of the entire huge matrix. In order to
613    * accomplish this, we need to know many PDEs we have. Another use case,
614    * the fieldsplit preconditioner can be constructed in place with this info wihtout
615    * involving any user efforts.
616    */
block_size()617   unsigned int block_size() const
618   {
619     return (this->has_blocked_representation() ? this->n_variables() : 1);
620   }
621 
622   /**
623    * \returns The total number of degrees of freedom in the problem.
624    */
n_dofs()625   dof_id_type n_dofs() const { return _n_dfs; }
626 
627   /**
628    * \returns The number of SCALAR dofs.
629    */
n_SCALAR_dofs()630   dof_id_type n_SCALAR_dofs() const { return _n_SCALAR_dofs; }
631 
632   /**
633    * \returns The number of degrees of freedom on this processor.
634    */
n_local_dofs()635   dof_id_type n_local_dofs () const
636   { return this->n_dofs_on_processor (this->processor_id()); }
637 
638   /**
639    * \returns The number of degrees of freedom on partition \p proc.
640    */
n_dofs_on_processor(const processor_id_type proc)641   dof_id_type n_dofs_on_processor(const processor_id_type proc) const
642   {
643     libmesh_assert_less (proc, _first_df.size());
644     return cast_int<dof_id_type>(_end_df[proc] - _first_df[proc]);
645   }
646 
647   /**
648    * \returns The first dof index that is local to partition \p proc.
649    */
first_dof(const processor_id_type proc)650   dof_id_type first_dof(const processor_id_type proc) const
651   { libmesh_assert_less (proc, _first_df.size()); return _first_df[proc]; }
652 
first_dof()653   dof_id_type first_dof() const
654   { return this->first_dof(this->processor_id()); }
655 
656 #ifdef LIBMESH_ENABLE_AMR
657   /**
658    * \returns The first old dof index that is local to partition \p proc.
659    */
first_old_dof(const processor_id_type proc)660   dof_id_type first_old_dof(const processor_id_type proc) const
661   { libmesh_assert_less (proc, _first_old_df.size()); return _first_old_df[proc]; }
662 
first_old_dof()663   dof_id_type first_old_dof() const
664   { return this->first_old_dof(this->processor_id()); }
665 
666 #endif //LIBMESH_ENABLE_AMR
667 
668   /**
669    * \returns The first dof index that is after all indices local to
670    * processor \p proc.
671    *
672    * Analogous to the end() member function of STL containers.
673    */
end_dof(const processor_id_type proc)674   dof_id_type end_dof(const processor_id_type proc) const
675   { libmesh_assert_less (proc, _end_df.size()); return _end_df[proc]; }
676 
end_dof()677   dof_id_type end_dof() const
678   { return this->end_dof(this->processor_id()); }
679 
680   /**
681    * \returns The processor id that owns the dof index \p dof
682    */
dof_owner(const dof_id_type dof)683   processor_id_type dof_owner(const dof_id_type dof) const
684   { std::vector<dof_id_type>::const_iterator ub =
685       std::upper_bound(_end_df.begin(), _end_df.end(), dof);
686     libmesh_assert (ub != _end_df.end());
687     return cast_int<processor_id_type>(ub - _end_df.begin());
688   }
689 
690 #ifdef LIBMESH_ENABLE_AMR
691   /**
692    * \returns The first old dof index that is after all indices local
693    * to processor \p proc.
694    *
695    * Analogous to the end() member function of STL containers.
696    */
end_old_dof(const processor_id_type proc)697   dof_id_type end_old_dof(const processor_id_type proc) const
698   { libmesh_assert_less (proc, _end_old_df.size()); return _end_old_df[proc]; }
699 
end_old_dof()700   dof_id_type end_old_dof() const
701   { return this->end_old_dof(this->processor_id()); }
702 
703 #endif //LIBMESH_ENABLE_AMR
704 
705   /**
706    * Fills the vector \p di with the global degree of freedom indices
707    * for the element.
708    */
709   void dof_indices (const Elem * const elem,
710                     std::vector<dof_id_type> & di) const;
711 
712   /**
713    * Fills the vector \p di with the global degree of freedom indices
714    * for the element.  For one variable, and potentially for a
715    * non-default element p refinement level
716    */
717   void dof_indices (const Elem * const elem,
718                     std::vector<dof_id_type> & di,
719                     const unsigned int vn,
720                     int p_level = -12345) const;
721 
722   /**
723    * Fills the vector \p di with the global degree of freedom indices
724    * for the \p node.
725    */
726   void dof_indices (const Node * const node,
727                     std::vector<dof_id_type> & di) const;
728 
729   /**
730    * Fills the vector \p di with the global degree of freedom indices
731    * for the \p node, for one variable \p vn.
732    */
733   void dof_indices (const Node * const node,
734                     std::vector<dof_id_type> & di,
735                     const unsigned int vn) const;
736 
737   /**
738    * Appends to the vector \p di the global degree of freedom indices
739    * for \p elem.node_ref(n), for one variable \p vn.  On hanging
740    * nodes with both vertex and non-vertex DoFs, only those indices
741    * which are directly supported on \p elem are included.
742    */
743   void dof_indices (const Elem & elem,
744                     unsigned int n,
745                     std::vector<dof_id_type> & di,
746                     const unsigned int vn) const;
747 
748 #ifdef LIBMESH_ENABLE_AMR
749 
750   /**
751    * Appends to the vector \p di the old global degree of freedom
752    * indices for \p elem.node_ref(n), for one variable \p vn.  On
753    * hanging nodes with both vertex and non-vertex DoFs, only those
754    * indices which are directly supported on \p elem are included.
755    */
756   void old_dof_indices (const Elem & elem,
757                         unsigned int n,
758                         std::vector<dof_id_type> & di,
759                         const unsigned int vn) const;
760 
761 #endif // LIBMESH_ENABLE_AMR
762 
763   /**
764    * Fills the vector \p di with the global degree of freedom indices
765    * corresponding to the SCALAR variable vn. If old_dofs=true,
766    * the old SCALAR dof indices are returned.
767    *
768    * \note We do not need to pass in an element since SCALARs are
769    * global variables.
770    */
771   void SCALAR_dof_indices (std::vector<dof_id_type> & di,
772                            const unsigned int vn,
773                            const bool old_dofs=false) const;
774 
775   /**
776    * \returns \p true if degree of freedom index \p dof_index
777    * is either a local index or in the \p send_list.
778    *
779    * \note This is an O(logN) operation for a send_list of size N; we
780    * don't cache enough information for O(1) right now.
781    */
782   bool semilocal_index (dof_id_type dof_index) const;
783 
784   /**
785    * \returns \p true if all degree of freedom indices in \p
786    * dof_indices are either local indices or in the \p send_list.
787    *
788    * \note This is an O(logN) operation for a send_list of size N; we
789    * don't cache enough information for O(1) right now.
790    */
791   bool all_semilocal_indices (const std::vector<dof_id_type> & dof_indices) const;
792 
793   /**
794    * \returns \p true if degree of freedom index \p dof_index
795    * is a local index.
796    */
local_index(dof_id_type dof_index)797   bool local_index (dof_id_type dof_index) const
798   { return (dof_index >= this->first_dof()) && (dof_index < this->end_dof()); }
799 
800   /**
801    * \returns \p true iff our solutions can be locally evaluated on
802    * \p obj (which should be an Elem or a Node) for variable number \p
803    * var_num (for all variables, if \p var_num is invalid_uint)
804    */
805   template <typename DofObjectSubclass>
806   bool is_evaluable(const DofObjectSubclass & obj,
807                     unsigned int var_num = libMesh::invalid_uint) const;
808 
809   /**
810    * Allow the implicit_neighbor_dofs flag to be set programmatically.
811    * This overrides the --implicit_neighbor_dofs commandline option.
812    * We can use this to set the implicit neighbor dofs option differently
813    * for different systems, whereas the commandline option is the same
814    * for all systems.
815    */
816   void set_implicit_neighbor_dofs(bool implicit_neighbor_dofs);
817 
818   /**
819    * Tells other library functions whether or not this problem
820    * includes coupling between dofs in neighboring cells, as can
821    * currently be specified on the command line or inferred from
822    * the use of all discontinuous variables.
823    */
824   bool use_coupled_neighbor_dofs(const MeshBase & mesh) const;
825 
826   /**
827    * Builds the local element vector \p Ue from the global vector \p Ug,
828    * accounting for any constrained degrees of freedom.  For an element
829    * without constrained degrees of freedom this is the trivial mapping
830    * \f$ Ue[i] = Ug[dof_indices[i]] \f$
831    *
832    * \note The user must ensure that the element vector \p Ue is
833    * properly sized when calling this method.  This is because there
834    * is no \p resize() method in the \p DenseVectorBase<> class.
835    */
836   void extract_local_vector (const NumericVector<Number> & Ug,
837                              const std::vector<dof_id_type> & dof_indices,
838                              DenseVectorBase<Number> & Ue) const;
839 
840   /**
841    * Fills an array of those dof indices which belong to the given
842    * variable number and live on the current processor.
843    */
844   void local_variable_indices(std::vector<dof_id_type> & idx,
845                               const MeshBase & mesh,
846                               unsigned int var_num) const;
847 
848 #ifdef LIBMESH_ENABLE_CONSTRAINTS
849 
850   //--------------------------------------------------------------------
851   // Constraint-specific methods
852   /**
853    * \returns The total number of constrained degrees of freedom
854    * in the problem.
855    */
856   dof_id_type n_constrained_dofs() const;
857 
858   /**
859    * \returns The number of constrained degrees of freedom
860    * on this processor.
861    */
862   dof_id_type n_local_constrained_dofs() const;
863 
864 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
865   /**
866    * \returns The total number of constrained Nodes
867    * in the mesh.
868    */
n_constrained_nodes()869   dof_id_type n_constrained_nodes() const
870   { return cast_int<dof_id_type>(_node_constraints.size()); }
871 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
872 
873   /**
874    * Rebuilds the raw degree of freedom and DofObject constraints.
875    * A time is specified for use in building time-dependent Dirichlet
876    * constraints.
877    */
878   void create_dof_constraints (const MeshBase &, Real time=0);
879 
880   /**
881    * Gathers constraint equation dependencies from other processors
882    */
883   void allgather_recursive_constraints (MeshBase &);
884 
885   /**
886    * Sends constraint equations to constraining processors
887    */
888   void scatter_constraints (MeshBase &);
889 
890   /**
891    * Helper function for querying about constraint equations on other
892    * processors.  If any id in \p requested_dof_ids is constrained on
893    * another processor, its constraint will be added on this processor
894    * as well.  If \p look_for_constrainees is true, then constraints
895    * will also be returned if the id appears as a constraining value
896    * not just if it appears as a constrained value.
897    *
898    * This function operates recursively: if the constraint for a
899    * constrained dof is newly added locally, then any other dofs which
900    * constrain it are queried to see if they are in turn constrained,
901    * and so on.
902    */
903   void gather_constraints (MeshBase & mesh,
904                            std::set<dof_id_type> & unexpanded_dofs,
905                            bool look_for_constrainees);
906 
907   /**
908    * Postprocesses any constrained degrees of freedom
909    * to be constrained only in terms of unconstrained dofs, then adds
910    * unconstrained dofs to the send_list and prepares that for use.
911    * This should be run after both system (create_dof_constraints) and
912    * user constraints have all been added.
913    */
914   void process_constraints (MeshBase &);
915 
916   /**
917    * Throw an error if we detect any constraint loops, i.e.
918    * A -> B -> C -> A
919    * that is, "dof A is constrained in terms of dof B which is
920    * constrained in terms of dof C which is constrained in terms of
921    * dof A", since these are not supported by libMesh and give
922    * erroneous results if they are present.
923    *
924    * \note The original "cyclic constraint" terminology was
925    * unfortunate since the word cyclic is used by some software to
926    * indicate an actual type of rotational/angular contraint and not
927    * (as here) a cyclic graph. The former nomenclature will eventually
928    * be deprecated in favor of "constraint loop".
929    */
930   void check_for_cyclic_constraints();
931   void check_for_constraint_loops();
932 
933   /**
934    * Adds a copy of the user-defined row to the constraint matrix, using
935    * an inhomogeneous right-hand-side for the constraint equation.
936    */
937   void add_constraint_row (const dof_id_type dof_number,
938                            const DofConstraintRow & constraint_row,
939                            const Number constraint_rhs,
940                            const bool forbid_constraint_overwrite);
941 
942   /**
943    * Adds a copy of the user-defined row to the constraint matrix,
944    * using an inhomogeneous right-hand-side for the adjoint constraint
945    * equation.
946    *
947    * \p forbid_constraint_overwrite here only tests for overwriting
948    * the rhs.  This method should only be used when an equivalent
949    * constraint (with a potentially different rhs) already exists for
950    * the primal problem.
951    */
952   void add_adjoint_constraint_row (const unsigned int qoi_index,
953                                    const dof_id_type dof_number,
954                                    const DofConstraintRow & constraint_row,
955                                    const Number constraint_rhs,
956                                    const bool forbid_constraint_overwrite);
957 
958   /**
959    * Adds a copy of the user-defined row to the constraint matrix, using
960    * a homogeneous right-hand-side for the constraint equation.
961    * By default, produces an error if the DOF was already constrained.
962    */
963   void add_constraint_row (const dof_id_type dof_number,
964                            const DofConstraintRow & constraint_row,
965                            const bool forbid_constraint_overwrite = true)
966   { add_constraint_row(dof_number, constraint_row, 0., forbid_constraint_overwrite); }
967 
968   /**
969    * \returns An iterator pointing to the first DoF constraint row.
970    */
constraint_rows_begin()971   DofConstraints::const_iterator constraint_rows_begin() const
972   { return _dof_constraints.begin(); }
973 
974   /**
975    * \returns An iterator pointing just past the last DoF constraint row.
976    */
constraint_rows_end()977   DofConstraints::const_iterator constraint_rows_end() const
978   { return _dof_constraints.end(); }
979 
stash_dof_constraints()980   void stash_dof_constraints()
981   {
982     libmesh_assert(_stashed_dof_constraints.empty());
983     _dof_constraints.swap(_stashed_dof_constraints);
984   }
985 
unstash_dof_constraints()986   void unstash_dof_constraints()
987   {
988     libmesh_assert(_dof_constraints.empty());
989     _dof_constraints.swap(_stashed_dof_constraints);
990   }
991 
992   /**
993    * Similar to the stash/unstash_dof_constraints() API, but swaps
994    * _dof_constraints and _stashed_dof_constraints without asserting
995    * that the source or destination is empty first.
996    *
997    * \note There is an implicit assumption that swapping between sets
998    * of Constraints does not change the sparsity pattern or expand the
999    * send_list, since the only thing changed is the DofConstraints
1000    * themselves.  This is intended to work for swapping between
1001    * DofConstraints A and B, where A is used to define the send_list,
1002    * and B is a subset of A.
1003    */
swap_dof_constraints()1004   void swap_dof_constraints()
1005   {
1006     _dof_constraints.swap(_stashed_dof_constraints);
1007   }
1008 
1009 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
1010   /**
1011    * \returns An iterator pointing to the first Node constraint row.
1012    */
node_constraint_rows_begin()1013   NodeConstraints::const_iterator node_constraint_rows_begin() const
1014   { return _node_constraints.begin(); }
1015 
1016   /**
1017    * \returns An iterator pointing just past the last Node constraint row.
1018    */
node_constraint_rows_end()1019   NodeConstraints::const_iterator node_constraint_rows_end() const
1020   { return _node_constraints.end(); }
1021 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
1022 
1023   /**
1024    * \returns \p true if the degree of freedom dof is constrained,
1025    * \p false otherwise.
1026    */
1027   bool is_constrained_dof (const dof_id_type dof) const;
1028 
1029   /**
1030    * \returns \p true if the system has any heterogenous constraints for
1031    * adjoint solution \p qoi_num, \p false otherwise.
1032    */
1033   bool has_heterogenous_adjoint_constraints (const unsigned int qoi_num) const;
1034 
1035   /**
1036    * \returns The heterogeneous constraint value if the degree of
1037    * freedom \p dof has a heterogenous constraint for adjoint solution
1038    * \p qoi_num, zero otherwise.
1039    */
1040   Number has_heterogenous_adjoint_constraint (const unsigned int qoi_num,
1041                                               const dof_id_type dof) const;
1042 
1043   /**
1044    * \returns A reference to the set of right-hand-side values in
1045    * primal constraint equations
1046    */
1047   DofConstraintValueMap & get_primal_constraint_values();
1048 
1049   /**
1050    * \returns \p true if the Node is constrained,
1051    * false otherwise.
1052    */
1053   bool is_constrained_node (const Node * node) const;
1054 
1055   /**
1056    * Prints (from processor 0) all DoF and Node constraints.  If \p
1057    * print_nonlocal is true, then each constraint is printed once for
1058    * each processor that knows about it, which may be useful for \p
1059    * DistributedMesh debugging.
1060    */
1061   void print_dof_constraints(std::ostream & os=libMesh::out,
1062                              bool print_nonlocal=false) const;
1063 
1064   /**
1065    * Gets a string reporting all DoF and Node constraints local to
1066    * this processor.  If \p print_nonlocal is true, then nonlocal
1067    * constraints which are locally known are included.
1068    */
1069   std::string get_local_constraints(bool print_nonlocal=false) const;
1070 
1071 
1072   /**
1073    * Tests the constrained degrees of freedom on the numeric vector \p v, which
1074    * represents a solution defined on the mesh, returning a pair whose first
1075    * entry is the maximum absolute error on a constrained DoF and whose second
1076    * entry is the maximum relative error.  Useful for debugging purposes.
1077    *
1078    * If \p v == nullptr, the system solution vector is tested.
1079    */
1080   std::pair<Real, Real> max_constraint_error(const System & system,
1081                                              NumericVector<Number> * v = nullptr) const;
1082 
1083 #endif // LIBMESH_ENABLE_CONSTRAINTS
1084 
1085   //--------------------------------------------------------------------
1086   // Constraint-specific methods
1087   // Some of these methods are enabled (but inlined away to nothing)
1088   // when constraints are disabled at configure-time.  This is to
1089   // increase API compatibility of user code with different library
1090   // builds.
1091 
1092   /**
1093    * Constrains the element matrix.  This method requires the
1094    * element matrix to be square, in which case the elem_dofs
1095    * correspond to the global DOF indices of both the rows and
1096    * columns of the element matrix.  For this case the rows
1097    * and columns of the matrix necessarily correspond to variables
1098    * of the same approximation order.
1099    *
1100    * If \p asymmetric_constraint_rows is set to true (as it is by
1101    * default), constraint row equations will be reinforced in a way
1102    * which breaks matrix symmetry but makes inexact linear solver
1103    * solutions more likely to satisfy hanging node constraints.
1104    */
1105   void constrain_element_matrix (DenseMatrix<Number> & matrix,
1106                                  std::vector<dof_id_type> & elem_dofs,
1107                                  bool asymmetric_constraint_rows = true) const;
1108 
1109   /**
1110    * Constrains the element matrix.  This method allows the
1111    * element matrix to be non-square, in which case the row_dofs
1112    * and col_dofs may be of different size and correspond to
1113    * variables approximated in different spaces.
1114    */
1115   void constrain_element_matrix (DenseMatrix<Number> & matrix,
1116                                  std::vector<dof_id_type> & row_dofs,
1117                                  std::vector<dof_id_type> & col_dofs,
1118                                  bool asymmetric_constraint_rows = true) const;
1119 
1120   /**
1121    * Constrains the element vector.
1122    */
1123   void constrain_element_vector (DenseVector<Number> & rhs,
1124                                  std::vector<dof_id_type> & dofs,
1125                                  bool asymmetric_constraint_rows = true) const;
1126 
1127   /**
1128    * Constrains the element matrix and vector.  This method requires
1129    * the element matrix to be square, in which case the elem_dofs
1130    * correspond to the global DOF indices of both the rows and
1131    * columns of the element matrix.  For this case the rows
1132    * and columns of the matrix necessarily correspond to variables
1133    * of the same approximation order.
1134    */
1135   void constrain_element_matrix_and_vector (DenseMatrix<Number> & matrix,
1136                                             DenseVector<Number> & rhs,
1137                                             std::vector<dof_id_type> & elem_dofs,
1138                                             bool asymmetric_constraint_rows = true) const;
1139 
1140   /**
1141    * Constrains the element matrix and vector.  This method requires
1142    * the element matrix to be square, in which case the elem_dofs
1143    * correspond to the global DOF indices of both the rows and
1144    * columns of the element matrix.  For this case the rows
1145    * and columns of the matrix necessarily correspond to variables
1146    * of the same approximation order.
1147    *
1148    * The heterogenous version of this method creates linear systems in
1149    * which heterogenously constrained degrees of freedom will solve to
1150    * their correct offset values, as would be appropriate for finding
1151    * a solution to a linear problem in a single algebraic solve.  The
1152    * non-heterogenous version of this method creates linear systems in
1153    * which even heterogenously constrained degrees of freedom are
1154    * solved without offset values taken into account, as would be
1155    * appropriate for finding linearized updates to a solution in which
1156    * heterogenous constraints are already satisfied.
1157    *
1158    * By default, the constraints for the primal solution of this
1159    * system are used.  If a non-negative \p qoi_index is passed in,
1160    * then the constraints for the corresponding adjoint solution are
1161    * used instead.
1162    */
1163   void heterogenously_constrain_element_matrix_and_vector (DenseMatrix<Number> & matrix,
1164                                                            DenseVector<Number> & rhs,
1165                                                            std::vector<dof_id_type> & elem_dofs,
1166                                                            bool asymmetric_constraint_rows = true,
1167                                                            int qoi_index = -1) const;
1168 
1169   /**
1170    * Constrains the element vector.  This method requires
1171    * the element matrix to be square and not-yet-constrained, in which
1172    * case the elem_dofs correspond to the global DOF indices of both
1173    * the rows and columns of the element matrix.
1174    *
1175    * The heterogenous version of this method creates linear systems in
1176    * which heterogenously constrained degrees of freedom will solve to
1177    * their correct offset values, as would be appropriate for finding
1178    * a solution to a linear problem in a single algebraic solve.  The
1179    * non-heterogenous version of this method creates linear systems in
1180    * which even heterogenously constrained degrees of freedom are
1181    * solved without offset values taken into account, as would be
1182    * appropriate for finding linearized updates to a solution in which
1183    * heterogenous constraints are already satisfied.
1184    *
1185    * By default, the constraints for the primal solution of this
1186    * system are used.  If a non-negative \p qoi_index is passed in,
1187    * then the constraints for the corresponding adjoint solution are
1188    * used instead.
1189    */
1190   void heterogenously_constrain_element_vector (const DenseMatrix<Number> & matrix,
1191                                                 DenseVector<Number> & rhs,
1192                                                 std::vector<dof_id_type> & elem_dofs,
1193                                                 bool asymmetric_constraint_rows = true,
1194                                                 int qoi_index = -1) const;
1195 
1196 
1197 
1198   /**
1199    * Constrains a dyadic element matrix B = v w'.  This method
1200    * requires the element matrix to be square, in which case the
1201    * elem_dofs correspond to the global DOF indices of both the rows
1202    * and columns of the element matrix.  For this case the rows and
1203    * columns of the matrix necessarily correspond to variables of the
1204    * same approximation order.
1205    */
1206   void constrain_element_dyad_matrix (DenseVector<Number> & v,
1207                                       DenseVector<Number> & w,
1208                                       std::vector<dof_id_type> & row_dofs,
1209                                       bool asymmetric_constraint_rows = true) const;
1210 
1211   /**
1212    * Does not actually constrain anything, but modifies \p dofs in the
1213    * same way as any of the constrain functions would do, i.e. adds
1214    * those dofs in terms of which any of the existing dofs is
1215    * constrained.
1216    */
1217   void constrain_nothing (std::vector<dof_id_type> & dofs) const;
1218 
1219   /**
1220    * Constrains the numeric vector \p v, which represents a solution defined on
1221    * the mesh.  This may need to be used after a linear solve, if your linear
1222    * solver's solutions do not satisfy your DoF constraints to a tight enough
1223    * tolerance.
1224    *
1225    * If \p v == nullptr, the system solution vector is constrained
1226    *
1227    * If \p homogeneous == true, heterogeneous constraints are enforced
1228    * as if they were homogeneous.  This might be appropriate for e.g. a
1229    * vector representing a difference between two
1230    * heterogeneously-constrained solutions.
1231    */
1232   void enforce_constraints_exactly (const System & system,
1233                                     NumericVector<Number> * v = nullptr,
1234                                     bool homogeneous = false) const;
1235 
1236   /**
1237    * Heterogenously constrains the numeric vector \p v, which
1238    * represents an adjoint solution defined on the mesh for quantity
1239    * fo interest \p q.  For homogeneous constraints, use \p
1240    * enforce_constraints_exactly instead
1241    */
1242   void enforce_adjoint_constraints_exactly (NumericVector<Number> & v,
1243                                             unsigned int q) const;
1244 
1245   void enforce_constraints_on_residual (const NonlinearImplicitSystem & system,
1246                                         NumericVector<Number> * rhs,
1247                                         NumericVector<Number> const * solution,
1248                                         bool homogeneous = true) const;
1249 
1250   void enforce_constraints_on_jacobian (const NonlinearImplicitSystem & system,
1251                                         SparseMatrix<Number> * jac) const;
1252 
1253 #ifdef LIBMESH_ENABLE_PERIODIC
1254 
1255   //--------------------------------------------------------------------
1256   // PeriodicBoundary-specific methods
1257 
1258   /**
1259    * Adds a copy of the specified periodic boundary to the system.
1260    */
1261   void add_periodic_boundary (const PeriodicBoundaryBase & periodic_boundary);
1262 
1263   /**
1264    * Add a periodic boundary pair
1265    *
1266    * \param boundary - primary boundary
1267    * \param inverse_boundary - inverse boundary
1268    */
1269   void add_periodic_boundary (const PeriodicBoundaryBase & boundary, const PeriodicBoundaryBase & inverse_boundary);
1270 
1271   /**
1272    * \returns \p true if the boundary given by \p boundaryid is periodic,
1273    * false otherwise
1274    */
1275   bool is_periodic_boundary (const boundary_id_type boundaryid) const;
1276 
get_periodic_boundaries()1277   PeriodicBoundaries * get_periodic_boundaries()
1278   {
1279     return _periodic_boundaries.get();
1280   }
1281 
1282 #endif // LIBMESH_ENABLE_PERIODIC
1283 
1284 
1285 #ifdef LIBMESH_ENABLE_DIRICHLET
1286 
1287   //--------------------------------------------------------------------
1288   // DirichletBoundary-specific methods
1289 
1290   /**
1291    * Adds a copy of the specified Dirichlet boundary to the system.
1292    *
1293    * The constraints implied by DirichletBoundary objects are imposed
1294    * in the same order in which DirichletBoundary objects are added to
1295    * the DofMap. When multiple DirichletBoundary objects would impose
1296    * competing constraints on a given DOF, the *first*
1297    * DirichletBoundary to constrain the DOF "wins". This distinction
1298    * is important when e.g. two surfaces (sidesets) intersect. The
1299    * nodes on the intersection will be constrained according to
1300    * whichever sideset's DirichletBoundary object was added to the
1301    * DofMap first.
1302    */
1303   void add_dirichlet_boundary (const DirichletBoundary & dirichlet_boundary);
1304 
1305   /**
1306    * Adds a copy of the specified Dirichlet boundary to the system,
1307    * corresponding to the adjoint problem defined by Quantity of
1308    * Interest \p q.
1309    */
1310   void add_adjoint_dirichlet_boundary (const DirichletBoundary & dirichlet_boundary,
1311                                        unsigned int q);
1312 
1313   /**
1314    * Removes the specified Dirichlet boundary from the system.
1315    */
1316   void remove_dirichlet_boundary (const DirichletBoundary & dirichlet_boundary);
1317 
1318   /**
1319    * Removes from the system the specified Dirichlet boundary for the
1320    * adjoint equation defined by Quantity of interest index q
1321    */
1322   void remove_adjoint_dirichlet_boundary (const DirichletBoundary & dirichlet_boundary,
1323                                           unsigned int q);
1324 
get_dirichlet_boundaries()1325   const DirichletBoundaries * get_dirichlet_boundaries() const
1326   {
1327     return _dirichlet_boundaries.get();
1328   }
1329 
get_dirichlet_boundaries()1330   DirichletBoundaries * get_dirichlet_boundaries()
1331   {
1332     return _dirichlet_boundaries.get();
1333   }
1334 
1335   bool has_adjoint_dirichlet_boundaries(unsigned int q) const;
1336 
1337   const DirichletBoundaries *
1338   get_adjoint_dirichlet_boundaries(unsigned int q) const;
1339 
1340   DirichletBoundaries *
1341   get_adjoint_dirichlet_boundaries(unsigned int q);
1342 
1343 #endif // LIBMESH_ENABLE_DIRICHLET
1344 
1345 
1346 #ifdef LIBMESH_ENABLE_AMR
1347 
1348   //--------------------------------------------------------------------
1349   // AMR-specific methods
1350 
1351   /**
1352    * After a mesh is refined and repartitioned it is possible that the
1353    * \p _send_list will need to be augmented.  This is the case when an
1354    * element is refined and its children end up on different processors
1355    * than the parent.  These children will need values from the parent
1356    * when projecting the solution onto the refined mesh, hence the parent's
1357    * DOF indices need to be included in the \p _send_list.
1358    */
1359   // void augment_send_list_for_projection(const MeshBase &);
1360 
1361 #ifdef LIBMESH_ENABLE_AMR
1362 
1363   /**
1364    * Fills the vector di with the global degree of freedom indices
1365    * for the element using the \p DofMap::old_dof_object.
1366    * If no variable number is specified then all
1367    * variables are returned.
1368    */
1369   void old_dof_indices (const Elem * const elem,
1370                         std::vector<dof_id_type> & di,
1371                         const unsigned int vn = libMesh::invalid_uint) const;
1372 
1373   /**
1374    * \returns The total number of degrees of freedom on old_dof_objects
1375    */
n_old_dofs()1376   dof_id_type n_old_dofs() const { return _n_old_dfs; }
1377 
1378 #endif // LIBMESH_ENABLE_AMR
1379 
1380   /**
1381    * Constrains degrees of freedom on side \p s of element \p elem which
1382    * correspond to variable number \p var and to p refinement levels
1383    * above \p p.
1384    */
1385   void constrain_p_dofs (unsigned int var,
1386                          const Elem * elem,
1387                          unsigned int s,
1388                          unsigned int p);
1389 
1390 #endif // LIBMESH_ENABLE_AMR
1391 
1392   /**
1393    * Reinitialize the underlying data structures conformal to the current mesh.
1394    */
1395   void reinit (MeshBase & mesh);
1396 
1397   /**
1398    * Free all new memory associated with the object, but restore its
1399    * original state, with the mesh pointer and any default ghosting.
1400    */
1401   void clear ();
1402 
1403   /**
1404    * Prints summary info about the sparsity bandwidth and constraints.
1405    */
1406   void print_info(std::ostream & os=libMesh::out) const;
1407 
1408   /**
1409    * Gets summary info about the sparsity bandwidth and constraints.
1410    */
1411   std::string get_info() const;
1412 
1413   /**
1414    * Degree of freedom coupling.  If left empty each DOF
1415    * couples to all others.  Can be used to reduce memory
1416    * requirements for sparse matrices.  DOF 0 might only
1417    * couple to itself, in which case \p dof_coupling(0,0)
1418    * should be 1 and \p dof_coupling(0,j) = 0 for j not equal
1419    * to 0.
1420    *
1421    * This variable is named as though it were class private,
1422    * but it is in the public interface.  Also there are no
1423    * public methods for accessing it...  This typically means
1424    * you should only use it if you know what you are doing.
1425    */
1426   CouplingMatrix * _dof_coupling;
1427 
1428   /**
1429    * \returns The number of the system we are responsible for.
1430    */
1431   unsigned int sys_number() const;
1432 
1433 private:
1434 
1435   /**
1436    * Helper function that gets the dof indices on the current element
1437    * for a non-SCALAR type variable, where the variable is identified
1438    * by its variable group number \p vg and its offset \p vig from the
1439    * first variable in that group.
1440    *
1441    * In DEBUG mode, the tot_size parameter will add up the total
1442    * number of dof indices that should have been added to di, and v
1443    * will be the variable number corresponding to vg and vig.
1444    */
1445   void _dof_indices (const Elem & elem,
1446                      int p_level,
1447                      std::vector<dof_id_type> & di,
1448                      const unsigned int vg,
1449                      const unsigned int vig,
1450                      const Node * const * nodes,
1451                      unsigned int       n_nodes
1452 #ifdef DEBUG
1453                      ,
1454                      const unsigned int v,
1455                      std::size_t & tot_size
1456 #endif
1457                      ) const;
1458 
1459   /**
1460    * Helper function that implements the element-nodal versions of
1461    * dof_indices and old_dof_indices
1462    */
1463   void _node_dof_indices (const Elem & elem,
1464                           unsigned int n,
1465                           const DofObject & obj,
1466                           std::vector<dof_id_type> & di,
1467                           const unsigned int vn) const;
1468 
1469   /**
1470    * Builds a sparsity pattern
1471    */
1472   std::unique_ptr<SparsityPattern::Build> build_sparsity(const MeshBase & mesh) const;
1473 
1474   /**
1475    * Invalidates all active DofObject dofs for this system
1476    */
1477   void invalidate_dofs(MeshBase & mesh) const;
1478 
1479   /**
1480    * \returns The Node pointer with index \p i from the \p mesh.
1481    */
1482   DofObject * node_ptr(MeshBase & mesh, dof_id_type i) const;
1483 
1484   /**
1485    * \returns The Elem pointer with index \p i from the \p mesh.
1486    */
1487   DofObject * elem_ptr(MeshBase & mesh, dof_id_type i) const;
1488 
1489   /**
1490    * A member function type like \p node_ptr() or \p elem_ptr().
1491    */
1492   typedef DofObject * (DofMap::*dofobject_accessor)
1493     (MeshBase & mesh, dof_id_type i) const;
1494 
1495   /**
1496    * Helper function for distributing dofs in parallel
1497    */
1498   template<typename iterator_type>
1499   void set_nonlocal_dof_objects(iterator_type objects_begin,
1500                                 iterator_type objects_end,
1501                                 MeshBase & mesh,
1502                                 dofobject_accessor objects);
1503 
1504   /**
1505    * Distributes the global degrees of freedom, for dofs on
1506    * this processor.  In this format the local
1507    * degrees of freedom are in a contiguous block for each
1508    * variable in the system.
1509    * Starts at index next_free_dof, and increments it to
1510    * the post-final index.
1511    */
1512   void distribute_local_dofs_var_major (dof_id_type & next_free_dof,
1513                                         MeshBase & mesh);
1514 
1515   /**
1516    * Distributes the global degrees of freedom for dofs on this
1517    * processor.  In this format all the degrees of freedom at a
1518    * node/element are in contiguous blocks.  Starts at index \p
1519    * next_free_dof, and increments it to the post-final index.  If \p
1520    * build_send_list is \p true, builds the send list.  If \p false,
1521    * clears and reserves the send list.
1522    *
1523    * \note The degrees of freedom for a given variable are not in
1524    * contiguous blocks, as in the case of \p distribute_local_dofs_var_major.
1525    */
1526   void distribute_local_dofs_node_major (dof_id_type & next_free_dof,
1527                                          MeshBase & mesh);
1528 
1529   /*
1530    * A utility method for obtaining a set of elements to ghost along
1531    * with merged coupling matrices.
1532    */
1533   static void
1534   merge_ghost_functor_outputs (GhostingFunctor::map_type & elements_to_ghost,
1535                                std::set<CouplingMatrix *> & temporary_coupling_matrices,
1536                                const std::set<GhostingFunctor *>::iterator & gf_begin,
1537                                const std::set<GhostingFunctor *>::iterator & gf_end,
1538                                const MeshBase::const_element_iterator & elems_begin,
1539                                const MeshBase::const_element_iterator & elems_end,
1540                                processor_id_type p);
1541 
1542   /**
1543    * Adds entries to the \p _send_list vector corresponding to DoFs
1544    * on elements neighboring the current processor.
1545    */
1546   void add_neighbors_to_send_list(MeshBase & mesh);
1547 
1548 #ifdef LIBMESH_ENABLE_CONSTRAINTS
1549 
1550   /**
1551    * Build the constraint matrix C associated with the element
1552    * degree of freedom indices elem_dofs. The optional parameter
1553    * \p called_recursively should be left at the default value
1554    * \p false.  This is used to handle the special case of
1555    * an element's degrees of freedom being constrained in terms
1556    * of other, local degrees of freedom.  The usual case is
1557    * for an elements DOFs to be constrained by some other,
1558    * external DOFs.
1559    */
1560   void build_constraint_matrix (DenseMatrix<Number> & C,
1561                                 std::vector<dof_id_type> & elem_dofs,
1562                                 const bool called_recursively=false) const;
1563 
1564   /**
1565    * Build the constraint matrix C and the forcing vector H
1566    * associated with the element degree of freedom indices elem_dofs.
1567    * The optional parameter \p called_recursively should be left at
1568    * the default value \p false.  This is used to handle the special
1569    * case of an element's degrees of freedom being constrained in
1570    * terms of other, local degrees of freedom.  The usual case is for
1571    * an elements DOFs to be constrained by some other, external DOFs
1572    * and/or Dirichlet conditions.
1573    *
1574    * The forcing vector will depend on which solution's heterogenous
1575    * constraints are being applied.  For the default \p qoi_index this
1576    * will be the primal solution; for \p qoi_index >= 0 the
1577    * corresponding adjoint solution's constraints will be used.
1578    */
1579   void build_constraint_matrix_and_vector (DenseMatrix<Number> & C,
1580                                            DenseVector<Number> & H,
1581                                            std::vector<dof_id_type> & elem_dofs,
1582                                            int qoi_index = -1,
1583                                            const bool called_recursively=false) const;
1584 
1585   /**
1586    * Finds all the DOFS associated with the element DOFs elem_dofs.
1587    * This will account for off-element couplings via hanging nodes.
1588    */
1589   void find_connected_dofs (std::vector<dof_id_type> & elem_dofs) const;
1590 
1591   /**
1592    * Finds all the DofObjects associated with the set in \p objs.
1593    * This will account for off-element couplings via hanging nodes.
1594    */
1595   void find_connected_dof_objects (std::vector<const DofObject *> & objs) const;
1596 
1597   /**
1598    * Adds entries to the \p _send_list vector corresponding to DoFs
1599    * which are dependencies for constraint equations on the current
1600    * processor.
1601    */
1602   void add_constraints_to_send_list();
1603 
1604 #endif // LIBMESH_ENABLE_CONSTRAINTS
1605 
1606   /**
1607    * This flag indicates whether or not we do an opt-mode check for
1608    * the presence of constraint loops, i.e. cases where the constraint
1609    * graph is cyclic.
1610    */
1611   bool _error_on_constraint_loop;
1612 
1613   /**
1614    * The finite element type for each variable.
1615    */
1616   std::vector<Variable> _variables;
1617 
1618   /**
1619    * The finite element type for each variable group.
1620    */
1621   std::vector<VariableGroup> _variable_groups;
1622 
1623   /**
1624    * The variable group number for each variable.
1625    */
1626   std::vector<unsigned int> _variable_group_numbers;
1627 
1628   /**
1629    * The number of the system we manage DOFs for.
1630    */
1631   const unsigned int _sys_number;
1632 
1633   /**
1634    * The mesh that system uses.
1635    */
1636   MeshBase & _mesh;
1637 
1638   /**
1639    * Additional matrices handled by this object.  These pointers do \e
1640    * not handle the memory, instead, \p System, who
1641    * told \p DofMap about them, owns them.
1642    */
1643   std::vector<SparseMatrix<Number> * > _matrices;
1644 
1645   /**
1646    * First DOF index on processor \p p.
1647    */
1648   std::vector<dof_id_type> _first_df;
1649 
1650   /**
1651    * Last DOF index (plus 1) on processor \p p.
1652    */
1653   std::vector<dof_id_type> _end_df;
1654 
1655   /**
1656    * First DOF index for SCALAR variable v, or garbage for non-SCALAR
1657    * variable v
1658    */
1659   std::vector<dof_id_type> _first_scalar_df;
1660 
1661   /**
1662    * A list containing all the global DOF indices that affect the
1663    * solution on my processor.
1664    */
1665   std::vector<dof_id_type> _send_list;
1666 
1667   /**
1668    * Function object to call to add extra entries to the sparsity pattern
1669    */
1670   AugmentSparsityPattern * _augment_sparsity_pattern;
1671 
1672   /**
1673    * A function pointer to a function to call to add extra entries to the sparsity pattern
1674    */
1675   void (*_extra_sparsity_function)(SparsityPattern::Graph &,
1676                                    std::vector<dof_id_type> & n_nz,
1677                                    std::vector<dof_id_type> & n_oz,
1678                                    void *);
1679   /**
1680    * A pointer associated with the extra sparsity that can optionally be passed in
1681    */
1682   void * _extra_sparsity_context;
1683 
1684   /**
1685    * Function object to call to add extra entries to the send list
1686    */
1687   AugmentSendList * _augment_send_list;
1688 
1689   /**
1690    * A function pointer to a function to call to add extra entries to the send list
1691    */
1692   void (*_extra_send_list_function)(std::vector<dof_id_type> &, void *);
1693 
1694   /**
1695    * A pointer associated with the extra send list that can optionally be passed in
1696    */
1697   void * _extra_send_list_context;
1698 
1699   /**
1700    * The default coupling GhostingFunctor, used to implement standard
1701    * libMesh sparsity pattern construction.
1702    *
1703    * We use a std::unique_ptr here to reduce header dependencies.
1704    */
1705   std::unique_ptr<DefaultCoupling> _default_coupling;
1706 
1707   /**
1708    * The default algebraic GhostingFunctor, used to implement standard
1709    * libMesh send_list construction.
1710    *
1711    * We use a std::unique_ptr here to reduce header dependencies.
1712    */
1713   std::unique_ptr<DefaultCoupling> _default_evaluating;
1714 
1715   /**
1716    * The list of all GhostingFunctor objects to be used when
1717    * distributing ghosted vectors.
1718    *
1719    * The library should automatically copy these functors to the
1720    * MeshBase, too, so any algebraically ghosted dofs will live on
1721    * geometrically ghosted elements.
1722    */
1723   std::set<GhostingFunctor *> _algebraic_ghosting_functors;
1724 
1725   /**
1726    * The list of all GhostingFunctor objects to be used when
1727    * coupling degrees of freedom in matrix sparsity patterns.
1728    *
1729    * These objects will *also* be used as algebraic ghosting functors,
1730    * but not vice-versa.
1731    *
1732    * The library should automatically copy these functors to the
1733    * MeshBase, too, so any dofs coupled to local dofs will live on
1734    * geometrically ghosted elements.
1735    */
1736   std::set<GhostingFunctor *> _coupling_functors;
1737 
1738   /**
1739    * Hang on to references to any GhostingFunctor objects we were
1740    * passed in shared_ptr form
1741    */
1742   std::map<GhostingFunctor *, std::shared_ptr<GhostingFunctor> > _shared_functors;
1743 
1744   /**
1745    * Default false; set to true if any attached matrix requires a full
1746    * sparsity pattern.
1747    */
1748   bool need_full_sparsity_pattern;
1749 
1750   /**
1751    * The sparsity pattern of the global matrix, kept around if it
1752    * might be needed by future additions of the same type of matrix.
1753    */
1754   std::unique_ptr<SparsityPattern::Build> _sp;
1755 
1756   /**
1757    * The number of on-processor nonzeros in my portion of the
1758    * global matrix.  If need_full_sparsity_pattern is true, this will
1759    * just be a pointer into the corresponding sparsity pattern vector.
1760    * Otherwise we have to new/delete it ourselves.
1761    */
1762   std::vector<dof_id_type> * _n_nz;
1763 
1764   /**
1765    * The number of off-processor nonzeros in my portion of the
1766    * global matrix; allocated similar to _n_nz.
1767    */
1768   std::vector<dof_id_type> * _n_oz;
1769 
1770   /**
1771    * Total number of degrees of freedom.
1772    */
1773   dof_id_type _n_dfs;
1774 
1775   /**
1776    * The total number of SCALAR dofs associated to
1777    * all SCALAR variables.
1778    */
1779   dof_id_type _n_SCALAR_dofs;
1780 
1781 #ifdef LIBMESH_ENABLE_AMR
1782 
1783   /**
1784    * Total number of degrees of freedom on old dof objects
1785    */
1786   dof_id_type _n_old_dfs;
1787 
1788   /**
1789    * First old DOF index on processor \p p.
1790    */
1791   std::vector<dof_id_type> _first_old_df;
1792 
1793   /**
1794    * Last old DOF index (plus 1) on processor \p p.
1795    */
1796   std::vector<dof_id_type> _end_old_df;
1797 
1798   /**
1799    * First old DOF index for SCALAR variable v, or garbage for
1800    * non-SCALAR variable v
1801    */
1802   std::vector<dof_id_type> _first_old_scalar_df;
1803 
1804 #endif
1805 
1806 #ifdef LIBMESH_ENABLE_CONSTRAINTS
1807   /**
1808    * Data structure containing DOF constraints.  The ith
1809    * entry is the constraint matrix row for DOF i.
1810    */
1811   DofConstraints _dof_constraints, _stashed_dof_constraints;
1812 
1813   DofConstraintValueMap      _primal_constraint_values;
1814 
1815   AdjointDofConstraintValues _adjoint_constraint_values;
1816 #endif
1817 
1818 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
1819   /**
1820    * Data structure containing DofObject constraints.
1821    */
1822   NodeConstraints _node_constraints;
1823 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
1824 
1825 
1826 #ifdef LIBMESH_ENABLE_PERIODIC
1827   /**
1828    * Data structure containing periodic boundaries.  The ith
1829    * entry is the constraint matrix row for boundaryid i.
1830    */
1831   std::unique_ptr<PeriodicBoundaries> _periodic_boundaries;
1832 #endif
1833 
1834 #ifdef LIBMESH_ENABLE_DIRICHLET
1835   /**
1836    * Check that all the ids in dirichlet_bcids are actually present in the mesh.
1837    * If not, this will throw an error.
1838    */
1839   void check_dirichlet_bcid_consistency (const MeshBase & mesh,
1840                                          const DirichletBoundary & boundary) const;
1841   /**
1842    * Data structure containing Dirichlet functions.  The ith
1843    * entry is the constraint matrix row for boundaryid i.
1844    */
1845   std::unique_ptr<DirichletBoundaries> _dirichlet_boundaries;
1846 
1847   /**
1848    * Data structure containing Dirichlet functions.  The ith
1849    * entry is the constraint matrix row for boundaryid i.
1850    */
1851   std::vector<DirichletBoundaries *> _adjoint_dirichlet_boundaries;
1852 #endif
1853 
1854   friend class SparsityPattern::Build;
1855 
1856   /**
1857    * Bools to indicate if we override the --implicit_neighbor_dofs
1858    * commandline options.
1859    */
1860   bool _implicit_neighbor_dofs_initialized;
1861   bool _implicit_neighbor_dofs;
1862 };
1863 
1864 
1865 // ------------------------------------------------------------
1866 // Dof Map inline member functions
1867 inline
sys_number()1868 unsigned int DofMap::sys_number() const
1869 {
1870   return _sys_number;
1871 }
1872 
1873 
1874 
1875 inline
variable_group(const unsigned int g)1876 const VariableGroup & DofMap::variable_group (const unsigned int g) const
1877 {
1878   libmesh_assert_less (g, _variable_groups.size());
1879 
1880   return _variable_groups[g];
1881 }
1882 
1883 
1884 
1885 inline
variable(const unsigned int c)1886 const Variable & DofMap::variable (const unsigned int c) const
1887 {
1888   libmesh_assert_less (c, _variables.size());
1889 
1890   return _variables[c];
1891 }
1892 
1893 
1894 
1895 inline
variable_order(const unsigned int c)1896 Order DofMap::variable_order (const unsigned int c) const
1897 {
1898   libmesh_assert_less (c, _variables.size());
1899 
1900   return _variables[c].type().order;
1901 }
1902 
1903 
1904 
1905 inline
variable_group_order(const unsigned int vg)1906 Order DofMap::variable_group_order (const unsigned int vg) const
1907 {
1908   libmesh_assert_less (vg, _variable_groups.size());
1909 
1910   return _variable_groups[vg].type().order;
1911 }
1912 
1913 
1914 
1915 inline
variable_type(const unsigned int c)1916 const FEType & DofMap::variable_type (const unsigned int c) const
1917 {
1918   libmesh_assert_less (c, _variables.size());
1919 
1920   return _variables[c].type();
1921 }
1922 
1923 
1924 
1925 inline
variable_group_type(const unsigned int vg)1926 const FEType & DofMap::variable_group_type (const unsigned int vg) const
1927 {
1928   libmesh_assert_less (vg, _variable_groups.size());
1929 
1930   return _variable_groups[vg].type();
1931 }
1932 
1933 
1934 #ifdef LIBMESH_ENABLE_CONSTRAINTS
1935 
1936 
1937 inline
is_constrained_node(const Node * node)1938 bool DofMap::is_constrained_node (const Node *
1939 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
1940                                   node
1941 #endif
1942                                   ) const
1943 {
1944 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
1945   if (_node_constraints.count(node))
1946     return true;
1947 #endif
1948 
1949   return false;
1950 }
1951 
1952 
1953 inline
is_constrained_dof(const dof_id_type dof)1954 bool DofMap::is_constrained_dof (const dof_id_type dof) const
1955 {
1956   if (_dof_constraints.count(dof))
1957     return true;
1958 
1959   return false;
1960 }
1961 
1962 
1963 inline
has_heterogenous_adjoint_constraints(const unsigned int qoi_num)1964 bool DofMap::has_heterogenous_adjoint_constraints (const unsigned int qoi_num) const
1965 {
1966   AdjointDofConstraintValues::const_iterator it =
1967     _adjoint_constraint_values.find(qoi_num);
1968   if (it == _adjoint_constraint_values.end())
1969     return false;
1970   if (it->second.empty())
1971     return false;
1972 
1973   return true;
1974 }
1975 
1976 
1977 inline
has_heterogenous_adjoint_constraint(const unsigned int qoi_num,const dof_id_type dof)1978 Number DofMap::has_heterogenous_adjoint_constraint (const unsigned int qoi_num,
1979                                                     const dof_id_type dof) const
1980 {
1981   AdjointDofConstraintValues::const_iterator it =
1982     _adjoint_constraint_values.find(qoi_num);
1983   if (it != _adjoint_constraint_values.end())
1984     {
1985       DofConstraintValueMap::const_iterator rhsit =
1986         it->second.find(dof);
1987       if (rhsit == it->second.end())
1988         return 0;
1989       else
1990         return rhsit->second;
1991     }
1992 
1993   return 0;
1994 }
1995 
1996 
1997 
1998 inline
get_primal_constraint_values()1999 DofConstraintValueMap & DofMap::get_primal_constraint_values()
2000 {
2001   return _primal_constraint_values;
2002 }
2003 
2004 
2005 
2006 #else
2007 
2008 //--------------------------------------------------------------------
2009 // Constraint-specific methods get inlined into nothing if
2010 // constraints are disabled, so there's no reason for users not to
2011 // use them.
2012 
constrain_element_matrix(DenseMatrix<Number> &,std::vector<dof_id_type> &,bool)2013 inline void DofMap::constrain_element_matrix (DenseMatrix<Number> &,
2014                                               std::vector<dof_id_type> &,
2015                                               bool) const {}
2016 
constrain_element_matrix(DenseMatrix<Number> &,std::vector<dof_id_type> &,std::vector<dof_id_type> &,bool)2017 inline void DofMap::constrain_element_matrix (DenseMatrix<Number> &,
2018                                               std::vector<dof_id_type> &,
2019                                               std::vector<dof_id_type> &,
2020                                               bool) const {}
2021 
constrain_element_vector(DenseVector<Number> &,std::vector<dof_id_type> &,bool)2022 inline void DofMap::constrain_element_vector (DenseVector<Number> &,
2023                                               std::vector<dof_id_type> &,
2024                                               bool) const {}
2025 
constrain_element_matrix_and_vector(DenseMatrix<Number> &,DenseVector<Number> &,std::vector<dof_id_type> &,bool)2026 inline void DofMap::constrain_element_matrix_and_vector (DenseMatrix<Number> &,
2027                                                          DenseVector<Number> &,
2028                                                          std::vector<dof_id_type> &,
2029                                                          bool) const {}
2030 
heterogenously_constrain_element_matrix_and_vector(DenseMatrix<Number> &,DenseVector<Number> &,std::vector<dof_id_type> &,bool,int)2031 inline void DofMap::heterogenously_constrain_element_matrix_and_vector
2032   (DenseMatrix<Number> &, DenseVector<Number> &,
2033    std::vector<dof_id_type> &, bool, int) const {}
2034 
heterogenously_constrain_element_vector(const DenseMatrix<Number> &,DenseVector<Number> &,std::vector<dof_id_type> &,bool,int)2035 inline void DofMap::heterogenously_constrain_element_vector
2036   (const DenseMatrix<Number> &, DenseVector<Number> &,
2037    std::vector<dof_id_type> &, bool, int) const {}
2038 
constrain_element_dyad_matrix(DenseVector<Number> &,DenseVector<Number> &,std::vector<dof_id_type> &,bool)2039 inline void DofMap::constrain_element_dyad_matrix (DenseVector<Number> &,
2040                                                    DenseVector<Number> &,
2041                                                    std::vector<dof_id_type> &,
2042                                                    bool) const {}
2043 
constrain_nothing(std::vector<dof_id_type> &)2044 inline void DofMap::constrain_nothing (std::vector<dof_id_type> &) const {}
2045 
enforce_constraints_exactly(const System &,NumericVector<Number> *,bool)2046 inline void DofMap::enforce_constraints_exactly (const System &,
2047                                                  NumericVector<Number> *,
2048                                                  bool) const {}
2049 
enforce_adjoint_constraints_exactly(NumericVector<Number> &,unsigned int)2050 inline void DofMap::enforce_adjoint_constraints_exactly (NumericVector<Number> &,
2051                                                          unsigned int) const {}
2052 
2053 
enforce_constraints_on_residual(const NonlinearImplicitSystem &,NumericVector<Number> *,NumericVector<Number> const *,bool)2054 inline void DofMap::enforce_constraints_on_residual
2055   (const NonlinearImplicitSystem &,
2056    NumericVector<Number> *,
2057    NumericVector<Number> const *,
2058    bool) const {}
2059 
enforce_constraints_on_jacobian(const NonlinearImplicitSystem &,SparseMatrix<Number> *)2060 inline void DofMap::enforce_constraints_on_jacobian
2061   (const NonlinearImplicitSystem &,
2062    SparseMatrix<Number> *) const {}
2063 
2064 #endif // LIBMESH_ENABLE_CONSTRAINTS
2065 
2066 } // namespace libMesh
2067 
2068 #endif // LIBMESH_DOF_MAP_H
2069