13 Prepare CG solver for coupling and ensure that both solvers are invoked in the correct order
15 Throughtout the mesh traversal steps from coarse to fine grid (descend), the
16 DG solver is to be executed before(!) the CG solver. It is the DG solver
17 which we equip with a preprocessing step, so we know that we are on the safe
20 We also introduce a new helper value for the CG solver: newValue has,
21 after each traversal, the injected value of the solution. We can then roll
22 it over if we aim for a FAS-type implementation. Further to that, we have
23 the solvers new rhs, which we again use for the next iteration, and its
24 previous (old) value which we use to compute the delta.
26 @see AbstractDGCGCoupling for a description of where the individual values are used.
29 assert cg_solver._unknowns_per_vertex_node==dg_solver._unknowns_per_cell_node
40 Couple the solution and updates of two different solvers
45 This action set has to be used as a preprocessing step of the CG:
47 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
48 solver.preprocessing_action_set = mghype.matrixfree.solvers.api.actionsets.AbstractDGCGCoupling(
52 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
54 I recommend not to use the coupling directly, but one of its subclasses.
59 We have a new variable SumOfInjectedValues. This one is set to zero at the end
60 of touchVertexFirstTime(), i.e. at the begin of a mesh sweep. In each fine
61 grid cell, i.e. each cell carrying a DG polynomial, we evaluate this
62 polynomial's value in the @f$ 2^d @f$ vertices (corners) of the cell. Of
63 these values, we restrict @f$ 2^{=-d} @f$th of its value to the next coarser
64 mesh level. Prior to the start of a new mesh sweep, SumOfInjectedValues holds
65 the average value of the solution in a vertex. This is just before we
66 clear it again, i.e. we can plug into touchVertexFirstTime() just before we
67 clear this field to read our a coarsened representation of the solution at
74 This class takes the solution of a DG solver and injects the current solution
75 onto the vertices. For this, it simply averages the @f$ 2^d @f$ different
76 values of the DG polynomials into the vertex. We do this only for unrefined
79 To realise this behaviour, we rely on functions held within
80 AbstractDGCGCoupling.h.
81 It is important that prepare_and_order_DG_CG_solvers() has been invoked for
82 the two solvers whenever we use this action set.
87 __TemplateTouchVertexFirstTime=
"""
89 fineGridVertex{{CG_SOLVER_NAME}}.getType() != vertexdata::{{CG_SOLVER_NAME}}::Type::Coarse
92 if ({{PREDICATE_INJECT_AND_RESTRICT}}) {
93 mghype::matrixfree::solvers::dgcgcoupling::rollOverAndPrepareCGVertex(
94 fineGridVertex{{CG_SOLVER_NAME}},
95 true, // restrictRhsAndInjectSolution
102 We aim to visit this section just before we prolongate. Passing false to
103 restrictRhsAndInjectSolution has the effect of setting delta to the "value"
104 parameter, ie we pick up the final solution to be interpolated during
107 else if ( {{PREDICATE_PROLONGATE}} ) {
108 mghype::matrixfree::solvers::dgcgcoupling::rollOverAndPrepareCGVertex(
109 fineGridVertex{{CG_SOLVER_NAME}},
110 false, // restrictRhsAndInjectSolution
118 templateTouchCellFirstTime=
"""
119 // ============================
121 // ============================
122 const double additiveMultigridRelaxation = 0.0;
124 fineGridCell{{DG_SOLVER_NAME}}.getType() != celldata::{{DG_SOLVER_NAME}}::Type::Coarse
126 {{PREDICATE_PROLONGATE}}
128 logTraceInWith2Arguments("Prolongate()", (bool)({{PREDICATE_PROLONGATE}}), fineGridCell{{DG_SOLVER_NAME}}.toString());
129 constexpr int Cols = TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns;
130 constexpr int Rows = {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode;
132 static std::vector< tarch::la::Matrix< Rows, Cols, double > > matrices = {
133 {% for MATRIX in PROLONGATION_MATRIX %}
135 {{MATRIX[0]| join(", ")}}
136 {% for ROW in MATRIX[1:] %}
137 ,{{ROW | join(", ")}}
143 {% if PROLONGATION_MATRIX_SCALING is not defined %}
144 #error No scaling for prolongation matrix available.
147 static std::vector<int> scaleFactors = {
148 {% for el in PROLONGATION_MATRIX_SCALING %}
153 tarch::la::Matrix< Rows, Cols, double > composedProlongationMatrix = ::mghype::composeMatrixFromHWeightedLinearCombination( matrices, scaleFactors, marker.h() );
155 fineGridCell{{DG_SOLVER_NAME}}.setSolution(
156 mghype::matrixfree::solvers::dgcgcoupling::prolongate<{{DG_SOLVER_NAME}}, {{CG_SOLVER_NAME}}>(
157 composedProlongationMatrix,
158 fineGridCell{{DG_SOLVER_NAME}}.getSolution(),
159 fineGridVertices{{CG_SOLVER_NAME}}
162 logTraceOutWith1Argument("Prolongate()", fineGridCell{{DG_SOLVER_NAME}}.toString());
168 __TemplateTouchCellLastTime_FAS=
"""
170 fineGridCell{{DG_SOLVER_NAME}}.getType() != celldata::{{DG_SOLVER_NAME}}::Type::Coarse
172 {{PREDICATE_EVALUATE_RHS}}
174 assertionEquals( {{CG_SOLVER_NAME}}::VertexUnknowns, {{DG_SOLVER_NAME}}::UnknownsPerCellNode );
176 // ==========================================
177 // compute and restrict hierarchical residual
178 // ==========================================
180 static std::vector< tarch::la::Matrix< {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode, TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns, double > > prolongationMatrices = {
181 {% for MATRIX in PROLONGATION_MATRIX %}
183 {{MATRIX[0]| join(", ")}}
184 {% for ROW in MATRIX[1:] %}
185 ,{{ROW | join(", ")}}
191 {% if PROLONGATION_MATRIX_SCALING is not defined %}
192 #error No scaling for injection matrix available.
195 static std::vector<int> prolongationMatricesScaleFactors = {
196 {% for el in PROLONGATION_MATRIX_SCALING %}
201 tarch::la::Matrix< {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode, TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns, double > composedProlongationMatrix = ::mghype::composeMatrixFromHWeightedLinearCombination( prolongationMatrices, prolongationMatricesScaleFactors, marker.h() );
203 static std::vector< tarch::la::Matrix< TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns, {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode, double > > restrictionMatrices = {
204 {% for MATRIX in RESTRICTION_MATRIX %}
206 {{MATRIX[0]| join(", ")}}
207 {% for ROW in MATRIX[1:] %}
208 ,{{ROW | join(", ")}}
214 {% if RESTRICTION_MATRIX_SCALING is not defined %}
215 #error No scaling for injection matrix available.
218 static std::vector<int> restrictionMatricesScaleFactors = {
219 {% for el in INJECTION_MATRIX_SCALING %}
224 tarch::la::Matrix< TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns, {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode, double > composedRestrictionMatrix = ::mghype::composeMatrixFromHWeightedLinearCombination( restrictionMatrices, restrictionMatricesScaleFactors, marker.h() );
226 mghype::matrixfree::solvers::dgcgcoupling::computeAndRestrictHierarchicalResidual<{{DG_SOLVER_NAME}}, {{CG_SOLVER_NAME}}>(
227 composedProlongationMatrix,
228 composedRestrictionMatrix,
229 repositories::{{DG_SOLVER_INSTANCE}}.getMassMatrix( marker.x(), marker.h() ),
230 repositories::{{DG_SOLVER_INSTANCE}}.getLocalAssemblyMatrix(marker.x(), marker.h()),
231 fineGridCell{{DG_SOLVER_NAME}}.getSolution(),
232 fineGridCell{{DG_SOLVER_NAME}}.getRhs(),
233 fineGridVertices{{CG_SOLVER_NAME}}
237 // ============================
238 // inject solution back (accumulation)
239 // ============================
241 constexpr int Rows = TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns;
242 constexpr int Cols = {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode;
244 static std::vector< tarch::la::Matrix< Rows, Cols, double > > injectionMatrices = {
245 {% for MATRIX in INJECTION_MATRIX %}
247 {{MATRIX[0]| join(", ")}}
248 {% for ROW in MATRIX[1:] %}
249 ,{{ROW | join(", ")}}
255 {% if INJECTION_MATRIX_SCALING is not defined %}
256 #error No scaling for injection matrix available.
259 static std::vector<int> injectionMatricesScaleFactors = {
260 {% for el in INJECTION_MATRIX_SCALING %}
265 tarch::la::Matrix< Rows, Cols, double > composedInjectionMatrix = ::mghype::composeMatrixFromHWeightedLinearCombination( injectionMatrices, injectionMatricesScaleFactors, marker.h() );
267 mghype::matrixfree::solvers::dgcgcoupling::injectSolution<{{DG_SOLVER_NAME}}, {{CG_SOLVER_NAME}}>(
268 composedInjectionMatrix,
269 fineGridCell{{DG_SOLVER_NAME}}.getSolution(),
270 fineGridVertices{{CG_SOLVER_NAME}}
277 mghype::matrixfree::solvers::dgcgcoupling::updateRestrictionCounters(
278 fineGridVertices{{CG_SOLVER_NAME}}
284 __TemplateTouchCellLastTime_CorrectionScheme=
"""
286 fineGridCell{{DG_SOLVER_NAME}}.getType() != celldata::{{DG_SOLVER_NAME}}::Type::Coarse
288 {{PREDICATE_EVALUATE_RHS}}
290 logTraceIn("ComputeAndRestrictResidual");
291 assertionEquals( {{CG_SOLVER_NAME}}::VertexUnknowns, {{DG_SOLVER_NAME}}::UnknownsPerCellNode );
293 // =============================
294 // compute and restrict residual
295 // =============================
297 static std::vector< tarch::la::Matrix< TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns, {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode, double > > restrictionMatrices = {
298 {% for MATRIX in RESTRICTION_MATRIX %}
300 {{MATRIX[0]| join(", ")}}
301 {% for ROW in MATRIX[1:] %}
302 ,{{ROW | join(", ")}}
308 {% if RESTRICTION_MATRIX_SCALING is not defined %}
309 #error No scaling for injection matrix available.
312 static std::vector<int> restrictionMatricesScaleFactors = {
313 {% for el in INJECTION_MATRIX_SCALING %}
318 tarch::la::Matrix< TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns, {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode, double > composedRestrictionMatrix = ::mghype::composeMatrixFromHWeightedLinearCombination( restrictionMatrices, restrictionMatricesScaleFactors, marker.h() );
320 // ============================
321 // update the solutions on all 4 adjacent faces so that we
322 // can correctly restrict the residual. by now, all
323 // projections have been set correctly, but we might
324 // redundantly set solutions...
325 // ============================
327 // vector to hold "updated" solutions
328 tarch::la::Vector< repositories::{{DG_SOLVER_INSTANCE}}.FaceUnknownsSolution*TwoTimesD, double > faceSolutions;
330 for (int f=0; f<TwoPowerD; f++) {
331 for (int s=0; s<repositories::{{DG_SOLVER_INSTANCE}}.FaceUnknownsSolution; s++)
332 faceSolutions( f*repositories::{{DG_SOLVER_INSTANCE}}.FaceUnknownsSolution + s ) = fineGridFaces{{DG_SOLVER_NAME}}(f).getSolution(s);
335 mghype::matrixfree::solvers::dgcgcoupling::computeAndRestrictResidual<{{DG_SOLVER_NAME}}, {{CG_SOLVER_NAME}}>(
336 composedRestrictionMatrix,
337 repositories::{{DG_SOLVER_INSTANCE}}.getMassMatrix( marker.x(), marker.h() ),
338 repositories::{{DG_SOLVER_INSTANCE}}.getLocalAssemblyMatrix(marker.x(), marker.h()),
339 fineGridCell{{DG_SOLVER_NAME}}.getSolution(),
340 fineGridCell{{DG_SOLVER_NAME}}.getRhs(),
341 repositories::{{DG_SOLVER_INSTANCE}}.getCellFromFaceMatrix( marker.x(), marker.h() ) * faceSolutions,
342 fineGridVertices{{CG_SOLVER_NAME}}
346 // ============================
347 // inject solution back (accumulation)
348 // ============================
350 constexpr int Rows = TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns;
351 constexpr int Cols = {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode;
353 static std::vector< tarch::la::Matrix< Rows, Cols, double > > injectionMatrices = {
354 {% for MATRIX in INJECTION_MATRIX %}
356 {{MATRIX[0]| join(", ")}}
357 {% for ROW in MATRIX[1:] %}
358 ,{{ROW | join(", ")}}
364 {% if INJECTION_MATRIX_SCALING is not defined %}
365 #error No scaling for injection matrix available.
368 static std::vector<int> injectionMatricesScaleFactors = {
369 {% for el in INJECTION_MATRIX_SCALING %}
374 tarch::la::Matrix< Rows, Cols, double > composedInjectionMatrix = ::mghype::composeMatrixFromHWeightedLinearCombination( injectionMatrices, injectionMatricesScaleFactors, marker.h() );
376 mghype::matrixfree::solvers::dgcgcoupling::injectSolution<{{DG_SOLVER_NAME}}, {{CG_SOLVER_NAME}}>(
377 composedInjectionMatrix,
378 fineGridCell{{DG_SOLVER_NAME}}.getSolution(),
379 fineGridVertices{{CG_SOLVER_NAME}}
386 mghype::matrixfree::solvers::dgcgcoupling::updateRestrictionCounters(
387 fineGridVertices{{CG_SOLVER_NAME}}
389 logTraceOut("ComputeAndRestrictResidual");
397 prolongation_matrix_scaling,
399 restriction_matrix_scaling,
401 injection_matrix_scaling,
408 @param prolongation_matrix Please consult the action set ComputeAndRestrictBiasedHierarchicalResidual.
410 @param prolongation_matrix_scaling Please consult the action set ComputeAndRestrictBiasedHierarchicalResidual.
412 @param injection_matrix: [ @f$ \mathbb{R}^{2^dK \times (p+1}^dK } @f$ ]
413 Sequence of matrices. Each takes the solution over the cell spanned by
414 @f$ (p+1}^dK @f$ weights and maps them onto @f$ K @f$ quantities on the
415 vertices. These quantities are typically just the value of the polynomial
416 in the vertex, but you can pick other schemes, too. Most of the time, it
417 will be a single injection (with one scaling, see below). To be in line
418 with the other signatures, you can however specify the total injection through a
419 sequence of matrices, each one with its own @f$ h^s @f$ scaling.
421 @param injection_matrix_scaling: [ Integer ]
422 Specifies a sequence of values @f$ s @f$. They define with which
423 @f$ h^s @f$ the corresponding matrices in injection_matrix are to be
424 scaled. That is, if you pass in a [3,0], then the first matrix in
425 injection_matrix will be scaled with @f$ h^3 @f$ and the second one
426 with one. If you work with a simple function evaluation as injection,
427 then you are fine with one matrix, and its scaline will be [ 0 ].
429 @param use_fas: Boolean
430 If this flag is set, we realise a FAS following the HTMG idea by
434 super( AbstractDGCGCoupling, self ).
__init__(
443 dg_solver._basic_descend_order = cg_solver._basic_descend_order - 1
446 self.
d[
"DG_SOLVER_INSTANCE"] = dg_solver.instance_name()
447 self.
d[
"DG_SOLVER_NAME"] = dg_solver.typename()
448 self.
d[
"CG_SOLVER_INSTANCE"] = cg_solver.instance_name()
449 self.
d[
"CG_SOLVER_NAME"] = cg_solver.typename()
451 self.
d[
"INJECTION_MATRIX"] = injection_matrix
452 self.
d[
"INJECTION_MATRIX_SCALING"] = injection_matrix_scaling
453 self.
d[
"PROLONGATION_MATRIX"] = prolongation_matrix
454 self.
d[
"PROLONGATION_MATRIX_SCALING"] = prolongation_matrix_scaling
455 self.
d[
"RESTRICTION_MATRIX"] = restriction_matrix
456 self.
d[
"RESTRICTION_MATRIX_SCALING"] = restriction_matrix_scaling
458 self.
d[
"PREDICATE_INJECT_AND_RESTRICT"] =
"true"
459 self.
d[
"PREDICATE_PROLONGATE"] =
"true"
460 self.
d[
"PREDICATE_EVALUATE_RHS"] =
"true"
463 self.
d[
"USE_FAS"] =
"true"
466 self.
d[
"USE_FAS"] =
"false"
472 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_VERTEX_FIRST_TIME:
475 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
478 if self.
_use_fas and operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_LAST_TIME:
481 if not self.
_use_fas and operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_LAST_TIME:
489 Configure name of generated C++ action set
491 This action set will end up in the directory observers with a name that
492 reflects how the observer (initialisation) is mapped onto this action
493 set. The name pattern is ObserverName2ActionSetIdentifier where this
494 routine co-determines the ActionSetIdentifier. We make is reflect the
498 return __name__.replace(
".py",
"").replace(
".",
"_")
503 The action set that Peano will generate that corresponds to this class
504 should not be modified by users and can safely be overwritten every time
505 we run the Python toolkit.
513 We need the solver repository in this action set, as we directly access
514 the solver object. We also need access to Peano's d-dimensional loops.
518#include "../repositories/SolverRepository.h"
519#include "peano4/utils/Loop.h"
520#include "mghype/mghype.h"
521#include "mghype/matrixfree/solvers/DGCGCoupling.h"
528 Introduce additive CC Coupling
530 The control logic here is simplistic and prescripted. We follow the
531 following steps for the additive solver with one iteration:
534 - Interpolate correction, i.e. sum all the hierarchies up.
535 This happens in touchCellFirstTime().
536 - Compute and restrict residual and inject solution (if FAS).
537 This happens in touchCellLastTime().
538 - Suspend both solvers, but let DG solver project its solution onto the
541 - All solvers compute.
542 - DG solver can project solution onto faces.
545 Nothing stops us from repeating the step (2) multiple times, which gives
546 us the opportunity to play around with various multigrid schemes.
547 If we are in the last sweep of (2), the projection onto the faces of the
548 DG solver is not necessary. We'll overwrite this solution a minute later
553 This action set will map onto a class of its own. We give the class a
554 class attribute which we increment by one in each step. We then make the
555 actual logic depend upon this counter, as we inject the predicates into
556 the superclass: That is, the superclass has some boolean expressions which
557 allow us to switch its features on and off. We make those guys depends upon
565 prolongation_matrix_scaling,
567 restriction_matrix_scaling,
569 injection_matrix_scaling,
571 smoothing_steps_per_cycle = 1
573 super( AdditiveDGCGCoupling, self ).
__init__(
577 prolongation_matrix_scaling,
579 restriction_matrix_scaling,
581 injection_matrix_scaling,
584 self.
dd[
"PREDICATE_INJECT_AND_RESTRICT"] =
"CycleCounter==0"
585 self.
dd[
"PREDICATE_PROLONGATE"] =
"CycleCounter==0"
586 self.
dd[
"PREDICATE_EVALUATE_RHS"] =
"CycleCounter==0"
587 self.
dd[
"SMOOTHING_STEPS_PER_CYCLE"] = smoothing_steps_per_cycle
589 assert smoothing_steps_per_cycle>=1,
"at least one smoothing step required"
595 Add a new static attribute to the class.
599 static int CycleCounter;
606 Initialise the new counter.
609 return "int " + full_qualified_classname +
"::CycleCounter = -1;"
613 return jinja2.Template(
"""
616 if (CycleCounter==0) {
617 logInfo( "prepareTraversal(...)", "pre-step: prolong updates and restrict (new) residual, but do not yet run any solver" );
618 repositories::instanceOf{{CG_SOLVER_NAME}}.suspend();
619 repositories::instanceOf{{DG_SOLVER_NAME}}.suspend(true);
621 else if (CycleCounter=={{SMOOTHING_STEPS_PER_CYCLE}}) {
622 logInfo( "prepareTraversal(...)", "last smoothing step" );
626 logInfo( "prepareTraversal(...)", "normal smoothing step" );
628""").render( **self.
dd )
635 Introduce multiplicative CC Coupling
637 The control logic here is simplistic and prescripted. We follow the
638 following steps for the additive solver with one iteration:
640 1. Pre First smoothing step
641 - When we touchVertexFirstTime, we pass over rollOverAndPrepareCGVertex,
642 which has the effect of taking whatever is in the CG solution
643 and writing it into the Delta. This is then interpolated during
645 - Interpolate correction, i.e. sum all the hierarchies up.
646 This happens in touchCellFirstTime().
649 - Let DG solver project data onto faces
653 3. Nth DG smoothing step
654 - Still run DG solver (finish smoothing)
655 During touchCellLastTime, we:
656 - Compute hierarchical residual
659 These steps will set newRestrictedRhs correctly
661 On the first CG smoothing step, we should, during
662 touchVertexFirstTime, pass over rollOverAndPrepareCGVertex
663 which takes newRestrictedRhs and writes it into rhs, and
669 This action set will map onto a class of its own. We give the class a
670 class attribute which we increment by one in each step. We then make the
671 actual logic depend upon this counter, as we inject the predicates into
672 the superclass: That is, the superclass has some boolean expressions which
673 allow us to switch its features on and off. We make those guys depends upon
681 prolongation_matrix_scaling,
683 restriction_matrix_scaling,
685 injection_matrix_scaling,
687 smoothing_steps_DG = 5,
688 smoothing_steps_CG = -1,
694 @param smoothing_steps_DG: positive integer
696 @param smoothing_steps_CG: positive integer or -1
697 The -1 indicates that we wait for full convergence on the coarse
701 super( MultiplicativeDGCGCoupling, self ).
__init__(
705 prolongation_matrix_scaling,
707 restriction_matrix_scaling,
709 injection_matrix_scaling,
715 cg_solver_name = self.
dd[
"CG_SOLVER_NAME"]
716 dg_solver_name = self.
dd[
"DG_SOLVER_NAME"]
723 self.
dd[
"PREDICATE_INJECT_AND_RESTRICT"] = f
"DGCycleCounter>DGSmoothingSteps and CGCycleCounter==1"
726 self.
dd[
"PREDICATE_PROLONGATE"] = f
"DGCycleCounter==1 and CGCycleCounter==0"
732 self.
dd[
"PREDICATE_EVALUATE_RHS"] = f
"DGCycleCounter>DGSmoothingSteps and CGCycleCounter==0"
734 assert smoothing_steps_DG>=1,
"at least one smoothing step required"
735 assert smoothing_steps_CG>=1
or smoothing_steps_CG==-1,
"at least one smoothing step required"
749 Add a new static attribute to the class.
754 smoothing_steps_CG_string =
"std::numeric_limits<int>::max()"
758 CG_solver_tolerance = self.
cg_solver._solver_tolerance
761 static constexpr int DGSmoothingSteps = {};
762 static constexpr int CGSmoothingSteps = {};
763 static constexpr double CGSolverTolerance = {};
764 static int DGCycleCounter;
765 static int CGCycleCounter;
772 Initialise the new counter.
776int """ + full_qualified_classname +
"""::DGCycleCounter = 0;
777int """ + full_qualified_classname +
"""::CGCycleCounter = 0;
781 return jinja2.Template(
"""
782 logTraceInWith3Arguments("PrepareTraversal", DGCycleCounter, CGCycleCounter, repositories::instanceOf{{CG_SOLVER_NAME}}.getGlobalResidualMaxNorm());
783 if (DGCycleCounter>0 and DGCycleCounter<DGSmoothingSteps) {
784 repositories::instanceOf{{CG_SOLVER_NAME}}.suspend();
786 logInfo( "prepareTraversal(...)", "run DG smoother step, disable CG solver" );
789 DGCycleCounter>0 and DGCycleCounter==DGSmoothingSteps
791 // same as above, but we need to make sure final update residual is halted
792 logInfo( "prepareTraversal(...)", "run final DG smoother step, disable CG solver" );
794 repositories::instanceOf{{CG_SOLVER_NAME}}.suspend();
795 repositories::instanceOf{{DG_SOLVER_NAME}}.suspend(false, true);
799 DGCycleCounter>DGSmoothingSteps
801 CGCycleCounter<CGSmoothingSteps
804 repositories::instanceOf{{CG_SOLVER_NAME}}.getGlobalResidualMaxNorm() > 0.0
806 repositories::instanceOf{{CG_SOLVER_NAME}}.getGlobalResidualMaxNorm() <= CGSolverTolerance
810 We haven't reached our termination condition for CG solver yet
812 repositories::instanceOf{{DG_SOLVER_NAME}}.suspend(false, false);
814 logInfo( "prepareTraversal(...)", "run CG smoother step, disable DG solver. CG residual="<< repositories::instanceOf{{CG_SOLVER_NAME}}.getGlobalResidualMaxNorm());
819 repositories::instanceOf{{DG_SOLVER_NAME}}.suspend(true, false);
820 repositories::instanceOf{{CG_SOLVER_NAME}}.suspend();
821 logInfo( "prepareTraversal(...)", "suspend all solvers, interpolate CG->DG and project new solution onto faces" );
823 logTraceOutWith5Arguments("PrepareTraversal", DGCycleCounter, CGCycleCounter, repositories::instanceOf{{DG_SOLVER_NAME}}.isSuspended(), repositories::instanceOf{{DG_SOLVER_NAME}}.projectOntoFaces(), repositories::instanceOf{{CG_SOLVER_NAME}}.isSuspended());
824""").render( **self.
dd )
Specialisation of dastgen2.attributes.DoubleArray which relies on Peano's tarch.
Action set (reactions to events)
Couple the solution and updates of two different solvers.
user_should_modify_template(self)
The action set that Peano will generate that corresponds to this class should not be modified by user...
get_includes(self)
We need the solver repository in this action set, as we directly access the solver object.
__init__(self, dg_solver, cg_solver, prolongation_matrix, prolongation_matrix_scaling, restriction_matrix, restriction_matrix_scaling, injection_matrix, injection_matrix_scaling, use_fas)
Construct action set.
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
str __TemplateTouchCellLastTime_CorrectionScheme
str templateTouchCellFirstTime
str __TemplateTouchCellLastTime_FAS
str __TemplateTouchVertexFirstTime
get_action_set_name(self)
Configure name of generated C++ action set.
Introduce additive CC Coupling.
get_attributes(self)
Add a new static attribute to the class.
get_body_of_prepareTraversal(self)
get_static_initialisations(self, full_qualified_classname)
Initialise the new counter.
__init__(self, dg_solver, cg_solver, prolongation_matrix, prolongation_matrix_scaling, restriction_matrix, restriction_matrix_scaling, injection_matrix, injection_matrix_scaling, use_fas, smoothing_steps_per_cycle=1)
Construct action set.
Introduce multiplicative CC Coupling.
get_static_initialisations(self, full_qualified_classname)
Initialise the new counter.
get_body_of_prepareTraversal(self)
__init__(self, dg_solver, cg_solver, prolongation_matrix, prolongation_matrix_scaling, restriction_matrix, restriction_matrix_scaling, injection_matrix, injection_matrix_scaling, use_fas, smoothing_steps_DG=5, smoothing_steps_CG=-1)
Construct the solver.
get_attributes(self)
Add a new static attribute to the class.
prepare_CG_correction_solvers(dg_solver, cg_solver)
Prepare CG solver for coupling and ensure that both solvers are invoked in the correct order.