From: wolf
-which does exactly what it says. This function accepts a list of pairs
-of boundary indicators and the according functions and returns a list of
+which does exactly what it says. This function accepts a number
+describing which part of the boundary we want to consider
+and the according function which shall be interpolated on that portion
+of the boundary. It returns a list of
pairs of degrees of freedom numbers and values denoting the respective
Dirichlet boundary values.
dof
and the corresponding fi
element fe
.
+ // this will hold the boundary value for
+ // the degrees of freedom on the boundary
+ // part with number '0'
map<int,double> boundary_values;
-DoFHandler<2>::FunctionMap dirichlet_bc;
-BoundaryFct bfct;
-dirichlet_bc[0]=&bfct;
-VectorTools<2>::interpolate_boundary_values(dof,dirichlet_bc,fe,boundary,boundary_values);
-u.reinit(f.size());
-MatrixTools<2>::apply_boundary_values(boundary_values,A,u,f);
+ // and this is some user-defined function
+ // describing the boundary values
+BoundaryFunction<dim> boundary_function;
+ // interpolate the DoFs on boundary
+ // portion '0':
+VectorTools<dim>::interpolate_boundary_values
+ (dof_handler,
+ 0, boundary_function,
+ boundary_values);
+
+ // set solution vector to the right size
+u.reinit(dof_handler.n_dofs());
+ // we assume that the global matrix and
+ // right hand side have already been
+ // assembled.
+
+ // now insert the boundary values into
+ // the linear system of equations:
+MatrixTools<dim>::apply_boundary_values
+ (boundary_values,
+ A, u, f);
-First, we need a few definitions: -
-boundary_values
maps DoF indices at the boundary computed by interpolate_boundary_values
to their respective values.
-dirichlet_bc
maps boundary indicators to boundary functions, supplied by us. All boundary indicators are zero by default, therefore the
-above statement maps the same function to all the boundaries. The boundary functions compute the boundary values.
-bfct
is a function returning cos(2*PI*x)*sin(2*PI*y)
-
, thereby supplying boundary values.
--This may seem a bit confusing. What actually happens is the following: -
-interpolate_boundary_values
takes the boundary functions
-bfct
, its relation to boundaries dirichlet_bc
and
-the triangulation dof, fe
and returns a
-mapping boundary_values
that maps values instead of functions
-to our boundaries. The function looks at all the boundaries the index
-of which is listed in dirichlet_bc
(in this example, all
-the boundaries with indicator 0). All we
-ever need to do is specify the initial triangulation.
-apply_boundary_values
subsequently takes that mapping and
-our system of equations Au=f and inserts the boundary values into
-the system of equations which can then be solved.
-interpolate_boundary_values
with
+different boundary indicators (the '0'
above) and
+respective functions. Since the function does not clear the contents
+of the map, you may use it for each of this successive calls and pass
+only the final object to apply_boundary_values
.
diff --git a/deal.II/doc/tutorial/chapter-1.elements/matrix_generation.html b/deal.II/doc/tutorial/chapter-1.elements/matrix_generation.html
index a5814d232c..d76fd45fd4 100644
--- a/deal.II/doc/tutorial/chapter-1.elements/matrix_generation.html
+++ b/deal.II/doc/tutorial/chapter-1.elements/matrix_generation.html
@@ -21,12 +21,12 @@
-There are several kinds of matrices we will deal with: +There are several kinds of matrices which we will deal with:
-The full matrix is assumed to have mostly cells of non-zero value.
-Therefore it consumes a lot of memory, much more than the other matrix types.
-It is initialized using FullMatrix::reinit(const unsigned
-int rows, const unsigned int cols)
.
+The full matrix is useful is we can assume that the we have mostly
+entries of non-zero value. Since we then store all entries, it
+consumes a lot of memory, much more than the other matrix types. It
+is initialized using FullMatrix::reinit(const unsigned int rows,
+const unsigned int cols)
.
@@ -93,20 +94,23 @@ appropriate places. This example initializes a sparse square matrix structure. const unsigned int dim=2; // For example -SparseMatrixStruct<double> sparsity_pattern; +SparseMatrixStruct sparsity_pattern; SparseMatrix<double> sparse_matrix; -DoFHandler<dim> dof; +DoFHandler<dim> dof_handler; // Your degrees of freedom must already be distributed -sparsity_pattern.reinit(dof.n_dofs(),dof.n_dofs(),dof.max_couplings_between_dofs()); +sparsity_pattern.reinit (dof_handler.n_dofs(), + dof_handler.n_dofs(), + dof_handler.max_couplings_between_dofs()); // If your grid is locally refined, condense the hanging nodes into the // structure. sparsity_pattern.compress(); -sparse_matrix.reinit(sparsity_pattern); +// initialize the actual matrix with the sparsity pattern +sparse_matrix.reinit (sparsity_pattern); @@ -114,10 +118,18 @@ sparse_matrix.reinit(sparsity_pattern);
-Vector operations are supplied by the class
-Vector
.
-The first and most important operation on a vector is its initialization
-using void Vector::reinit(const usigned int N, const bool fast=false)
.
+Vector operations are supplied by the class Vector
.
+The first and most important operation on a vector is its
+initialization using void Vector::reinit(const usigned int N,
+const bool fast=false)
, which resets the vector's size to
+N
and sets all elements to zero. If the second parameter
+fast
is set true, this means that the entries will not be
+cleared; this is useful if the vector is being assigned to immediately
+after, in which case an initialization with zeroes would be
+redundant. Note that this mode of use is rather uncommon and mostly
+only useful inside linear solvers where it is important to save as
+much computing time as possible.
@@ -148,6 +160,75 @@ f.reinit(dof.n_dofs()); +
reinit
functions of
+all vector and matrix classes are implemented in a way to only allow
+the allocated memory to grow, since this reduces the number of times
+allocation and de-allocation has to happen, and in addition reduces
+memory fragmentation.
+
++One immediate consequence is that if you write +
+
+Vector<double> f;
+f.reinit(100);
+f.reinit(50);
+
+
+then the second reinit
will only have the effect of
+reducing the internal size of the vector, but the memory that is no
+more needed will not be released. Likewise, if you later write
+
+
+f.reinit(100);
+
+
+this will again only set the size of the vector to a different value,
+but since enough memory is still allocated, no re-allocation has to
+happen. Only if the required number of entries exceeds the memory
+already allocated, will there be a re-allocation.
+
+
+All matrix and vector classes in deal.II work this
+way, and in fact this is also the way the standard C++ container
+classes like vector
or map
work.
+However, this is not very useful if you use vectors or matrices
+as member variables, since at times they may not be used at all if
+your program works on other objects or you are in other parts of the
+object. You would then like to let the vectors and matrices sleep with
+no memory presently lying around unused. For this purpose, all
+matrices and vectors support a mode of their reinit
+function which frees all memory that is presently allocated: just call
+it with parameters such that the new size is zero. For example, the
+following lines will release all memory from their objects:
+
+
+f.reinit(0);
+full_matrix.reinit(0,0);
+sparse_matrix_struct.reinit (0,0);
+sparse_matrix.reinit (sparse_matrix_struct);
+
+
+Note that in the last line, you have to pass an empty sparsity pattern
+to the sparse matrix to tell it to release all of its memory.
+
+
+clear
function. These, however, work differently than
+might be expected from the analogous functions in the C++ standard
+library. There, clear
removes all data from the objects
+and resets it into a virgin state. In deal.II,
+clear
only resets the values of a metrix or vector to
+zero, but does not change the size and does no re-allocation
+either. This unfortunate name clash is due to historical reasons.
+