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;
219class CollocatedLowOrderDiscretisation(
Solver):
222 \page petsc_collocated_solver Collocated Solver with PETSc
224 This is one of the simplest solvers that you can think of. It places
225 one degree of freedom (can be scalar or a vector) on each vertex. As
226 we support solely element-wise assembly, this means you can implement
227 things like a 9-point (2d) or 27-point (3d) stencil, but not really
228 anything more sophisticated.
230 cell_lhs_matrix: [double] or []
231 Pass in [] if you prefer to assemble the matrix per cell yourself.
233 cell_rhs_matrix: [double] or []
234 Pass in [] if you prefer to assemble the matrix per cell yourself.
236 cell_lhs_matrix_scaling: Positive integer
237 The lhs matrix is scaled with @f$ h^x @f$ where the x is defined by this
238 parameter. If you don't specify an lhs matrix, i.e. you prefer to inject
239 this matrix manually, you can leave this parameter None, as it is not
242 cell_rhs_matrix_scaling: Positive integer
243 The rhs matrix is scaled with @f$ h^x @f$ where the x is defined by this
244 parameter. If you don't specify a rhs matrix, i.e. you prefer to inject
245 this matrix manually, you can leave this parameter None, as it is not
257 cell_lhs_matrix_scaling,
258 cell_rhs_matrix_scaling,
262 Collocated low-order (d-linear) Finite Elements
265 super( CollocatedLowOrderDiscretisation, self ).
__init__( name,
269 self._unknowns = unknowns
274 self.cell_lhs_matrix = cell_lhs_matrix
275 self.cell_rhs_matrix = cell_rhs_matrix
276 self.cell_lhs_matrix_scaling = cell_lhs_matrix_scaling
277 self.cell_rhs_matrix_scaling = cell_rhs_matrix_scaling
281 def add_to_Peano4_datamodel( self, datamodel, verbose ):
282 super( CollocatedLowOrderDiscretisation, self ).add_to_Peano4_datamodel(datamodel,verbose)
283 datamodel.add_vertex(self._vertex_pde_data)
286 def add_use_statements(self, observer):
287 super( CollocatedLowOrderDiscretisation, self ).add_use_statements(observer)
288 observer.use_vertex( self._vertex_pde_data )
291 def add_to_plot(self, observer):
294 Tell the project's observer how to plot the data
296 Nothing fancy here. We add plotters from Peano's toolbox to visualise
297 solution and right-hand side.
301 filename =
"solution-" + self._name,
302 vertex_unknown = self._vertex_pde_data,
303 getter =
"getValue().data()",
305 time_stamp_evaluation = peano4.toolbox.PlotVertexDataInPeanoBlockFormat.CountTimeSteps,
306 number_of_unknows_per_vertex = self._unknowns,
307 guard_predicate =
"true",
310 filename =
"rhs-" + self._name,
311 vertex_unknown = self._vertex_pde_data,
312 getter =
"getRhs().data()",
314 time_stamp_evaluation = peano4.toolbox.PlotVertexDataInPeanoBlockFormat.CountTimeSteps,
315 number_of_unknows_per_vertex = self._unknowns,
316 guard_predicate =
"true",
321 def add_to_create_grid(self, observer):
326 def add_to_enumerate_and_init_solution(self, observer):
329 Solution initialisation
331 Close to trivial: Just add the action set petsc.actionsets.InitVertexDoFs
335 observer.add_action_set( EnumerateDoFs(self,
True,
False) )
336 observer.add_action_set( InitVertexDoFs(self) )
340 def add_to_assemble(self, observer):
345 def add_to_init_petsc(self, observer):
349 def add_to_map_solution_onto_mesh(self, observer):
350 observer.add_action_set( ProjectPETScSolutionOnVerticesBackOntoMesh(self) )
354 def add_implementation_files_to_project(self, namespace, output, subdirectory=""):
357 The solver creates two classes: An abstract base class and its
358 implementations. The abstract base class will be overwritten if
359 there is one in the directory. I pipe all the Python constants
360 into this base class, so they are available in the C++ code.
362 The implementation file will not be overwritten, as I assume that
363 the users will write their own domain-specific stuff in there. If
364 it does not exist yet, I'll create an empty stub which can be
365 befilled with something meaningful.
367 Besides the creation of these two files, I also add the files to the
368 project artifacts and the makefile, so they are captured by the build
372 templatefile_prefix = os.path.dirname( os.path.realpath(__file__) ) +
"/"
373 templatefile_prefix += self.__class__.__name__
379 "SOLVER_INCLUDES":
"",
382 "CELL_LHS_MATRIX": self.cell_lhs_matrix,
383 "CELL_RHS_MATRIX": self.cell_rhs_matrix,
384 "VERTEX_CARDINALITY": self.number_of_matrix_entries_per_vertex,
385 "CELL_LHS_MATRIX_SCALING": self.cell_lhs_matrix_scaling,
386 "CELL_RHS_MATRIX_SCALING": self.cell_rhs_matrix_scaling,
387 "SOLVER_NAME": self.typename(),
391 templatefile_prefix +
".Abstract.template.h",
392 templatefile_prefix +
".Abstract.template.cpp",
393 "Abstract" + self.typename(),
400 templatefile_prefix +
".template.h",
401 templatefile_prefix +
".template.cpp",
409 output.add( generated_abstract_header_file )
410 output.add( generated_solver_files )
411 output.makefile.add_h_file( subdirectory +
"Abstract" + self._name +
".h", generated=
True )
412 output.makefile.add_h_file( subdirectory + self._name +
".h", generated=
True )
413 output.makefile.add_cpp_file( subdirectory +
"Abstract" + self._name +
".cpp", generated=
True )
414 output.makefile.add_cpp_file( subdirectory + self._name +
".cpp", generated=
True )
419 def number_of_matrix_entries_per_vertex(self):
422 Nothing is associated with the vertex. There's nothing to be done here.
425 return self._unknowns
428 def number_of_matrix_entries_per_face(self):
431 In the DG scheme, we have a projection from the left and we have a
432 projection from the right. These values are proper projections, i.e.
433 they do not carry any semantics. Then we have to solve the Riemann
434 problem, and need one more unknown to store the outcome of that one.
440 def number_of_matrix_entries_per_cell(self):
443 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.
Abstract base class for all PETSc solvers.
Specialisation of dastgen2.attributes.DoubleArray which relies on Peano's tarch.
Default superclass for any data model in Peano which is stored within the grid.
Action set (reactions to events)