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
38 cg_solver._vertex_data.peano4_mpi_and_storage_aspect.merge_implementation +=
"""\n setNewRestrictedRhs( getNewRestrictedRhs() + neighbour.getNewRestrictedRhs() ); \n"""
44 Couple the solution and updates of two different solvers
49 This action set has to be used as a preprocessing step of the CG:
51 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
52 solver.preprocessing_action_set = mghype.matrixfree.solvers.api.actionsets.AbstractDGCGCoupling(
56 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
58 I recommend not to use the coupling directly, but one of its subclasses.
63 We have a new variable SumOfInjectedValues. This one is set to zero at the end
64 of touchVertexFirstTime(), i.e. at the begin of a mesh sweep. In each fine
65 grid cell, i.e. each cell carrying a DG polynomial, we evaluate this
66 polynomial's value in the @f$ 2^d @f$ vertices (corners) of the cell. Of
67 these values, we restrict @f$ 2^{=-d} @f$th of its value to the next coarser
68 mesh level. Prior to the start of a new mesh sweep, SumOfInjectedValues holds
69 the average value of the solution in a vertex. This is just before we
70 clear it again, i.e. we can plug into touchVertexFirstTime() just before we
71 clear this field to read our a coarsened representation of the solution at
78 This class takes the solution of a DG solver and injects the current solution
79 onto the vertices. For this, it simply averages the @f$ 2^d @f$ different
80 values of the DG polynomials into the vertex. We do this only for unrefined
83 To realise this behaviour, we rely on functions held within
84 AbstractDGCGCoupling.h.
85 It is important that prepare_and_order_DG_CG_solvers() has been invoked for
86 the two solvers whenever we use this action set.
91 __TemplateTouchVertexFirstTime=
"""
93 fineGridVertex{{CG_SOLVER_NAME}}.getType() != vertexdata::{{CG_SOLVER_NAME}}::Type::Coarse
96 if ({{PREDICATE_INJECT_AND_RESTRICT}}) {
97 mghype::matrixfree::solvers::dgcgcoupling::rollOverAndPrepareCGVertex(
98 fineGridVertex{{CG_SOLVER_NAME}},
99 true, // restrictRhsAndInjectSolution
106 We aim to visit this section just before we prolongate. Passing false to
107 restrictRhsAndInjectSolution has the effect of setting delta to the "value"
108 parameter, ie we pick up the final solution to be interpolated during
111 else if ( {{PREDICATE_PROLONGATE}} ) {
112 mghype::matrixfree::solvers::dgcgcoupling::rollOverAndPrepareCGVertex(
113 fineGridVertex{{CG_SOLVER_NAME}},
114 false, // restrictRhsAndInjectSolution
122 templateTouchCellFirstTime=
"""
123 // ============================
125 // ============================
126 const double additiveMultigridRelaxation = 0.0;
128 fineGridCell{{DG_SOLVER_NAME}}.getType() != celldata::{{DG_SOLVER_NAME}}::Type::Coarse
130 {{PREDICATE_PROLONGATE}}
132 logTraceInWith2Arguments("Prolongate()", (bool)({{PREDICATE_PROLONGATE}}), fineGridCell{{DG_SOLVER_NAME}}.toString());
133 constexpr int Cols = TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns;
134 constexpr int Rows = {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode;
136 static std::vector< tarch::la::Matrix< Rows, Cols, double > > matrices = {
137 {% for MATRIX in PROLONGATION_MATRIX %}
139 {{MATRIX[0]| join(", ")}}
140 {% for ROW in MATRIX[1:] %}
141 ,{{ROW | join(", ")}}
147 {% if PROLONGATION_MATRIX_SCALING is not defined %}
148 #error No scaling for prolongation matrix available.
151 static std::vector<int> scaleFactors = {
152 {% for el in PROLONGATION_MATRIX_SCALING %}
157 tarch::la::Matrix< Rows, Cols, double > composedProlongationMatrix = ::mghype::composeMatrixFromHWeightedLinearCombination( matrices, scaleFactors, marker.h() );
159 fineGridCell{{DG_SOLVER_NAME}}.setSolution(
160 mghype::matrixfree::solvers::dgcgcoupling::prolongate<{{DG_SOLVER_NAME}}, {{CG_SOLVER_NAME}}>(
161 composedProlongationMatrix,
162 fineGridCell{{DG_SOLVER_NAME}}.getSolution(),
163 fineGridVertices{{CG_SOLVER_NAME}}
166 logTraceOutWith1Argument("Prolongate()", fineGridCell{{DG_SOLVER_NAME}}.toString());
172 __TemplateTouchCellLastTime_FAS=
"""
174 fineGridCell{{DG_SOLVER_NAME}}.getType() != celldata::{{DG_SOLVER_NAME}}::Type::Coarse
176 {{PREDICATE_EVALUATE_RHS}}
178 assertionEquals( {{CG_SOLVER_NAME}}::VertexUnknowns, {{DG_SOLVER_NAME}}::UnknownsPerCellNode );
180 // ==========================================
181 // compute and restrict hierarchical residual
182 // ==========================================
184 static std::vector< tarch::la::Matrix< {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode, TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns, double > > prolongationMatrices = {
185 {% for MATRIX in PROLONGATION_MATRIX %}
187 {{MATRIX[0]| join(", ")}}
188 {% for ROW in MATRIX[1:] %}
189 ,{{ROW | join(", ")}}
195 {% if PROLONGATION_MATRIX_SCALING is not defined %}
196 #error No scaling for injection matrix available.
199 static std::vector<int> prolongationMatricesScaleFactors = {
200 {% for el in PROLONGATION_MATRIX_SCALING %}
205 tarch::la::Matrix< {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode, TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns, double > composedProlongationMatrix = ::mghype::composeMatrixFromHWeightedLinearCombination( prolongationMatrices, prolongationMatricesScaleFactors, marker.h() );
207 static std::vector< tarch::la::Matrix< TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns, {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode, double > > restrictionMatrices = {
208 {% for MATRIX in RESTRICTION_MATRIX %}
210 {{MATRIX[0]| join(", ")}}
211 {% for ROW in MATRIX[1:] %}
212 ,{{ROW | join(", ")}}
218 {% if RESTRICTION_MATRIX_SCALING is not defined %}
219 #error No scaling for injection matrix available.
222 static std::vector<int> restrictionMatricesScaleFactors = {
223 {% for el in INJECTION_MATRIX_SCALING %}
228 tarch::la::Matrix< TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns, {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode, double > composedRestrictionMatrix = ::mghype::composeMatrixFromHWeightedLinearCombination( restrictionMatrices, restrictionMatricesScaleFactors, marker.h() );
230 mghype::matrixfree::solvers::dgcgcoupling::computeAndRestrictHierarchicalResidual<{{DG_SOLVER_NAME}}, {{CG_SOLVER_NAME}}>(
231 composedProlongationMatrix,
232 composedRestrictionMatrix,
233 repositories::{{DG_SOLVER_INSTANCE}}.getRhsMatrix( marker.x(), marker.h() ),
234 repositories::{{DG_SOLVER_INSTANCE}}.getLocalAssemblyMatrix(marker.x(), marker.h()),
235 fineGridCell{{DG_SOLVER_NAME}}.getSolution(),
236 fineGridCell{{DG_SOLVER_NAME}}.getRhs(),
237 fineGridVertices{{CG_SOLVER_NAME}}
241 // ============================
242 // inject solution back (accumulation)
243 // ============================
245 constexpr int Rows = TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns;
246 constexpr int Cols = {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode;
248 static std::vector< tarch::la::Matrix< Rows, Cols, double > > injectionMatrices = {
249 {% for MATRIX in INJECTION_MATRIX %}
251 {{MATRIX[0]| join(", ")}}
252 {% for ROW in MATRIX[1:] %}
253 ,{{ROW | join(", ")}}
259 {% if INJECTION_MATRIX_SCALING is not defined %}
260 #error No scaling for injection matrix available.
263 static std::vector<int> injectionMatricesScaleFactors = {
264 {% for el in INJECTION_MATRIX_SCALING %}
269 tarch::la::Matrix< Rows, Cols, double > composedInjectionMatrix = ::mghype::composeMatrixFromHWeightedLinearCombination( injectionMatrices, injectionMatricesScaleFactors, marker.h() );
271 mghype::matrixfree::solvers::dgcgcoupling::injectSolution<{{DG_SOLVER_NAME}}, {{CG_SOLVER_NAME}}>(
272 composedInjectionMatrix,
273 fineGridCell{{DG_SOLVER_NAME}}.getSolution(),
274 fineGridVertices{{CG_SOLVER_NAME}}
281 mghype::matrixfree::solvers::dgcgcoupling::updateRestrictionCounters(
282 fineGridVertices{{CG_SOLVER_NAME}}
288 __TemplateTouchCellLastTime_CorrectionScheme=
"""
290 fineGridCell{{DG_SOLVER_NAME}}.getType() != celldata::{{DG_SOLVER_NAME}}::Type::Coarse
292 {{PREDICATE_EVALUATE_RHS}}
294 logTraceIn("ComputeAndRestrictResidual");
295 assertionEquals( {{CG_SOLVER_NAME}}::VertexUnknowns, {{DG_SOLVER_NAME}}::UnknownsPerCellNode );
297 // =============================
298 // compute and restrict residual
299 // =============================
301 static std::vector< tarch::la::Matrix< TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns, {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode, double > > restrictionMatrices = {
302 {% for MATRIX in RESTRICTION_MATRIX %}
304 {{MATRIX[0]| join(", ")}}
305 {% for ROW in MATRIX[1:] %}
306 ,{{ROW | join(", ")}}
312 {% if RESTRICTION_MATRIX_SCALING is not defined %}
313 #error No scaling for injection matrix available.
316 static std::vector<int> restrictionMatricesScaleFactors = {
317 {% for el in INJECTION_MATRIX_SCALING %}
322 tarch::la::Matrix< TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns, {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode, double > composedRestrictionMatrix = ::mghype::composeMatrixFromHWeightedLinearCombination( restrictionMatrices, restrictionMatricesScaleFactors, marker.h() );
324 // ============================
325 // update the solutions on all 4 adjacent faces so that we
326 // can correctly restrict the residual. by now, all
327 // projections have been set correctly, but we might
328 // redundantly set solutions...
329 // ============================
331 // vector to hold "updated" solutions
332 tarch::la::Vector< repositories::{{DG_SOLVER_INSTANCE}}.FaceUnknownsSolution*TwoTimesD, double > faceSolutions;
334 for (int f=0; f<TwoPowerD; f++) {
335 for (int s=0; s<repositories::{{DG_SOLVER_INSTANCE}}.FaceUnknownsSolution; s++)
336 faceSolutions( f*repositories::{{DG_SOLVER_INSTANCE}}.FaceUnknownsSolution + s ) = fineGridFaces{{DG_SOLVER_NAME}}(f).getSolution(s);
339 mghype::matrixfree::solvers::dgcgcoupling::computeAndRestrictResidual<{{DG_SOLVER_NAME}}, {{CG_SOLVER_NAME}}>(
340 composedRestrictionMatrix,
341 repositories::{{DG_SOLVER_INSTANCE}}.getRhsMatrix( marker.x(), marker.h() ),
342 repositories::{{DG_SOLVER_INSTANCE}}.getLocalAssemblyMatrix(marker.x(), marker.h()),
343 fineGridCell{{DG_SOLVER_NAME}}.getSolution(),
344 fineGridCell{{DG_SOLVER_NAME}}.getRhs(),
345 repositories::{{DG_SOLVER_INSTANCE}}.getCellFromFaceMatrix( marker.x(), marker.h() ) * faceSolutions,
346 fineGridVertices{{CG_SOLVER_NAME}}
350 // ============================
351 // inject solution back (accumulation)
352 // ============================
354 constexpr int Rows = TwoPowerD * {{CG_SOLVER_NAME}}::VertexUnknowns;
355 constexpr int Cols = {{DG_SOLVER_NAME}}::NodesPerCell * {{DG_SOLVER_NAME}}::UnknownsPerCellNode;
357 static std::vector< tarch::la::Matrix< Rows, Cols, double > > injectionMatrices = {
358 {% for MATRIX in INJECTION_MATRIX %}
360 {{MATRIX[0]| join(", ")}}
361 {% for ROW in MATRIX[1:] %}
362 ,{{ROW | join(", ")}}
368 {% if INJECTION_MATRIX_SCALING is not defined %}
369 #error No scaling for injection matrix available.
372 static std::vector<int> injectionMatricesScaleFactors = {
373 {% for el in INJECTION_MATRIX_SCALING %}
378 tarch::la::Matrix< Rows, Cols, double > composedInjectionMatrix = ::mghype::composeMatrixFromHWeightedLinearCombination( injectionMatrices, injectionMatricesScaleFactors, marker.h() );
380 mghype::matrixfree::solvers::dgcgcoupling::injectSolution<{{DG_SOLVER_NAME}}, {{CG_SOLVER_NAME}}>(
381 composedInjectionMatrix,
382 fineGridCell{{DG_SOLVER_NAME}}.getSolution(),
383 fineGridVertices{{CG_SOLVER_NAME}}
390 mghype::matrixfree::solvers::dgcgcoupling::updateRestrictionCounters(
391 fineGridVertices{{CG_SOLVER_NAME}}
393 logTraceOut("ComputeAndRestrictResidual");
401 prolongation_matrix_scaling,
403 restriction_matrix_scaling,
405 injection_matrix_scaling,
412 @param prolongation_matrix Please consult the action set ComputeAndRestrictBiasedHierarchicalResidual.
414 @param prolongation_matrix_scaling Please consult the action set ComputeAndRestrictBiasedHierarchicalResidual.
416 @param injection_matrix: [ @f$ \mathbb{R}^{2^dK \times (p+1}^dK } @f$ ]
417 Sequence of matrices. Each takes the solution over the cell spanned by
418 @f$ (p+1}^dK @f$ weights and maps them onto @f$ K @f$ quantities on the
419 vertices. These quantities are typically just the value of the polynomial
420 in the vertex, but you can pick other schemes, too. Most of the time, it
421 will be a single injection (with one scaling, see below). To be in line
422 with the other signatures, you can however specify the total injection through a
423 sequence of matrices, each one with its own @f$ h^s @f$ scaling.
425 @param injection_matrix_scaling: [ Integer ]
426 Specifies a sequence of values @f$ s @f$. They define with which
427 @f$ h^s @f$ the corresponding matrices in injection_matrix are to be
428 scaled. That is, if you pass in a [3,0], then the first matrix in
429 injection_matrix will be scaled with @f$ h^3 @f$ and the second one
430 with one. If you work with a simple function evaluation as injection,
431 then you are fine with one matrix, and its scaline will be [ 0 ].
433 @param use_fas: Boolean
434 If this flag is set, we realise a FAS following the HTMG idea by
438 super( AbstractDGCGCoupling, self ).
__init__(
447 dg_solver._basic_descend_order = cg_solver._basic_descend_order - 1
450 self.
d[
"DG_SOLVER_INSTANCE"] = dg_solver.instance_name()
451 self.
d[
"DG_SOLVER_NAME"] = dg_solver.typename()
452 self.
d[
"CG_SOLVER_INSTANCE"] = cg_solver.instance_name()
453 self.
d[
"CG_SOLVER_NAME"] = cg_solver.typename()
455 self.
d[
"INJECTION_MATRIX"] = injection_matrix
456 self.
d[
"INJECTION_MATRIX_SCALING"] = injection_matrix_scaling
457 self.
d[
"PROLONGATION_MATRIX"] = prolongation_matrix
458 self.
d[
"PROLONGATION_MATRIX_SCALING"] = prolongation_matrix_scaling
459 self.
d[
"RESTRICTION_MATRIX"] = restriction_matrix
460 self.
d[
"RESTRICTION_MATRIX_SCALING"] = restriction_matrix_scaling
462 self.
d[
"PREDICATE_INJECT_AND_RESTRICT"] =
"true"
463 self.
d[
"PREDICATE_PROLONGATE"] =
"true"
464 self.
d[
"PREDICATE_EVALUATE_RHS"] =
"true"
467 self.
d[
"USE_FAS"] =
"true"
470 self.
d[
"USE_FAS"] =
"false"
476 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_VERTEX_FIRST_TIME:
479 if operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME:
482 if self.
_use_fas and operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_LAST_TIME:
485 if not self.
_use_fas and operation_name==peano4.solversteps.ActionSet.OPERATION_TOUCH_CELL_LAST_TIME:
493 Configure name of generated C++ action set
495 This action set will end up in the directory observers with a name that
496 reflects how the observer (initialisation) is mapped onto this action
497 set. The name pattern is ObserverName2ActionSetIdentifier where this
498 routine co-determines the ActionSetIdentifier. We make is reflect the
502 return __name__.replace(
".py",
"").replace(
".",
"_")
507 The action set that Peano will generate that corresponds to this class
508 should not be modified by users and can safely be overwritten every time
509 we run the Python toolkit.
517 We need the solver repository in this action set, as we directly access
518 the solver object. We also need access to Peano's d-dimensional loops.
522#include "../repositories/SolverRepository.h"
523#include "peano4/utils/Loop.h"
524#include "mghype/mghype.h"
525#include "mghype/matrixfree/solvers/DGCGCoupling.h"
532 Introduce additive CC Coupling
534 The control logic here is simplistic and prescripted. We follow the
535 following steps for the additive solver with one iteration:
538 - Interpolate correction, i.e. sum all the hierarchies up.
539 This happens in touchCellFirstTime().
540 - Compute and restrict residual and inject solution (if FAS).
541 This happens in touchCellLastTime().
542 - Suspend both solvers, but let DG solver project its solution onto the
545 - All solvers compute.
546 - DG solver can project solution onto faces.
549 Nothing stops us from repeating the step (2) multiple times, which gives
550 us the opportunity to play around with various multigrid schemes.
551 If we are in the last sweep of (2), the projection onto the faces of the
552 DG solver is not necessary. We'll overwrite this solution a minute later
557 This action set will map onto a class of its own. We give the class a
558 class attribute which we increment by one in each step. We then make the
559 actual logic depend upon this counter, as we inject the predicates into
560 the superclass: That is, the superclass has some boolean expressions which
561 allow us to switch its features on and off. We make those guys depends upon
569 prolongation_matrix_scaling,
571 restriction_matrix_scaling,
573 injection_matrix_scaling,
575 smoothing_steps_per_cycle = 1
577 super( AdditiveDGCGCoupling, self ).
__init__(
581 prolongation_matrix_scaling,
583 restriction_matrix_scaling,
585 injection_matrix_scaling,
588 self.
dd[
"PREDICATE_INJECT_AND_RESTRICT"] =
"CycleCounter==0"
589 self.
dd[
"PREDICATE_PROLONGATE"] =
"CycleCounter==0"
590 self.
dd[
"PREDICATE_EVALUATE_RHS"] =
"CycleCounter==0"
591 self.
dd[
"SMOOTHING_STEPS_PER_CYCLE"] = smoothing_steps_per_cycle
593 assert smoothing_steps_per_cycle>=1,
"at least one smoothing step required"
599 Add a new static attribute to the class.
603 static int CycleCounter;
610 Initialise the new counter.
613 return "int " + full_qualified_classname +
"::CycleCounter = -1;"
617 return jinja2.Template(
"""
620 if (CycleCounter==0) {
621 logInfo( "prepareTraversal(...)", "pre-step: prolong updates and restrict (new) residual, but do not yet run any solver" );
622 repositories::instanceOf{{CG_SOLVER_NAME}}.suspend();
623 repositories::instanceOf{{DG_SOLVER_NAME}}.suspend(true);
625 else if (CycleCounter=={{SMOOTHING_STEPS_PER_CYCLE}}) {
626 logInfo( "prepareTraversal(...)", "last smoothing step" );
630 logInfo( "prepareTraversal(...)", "normal smoothing step" );
632""").render( **self.
dd )
639 Introduce multiplicative CC Coupling
641 The control logic here is simplistic and prescripted. We follow the
642 following steps for the additive solver with one iteration:
644 1. Pre First smoothing step
645 - When we touchVertexFirstTime, we pass over rollOverAndPrepareCGVertex,
646 which has the effect of taking whatever is in the CG solution
647 and writing it into the Delta. This is then interpolated during
649 - Interpolate correction, i.e. sum all the hierarchies up.
650 This happens in touchCellFirstTime().
653 - Let DG solver project data onto faces
657 3. Nth DG smoothing step
658 - Still run DG solver (finish smoothing)
659 During touchCellLastTime, we:
660 - Compute hierarchical residual
663 These steps will set newRestrictedRhs correctly
665 On the first CG smoothing step, we should, during
666 touchVertexFirstTime, pass over rollOverAndPrepareCGVertex
667 which takes newRestrictedRhs and writes it into rhs, and
673 This action set will map onto a class of its own. We give the class a
674 class attribute which we increment by one in each step. We then make the
675 actual logic depend upon this counter, as we inject the predicates into
676 the superclass: That is, the superclass has some boolean expressions which
677 allow us to switch its features on and off. We make those guys depends upon
685 prolongation_matrix_scaling,
687 restriction_matrix_scaling,
689 injection_matrix_scaling,
691 smoothing_steps_DG = 4,
692 smoothing_steps_CG = -1,
699 @param smoothing_steps_DG: positive integer
701 @param smoothing_steps_CG: positive integer or -1
702 The -1 indicates that we wait for full convergence on the coarse
705 @param vcycles: positive integer or -1.
706 Terminate after the given number of full V-cycles.
707 The -1 indicates that we wait for full convergence on the coarse mesh.
708 If a positive integer is set, the correction solver tolerance needs to be set to a small value
709 to ensure the given number of cycles is completed before the tolerance is reached.
710 @todo: Implement ignoring the tolerance when the number of cycles is set as a stopping criterion.
713 super( MultiplicativeDGCGCoupling, self ).
__init__(
717 prolongation_matrix_scaling,
719 restriction_matrix_scaling,
721 injection_matrix_scaling,
727 cg_solver_name = self.
dd[
"CG_SOLVER_NAME"]
728 dg_solver_name = self.
dd[
"DG_SOLVER_NAME"]
735 self.
dd[
"PREDICATE_INJECT_AND_RESTRICT"] = f
"DGCycleCounter>DGSmoothingSteps and CGCycleCounter==1"
738 self.
dd[
"PREDICATE_PROLONGATE"] = f
"DGCycleCounter==1 and CGCycleCounter==0"
744 self.
dd[
"PREDICATE_EVALUATE_RHS"] = f
"DGCycleCounter>DGSmoothingSteps and CGCycleCounter==0"
746 assert smoothing_steps_DG>=1,
"at least one smoothing step required"
747 assert smoothing_steps_CG>=1
or smoothing_steps_CG==-1,
"at least one smoothing step required"
762 Add a new static attribute to the class.
766 vcycles_string =
"std::numeric_limits<int>::max()"
771 smoothing_steps_CG_string =
"std::numeric_limits<int>::max()"
775 CG_solver_tolerance = self.
cg_solver._solver_tolerance
778 static constexpr int DGSmoothingSteps = {};
779 static constexpr int CGSmoothingSteps = {};
780 static constexpr double CGSolverTolerance = {};
781 static constexpr int VCycles = {};
782 static int DGCycleCounter;
783 static int CGCycleCounter;
784 static double initialGlobalResidualMaxNorm;
785""".format(self.
smoothing_steps_DG, smoothing_steps_CG_string, CG_solver_tolerance, vcycles_string)
791 Initialise the new counter.
795int """ + full_qualified_classname +
"""::DGCycleCounter = 0;
796int """ + full_qualified_classname +
"""::CGCycleCounter = 0;
797double """ + full_qualified_classname +
"""::initialGlobalResidualMaxNorm = 0;
801 return jinja2.Template(
"""
802 logTraceInWith3Arguments("PrepareTraversal", DGCycleCounter, CGCycleCounter, repositories::instanceOf{{CG_SOLVER_NAME}}.getGlobalResidualMaxNorm());
803 if (DGCycleCounter>0 and DGCycleCounter<DGSmoothingSteps) {
804 repositories::instanceOf{{CG_SOLVER_NAME}}.suspend();
806 logInfo( "prepareTraversal(...)", "run DG smoother step, disable CG solver" );
809 DGCycleCounter>0 and DGCycleCounter==DGSmoothingSteps
811 // same as above, but we need to make sure final update residual is halted
812 logInfo( "prepareTraversal(...)", "run final DG smoother step, disable CG solver" );
814 repositories::instanceOf{{CG_SOLVER_NAME}}.suspend();
815 repositories::instanceOf{{DG_SOLVER_NAME}}.suspend(false, true);
819 DGCycleCounter>DGSmoothingSteps
821 repositories::instanceOf{{CG_SOLVER_NAME}}.getVCycleCounter()<VCycles
824 repositories::instanceOf{{CG_SOLVER_NAME}}.getGlobalResidualMaxNorm() > 0.0
826 repositories::instanceOf{{CG_SOLVER_NAME}}.getGlobalResidualMaxNorm() <= std::max(1E-14,initialGlobalResidualMaxNorm*CGSolverTolerance)
830 We haven't reached our termination condition for CG solver yet
832 if (CGCycleCounter==1) {
833 initialGlobalResidualMaxNorm = repositories::instanceOf{{CG_SOLVER_NAME}}.getGlobalResidualMaxNorm();
835 repositories::instanceOf{{DG_SOLVER_NAME}}.suspend(false, false);
837 logInfo( "prepareTraversal(...)", "run CG smoother step, disable DG solver. CG residual="<< repositories::instanceOf{{CG_SOLVER_NAME}}.getGlobalResidualMaxNorm());
842 repositories::instanceOf{{DG_SOLVER_NAME}}.suspend(true, false);
843 repositories::instanceOf{{CG_SOLVER_NAME}}.suspend();
844 logInfo( "prepareTraversal(...)", "suspend all solvers, interpolate CG->DG and project new solution onto faces" );
846 logTraceOutWith5Arguments("PrepareTraversal", DGCycleCounter, CGCycleCounter, repositories::instanceOf{{DG_SOLVER_NAME}}.isSuspended(), repositories::instanceOf{{DG_SOLVER_NAME}}.projectOntoFaces(), repositories::instanceOf{{CG_SOLVER_NAME}}.isSuspended());
847""").render( **self.
dd )
Specialisation of array using 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.
__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=4, smoothing_steps_CG=-1, vcycles=1)
Construct the solver.
get_body_of_prepareTraversal(self)
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.