10from .Solver
import Solver
11from multigrid.petsc.api.actionsets.EnumerateDoFs
import EnumerateDoFs
12from multigrid.petsc.api.actionsets.InitVertexDoFs
import InitVertexDoFs
13from multigrid.petsc.api.actionsets.ProjectPETScSolutionBackOntoMesh
import ProjectPETScSolutionOnVerticesBackOntoMesh
15from abc
import abstractmethod
25 Trigger assembly of PETSc matrix and project rhs values from mesh onto rhs vector entries
28 TemplateTouchCellFirstTime =
"""
29 if (fineGridCell{{SOLVER_NAME}}PETScData.getType() == celldata::{{SOLVER_NAME}}PETScData::Type::Interior) {
30 //init a vector to collect global indices, and recall their position in the
31 //enumeration so we can apply the stencil correctly
32 std::vector<int> vertexIndices(TwoPowerD, -1);
34 for (int i=0; i<TwoPowerD ; i++) {
35 if (fineGridVertices{{SOLVER_NAME}}PETScData(i).getType() == vertexdata::{{SOLVER_NAME}}PETScData::Type::Interior) {
37 std::pair<int,int> localIndex = std::make_pair(_spacetreeId, fineGridVertices{{SOLVER_NAME}}PETScData(i).getUnknownBaseNumber());
38 int globalIndex = repositories::{{SOLVER_INSTANCE}}.getLocalToGlobalMap().getGlobalIndex(localIndex, ::petsc::LocalToGlobalMap::Type::Vertex);
39 vertexIndices[i] = globalIndex;
44 auto lhsMatrixEntry = repositories::{{SOLVER_INSTANCE}}.getLhsMatrix(marker.x(),marker.h());
46 for (int d=0; d<{{VERTEX_CARDINALITY}}; d++)
48 for (int i=0; i<TwoPowerD; i++) {
49 for (int j=0; j<TwoPowerD; j++) {
50 if (vertexIndices[i] != -1 and vertexIndices[j] != -1) {
51 repositories::{{SOLVER_INSTANCE}}.getLinearEquationSystem().increment(
52 vertexIndices[i] + d, //d for dof
54 lhsMatrixEntry(d*TwoPowerD+i,d*TwoPowerD+j)
61 auto rhs = repositories::{{SOLVER_INSTANCE}}.getRhsMatrix(marker.x(),marker.h());
62 for (int i=0; i<TwoPowerD; i++) {
63 logTraceInWith2Arguments( "touchCellFirstTime::RHS", marker.toString(), rhs );
64 if (fineGridVertices{{SOLVER_NAME}}PETScData(i).getType() == vertexdata::{{SOLVER_NAME}}PETScData::Type::Interior) {
65 double rhsContribution = 0.0;
66 for (int j=0; j<TwoPowerD; j++) {
67 double rhsValue = fineGridVertices{{SOLVER_NAME}}(j).getRhs(d);
70 we call d*TwoPowerD+i here because the rhs matrix typically has dimensions
71 TwoPowerD x TwoPowerD. When we promote to n unknowns, we make the matrix
72 larger: n*TwoPowerD x n*TwoPowerD. So, we call d*TwoPowerD+i so that we can
73 skip past the parts of the matrix we are no longer interested in.
75 rhsContribution += rhs(d*TwoPowerD+i,d*TwoPowerD+j) * rhsValue;
76 logTraceInWith3Arguments("AssembleRhs", rhs(d*TwoPowerD+i,d*TwoPowerD+j), rhsContribution, rhsValue);
77 logTraceOut("AssembleRhs");
79 repositories::{{SOLVER_INSTANCE}}.getLinearEquationSystem().increment(
87 logTraceOut( "touchCellFirstTime::RHS" );
91 TemplateTouchVertexFirstTime=
"""
92 //here we send the value, rhs from the mesh to petsc
94 if (fineGridVertex{{SOLVER_NAME}}PETScData.getType() == vertexdata::{{SOLVER_NAME}}PETScData::Type::Interior) {
95 //first, get global index
96 std::pair<int,int> localIndex = std::make_pair(_spacetreeId, fineGridVertex{{SOLVER_NAME}}PETScData.getUnknownBaseNumber());
97 int globalIndex = repositories::{{SOLVER_INSTANCE}}.getLocalToGlobalMap().getGlobalIndex(localIndex, ::petsc::LocalToGlobalMap::Type::Vertex);
99 assertion3(globalIndex>=0, globalIndex, marker.toString(), fineGridVertex{{SOLVER_NAME}}PETScData.toString() );
101 for (int i=0; i<{{VERTEX_CARDINALITY}}; i++)
103 //get the rhs that was present in the mesh
104 double rhs = fineGridVertex{{SOLVER_NAME}}.getRhs(i);
106 //send these to petsc
107 repositories::{{SOLVER_INSTANCE}}.getLinearEquationSystem().insert(globalIndex + i, rhs);
118Initialise vertex-associated degrees of freedom
120The initialisation requires a solver object, as we have to know what C++
121object this solver will produce.
123solver: petsc.solvers.CollocatedLowOrderDiscretisation or similar solver where
124 degrees of freedom are assigned exclusively to the vertices.
128 super( AssemblePetscMatrix, self ).
__init__()
130 self.
d[
"SOLVER_INSTANCE"] = solver.instance_name()
131 self.
d[
"SOLVER_NAME"] = solver.typename()
132 self.
d[
"VERTEX_CARDINALITY"] = solver.number_of_matrix_entries_per_vertex
137Provide C++ code snippet for peano4.solversteps.ActionSet.OPERATION_TOUCH_VERTEX_FIRST_TIME
138Provide C++ code snippet for peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME
140Only touchVertexFirstTime is an event where this action set actually
141does something: It inserts the template TemplateTouchVertexFirstTime and
142replaces it with entries from the dictionary. The latter is befilled
145We actually do something during touchVertexFirstTime and touchCellFirstTime. We insert the
146appropriate template into each.
150 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
153 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_VERTEX_FIRST_TIME:
162 Configure name of generated C++ action set
164 This action set will end up in the directory observers with a name that
165 reflects how the observer (initialisation) is mapped onto this action
166 set. The name pattern is ObserverName2ActionSetIdentifier where this
167 routine co-determines the ActionSetIdentifier. We make is reflect the
171 return __name__.replace(
".py",
"").replace(
".",
"_")
177 The action set that Peano will generate that corresponds to this class
178 should not be modified by users and can safely be overwritten every time
179 we run the Python toolkit.
188Consult petsc.Project for details
192#include "repositories/SolverRepository.h"
193#include "tarch/la/Matrix.h"
208Define body of constructor
214 _spacetreeId = treeNumber;
222 This is one of the simplest solvers that you can think of. It places
223 one degree of freedom (can be scalar or a vector) on each vertex. As
224 we support solely element-wise assembly, this means you can implement
225 things like a 9-point (2d) or 27-point (3d) stencil, but not really
226 anything more sophisticated.
228 cell_lhs_matrix: [double] or []
229 Pass in [] if you prefer to assemble the matrix per cell yourself.
231 cell_rhs_matrix: [double] or []
232 Pass in [] if you prefer to assemble the matrix per cell yourself.
234 cell_lhs_matrix_scaling: Positive integer
235 The lhs matrix is scaled with @f$ h^x @f$ where the x is defined by this
236 parameter. If you don't specify an lhs matrix, i.e. you prefer to inject
237 this matrix manually, you can leave this parameter None, as it is not
240 cell_rhs_matrix_scaling: Positive integer
241 The rhs matrix is scaled with @f$ h^x @f$ where the x is defined by this
242 parameter. If you don't specify a rhs matrix, i.e. you prefer to inject
243 this matrix manually, you can leave this parameter None, as it is not
255 cell_lhs_matrix_scaling,
256 cell_rhs_matrix_scaling,
260 Collocated low-order (d-linear) Finite Elements
263 super( CollocatedLowOrderDiscretisation, self ).
__init__( name,
292 Tell the project's observer how to plot the data
294 Nothing fancy here. We add plotters from Peano's toolbox to visualise
295 solution and right-hand side.
298 observer.add_action_set( peano4.toolbox.PlotVertexDataInPeanoBlockFormat(
299 filename =
"solution-" + self.
_name,
301 getter =
"getValue().data()",
303 time_stamp_evaluation = peano4.toolbox.PlotVertexDataInPeanoBlockFormat.CountTimeSteps,
304 number_of_unknows_per_vertex = self.
_unknowns,
305 guard_predicate =
"true",
307 observer.add_action_set( peano4.toolbox.PlotVertexDataInPeanoBlockFormat(
308 filename =
"rhs-" + self.
_name,
310 getter =
"getRhs().data()",
312 time_stamp_evaluation = peano4.toolbox.PlotVertexDataInPeanoBlockFormat.CountTimeSteps,
313 number_of_unknows_per_vertex = self.
_unknowns,
314 guard_predicate =
"true",
327 Solution initialisation
329 Close to trivial: Just add the action set petsc.actionsets.InitVertexDoFs
333 observer.add_action_set( EnumerateDoFs(self,
True,
False) )
334 observer.add_action_set( InitVertexDoFs(self) )
348 observer.add_action_set( ProjectPETScSolutionOnVerticesBackOntoMesh(self) )
355 The solver creates two classes: An abstract base class and its
356 implementations. The abstract base class will be overwritten if
357 there is one in the directory. I pipe all the Python constants
358 into this base class, so they are available in the C++ code.
360 The implementation file will not be overwritten, as I assume that
361 the users will write their own domain-specific stuff in there. If
362 it does not exist yet, I'll create an empty stub which can be
363 befilled with something meaningful.
365 Besides the creation of these two files, I also add the files to the
366 project artifacts and the makefile, so they are captured by the build
370 templatefile_prefix = os.path.dirname( os.path.realpath(__file__) ) +
"/"
371 templatefile_prefix += self.__class__.__name__
377 "SOLVER_INCLUDES":
"",
389 templatefile_prefix +
".Abstract.template.h",
390 templatefile_prefix +
".Abstract.template.cpp",
398 templatefile_prefix +
".template.h",
399 templatefile_prefix +
".template.cpp",
407 output.add( generated_abstract_header_file )
408 output.add( generated_solver_files )
409 output.makefile.add_h_file( subdirectory +
"Abstract" + self.
_name +
".h", generated=
True )
410 output.makefile.add_h_file( subdirectory + self.
_name +
".h", generated=
True )
411 output.makefile.add_cpp_file( subdirectory +
"Abstract" + self.
_name +
".cpp", generated=
True )
412 output.makefile.add_cpp_file( subdirectory + self.
_name +
".cpp", generated=
True )
420 Nothing is associated with the vertex. There's nothing to be done here.
429 In the DG scheme, we have a projection from the left and we have a
430 projection from the right. These values are proper projections, i.e.
431 they do not carry any semantics. Then we have to solve the Riemann
432 problem, and need one more unknown to store the outcome of that one.
441 This is the actual unknowns per cell
Trigger assembly of PETSc matrix and project rhs values from mesh onto rhs vector entries.
user_should_modify_template(self)
The action set that Peano will generate that corresponds to this class should not be modified by user...
get_constructor_body(self)
Define body of constructor.
get_action_set_name(self)
Configure name of generated C++ action set.
str TemplateTouchCellFirstTime
str TemplateTouchVertexFirstTime
get_body_of_operation(self, operation_name)
Provide C++ code snippet for peano4.solversteps.ActionSet.OPERATION_TOUCH_VERTEX_FIRST_TIME Provide...
get_includes(self)
Consult petsc.Project for details.
__init__(self, solver)
Initialise vertex-associated degrees of freedom.
get_attributes(self)
Return attributes as copied and pasted into the generated class.
This is one of the simplest solvers that you can think of.
add_use_statements(self, observer)
Register the index numbers to be used in each and every mesh traversal.
add_to_plot(self, observer)
Tell the project's observer how to plot the data.
number_of_matrix_entries_per_vertex(self)
Nothing is associated with the vertex.
number_of_matrix_entries_per_vertex
add_to_enumerate_and_init_solution(self, observer)
Solution initialisation.
add_to_init_petsc(self, observer)
Add whatever action set you want to use here.
add_to_Peano4_datamodel(self, datamodel, verbose)
Initialise index model.
number_of_matrix_entries_per_face(self)
In the DG scheme, we have a projection from the left and we have a projection from the right.
add_to_create_grid(self, observer)
Add whatever action set you want to use to observer.
add_to_assemble(self, observer)
Add whatever action set you want to use to observer.
add_implementation_files_to_project(self, namespace, output, subdirectory="")
The solver creates two classes: An abstract base class and its implementations.
add_to_map_solution_onto_mesh(self, observer)
Add whatever action set you want to use to observer.
number_of_matrix_entries_per_cell(self)
This is the actual unknowns per cell.
__init__(self, name, unknowns, dimensions, min_h, max_h, cell_lhs_matrix, cell_rhs_matrix, cell_lhs_matrix_scaling, cell_rhs_matrix_scaling)
Collocated low-order (d-linear) Finite Elements.
Abstract base class for all PETSc solvers.
number_of_matrix_entries_per_vertex(self)
Specialisation of array using Peano's tarch.
Default superclass for any data model in Peano which is stored within the grid.
Action set (reactions to events)