7from .Solver
import Solver
8from .actionsets.CollocatedSolver.InitDofs
import InitDofsCollocated
9from .actionsets.CollocatedSolver.UpdateSolution
import UpdateSolution
10from .actionsets.CollocatedSolver.ResetAndUpdateResidual
import ResetAndUpdateResidual
11from .actionsets.PlotVertexDataInPeanoBlockFormat
import (
12 PlotVertexDataInPeanoBlockFormat,
15from abc
import abstractmethod
22 Matrix-free Collocated Solver for d-linear shape functions.
24 Mathematical and algorithmic descriptions are to follow later. For now,
25 we describe how to use this solver and a little about how it works under
28 Each vertex stores a certain number of values, given by the parameter
29 unknowns_per_vertex. In essence, if this parameter is more than one,
30 we are solving multiple different equations simultaneously, or we
31 can equivalently think of our PDE being vector-valued.
33 The user needs to provide an assembly matrix, and a mass matrix. If
34 our vector-valued PDE has \f$ K \f$ components, then each of these
35 matrices should be square, with \f$ K * 2^D \f$ rows.
37 In particular, they should be structured as block diagonals. Let
38 \f$ A_i \f$ be square with \f$ 2^D \f$ rows. Then the mass/assembly
39 matrices should be structured as follows:
41 \f$ diag( A_1, A_2, \dots A_K ) \f$.
43 During the actual solver step, we run through each equation one
44 after another, fetching the appropriate mass and assembly matrices
45 for the equation in hand.
47 At present, it hasn't been decided how to plot the output of multiple
48 equations, since only 1 is supported.
50 # Data held on the vertices
52 ## Solution (formerly named Value)
53 This array holds the actual solution which we later plot. This is updated when we touch a vertex
58 This array holds the right-hand side of the equation. We assign this in
59 experiment-specific implementation files.
62 This array holds the sum of the diagonals of the local assembly matrix. This is
63 set to 0 at the start of every solver step
66 This is used to store \f$ Mb - Ax \f$, i.e. the RHS multiplied by the matrix, and subtract
67 the solution multiplied by the assembly matrix.
73 After the grid is created, we run around the mesh and assign types to the vertices and cells.
76 - "Coarse" if the vertex is due to be refined
77 - "Interior" if it's not on the boundary
78 - "Boundary" if it is on the boundary
81 - "Coarse" if it's due to be refined
82 - Otherwise marked as "Interior"
86 There is only one action set in this solver. We do something non-trivial during touchCellFirstTime,
87 touchVertexFirstTime and touchVertexLastTime.
89 ### touchVertexFirstTime
91 We check that the Vertex is not a coarse grid vertex, then we set the residuals and the diagonals to 0.
93 ### touchCellFirstTime
95 All four vertices are in scope here. We create three vectors, each of length \f$ 2^D \f$ to hold
96 one value per vertex. For each vertex in the cell (regardless of whether it is on the boundary), we :
97 - Update the residual to be \f$ Mb - Ax \f$
98 - Increment the diagonal
100 ### touchVertexLastTime
101 We update the solution value (on all vertices) to be equal to the solution at the previous sweep, and we add on
102 \f$ \omega \times r / d \f$
103 where \f$ r \f$ and \f$ d \f$ stand for the residual and diagonal respectively.
105 # Enforcement of boundary conditions
110 We currently overcount the residual on vertices that are shared across boundaries. This isn't an issue at present,
111 since we only check for the max, which is unaffected by this bug. But something to fix at later date.
122 local_assembly_matrix,
123 local_assembly_matrix_scaling,
127 smoother_relaxation=0.6,
128 custom_init_actionset=None,
129 custom_plot_actionset=None,
130 custom_init_vertex="",
131 custom_boundary_conditions="",
132 enable_plotting=True,
133 plot_predicate="true",
137 Collocated low-order (d-linear) Finite Elements
140 super(CollocatedDLinearDiscretisationWithPointJacobi, self).
__init__(
146 matrix_dims = (2**dimensions) * unknowns_per_vertex
161 self.
_vertex_data.peano4_mpi_and_storage_aspect.merge_implementation = (
188 CollocatedDLinearDiscretisationWithPointJacobi, self
199 Tell the project's observer how to plot the data
201 Nothing fancy here. We add plotters from Peano's toolbox to visualise
202 solution and right-hand side.
206 observer.add_action_set(
211 observer.add_action_set(
219 observer.add_action_set(
234 Solution initialisation. We can either use the
235 standard initialisation procedure or pass in
236 another one when we instantiate this solver
247 descend_invocation_order = (
250 observer.add_action_set(
253 observer.add_action_set(
259 self, namespace, output, subdirectory="", abstract_overwrite=True
263 The solver creates two classes: An abstract base class and its
264 implementations. The abstract base class will be overwritten if
265 there is one in the directory. I pipe all the Python constants
266 into this base class, so they are available in the C++ code.
269 templatefile_prefix = (
270 os.path.dirname(os.path.realpath(__file__)) +
"/templates/"
272 templatefile_prefix += self.__class__.__name__
278 "SOLVER_INCLUDES":
"",
295 generated_abstract_header_file = (
297 templatefile_prefix +
".Abstract.template.h",
298 templatefile_prefix +
".Abstract.template.cpp",
307 generated_solver_files = (
309 templatefile_prefix +
".template.h",
310 templatefile_prefix +
".template.cpp",
320 output.add(generated_abstract_header_file)
321 output.add(generated_solver_files)
322 output.makefile.add_h_file(
323 subdirectory +
"Abstract" + self.
_name +
".h", generated=
True
325 output.makefile.add_h_file(subdirectory + self.
_name +
".h", generated=
True)
326 output.makefile.add_cpp_file(
327 subdirectory +
"Abstract" + self.
_name +
".cpp", generated=
True
329 output.makefile.add_cpp_file(subdirectory + self.
_name +
".cpp", generated=
True)
336 if( !marker.willBeRefined() ) {
338 // naive += with the diag
339 setDiag( getDiag() + neighbour.getDiag() );
341 // ditto for residual
342 setResidual( getResidual() + neighbour.getResidual() );
Specialisation of array using Peano's tarch.
Action set (reactions to events)
Matrix-free Collocated Solver for d-linear shape functions.
_abstract_solver_implementation_extras
add_to_init_solution(self, observer)
Solution initialisation.
_local_assembly_matrix_scaling
__init__(self, name, unknowns_per_vertex, dimensions, min_h, max_h, local_assembly_matrix, local_assembly_matrix_scaling, mass_matrix, mass_matrix_scaling, solver_tolerance, smoother_relaxation=0.6, custom_init_actionset=None, custom_plot_actionset=None, custom_init_vertex="", custom_boundary_conditions="", enable_plotting=True, plot_predicate="true")
Collocated low-order (d-linear) Finite Elements.
_unknowns_per_vertex_node
add_use_statements(self, observer)
This routine should still be called even if overwritten in child class.
add_implementation_files_to_project(self, namespace, output, subdirectory="", abstract_overwrite=True)
The solver creates two classes: An abstract base class and its implementations.
_custom_boundary_conditions
add_to_plot(self, observer)
Tell the project's observer how to plot the data.
add_to_Peano4_datamodel(self, datamodel, verbose)
add_to_solve(self, observer)
_abstract_solver_header_extras
get_vertex_merge_method(self)
add_to_create_grid(self, observer)
Abstract base class for matrix free solvers.
_abstract_solver_header_extras
_abstract_solver_implementation_extras
In touchVertexFirstTime, we set the type of vertex we see (either Interior, Boundary or Coarse),...
Action set implementing the core of the collocated solver.
This action set goes first, so that if we've done at least one sweep, we can update the solution base...