6from .Helper
import write_file, shortened_class_name
8from .Overwrite
import Overwrite
15 Code generator for one action set
17 Do not confuse this with @ref peano4.api.solversteps.ActionSet.ActionSet,
18 which is the interface you actually implement (you subclass it and override
19 get_guard_of_operation(), get_body_of_operation(), get_attributes(),
20 get_includes(), ... to say
21 *what* the action set does). Users typically never interact with this
22 class. They work against the ActionSet in solversteps.
24 This class here is the corresponding writer: given one
25 such solversteps.ActionSet instance (held as self.implementation), it
26 emits the actual C++ .h/.cpp pair - the include guard, the class
27 declaration inside the right namespace, a static tarch::logging::Log
28 _log, the constructor/destructor, createGridControlEventsForNextTraversal(),
29 prepareTraversal()/unprepareTraversal(), and one method per grid event
30 (touchCellFirstTime, createPersistentVertex, ...) - calling back into
31 the get_implementation_of_*() routines - which combine your
32 get_guard_of_operation() and get_body_of_*() overrides - to fill in each
34 @ref peano4.api.solversteps.ActionSet.ActionSet is the data model, this class is the writer.
38 The class is instantiated in exactly one place: construct_output() of @ref
39 peano4.api.solversteps.StepToActionSets.StepToActionSets, which is called
40 once per action set attached to a @ref peano4.api.solversteps.Step.Step,
41 from Step.construct_output(), as it loops over self.action_sets. That
42 call site decides two things this class here itself does not know about:
44 - Which operations to generate.
45 - What the total number of vertices, cells, ... is and what they are called.
46 - Where the file goes and what it is called - if
47 action_set.user_should_modify_template() is True, it is named after the
48 action set itself and placed under actions/ (meant for you to hand-edit,
49 regenerated only if missing); if False, it is placed under observers/
50 and named "{step.name}2{action_set.get_action_set_name()}{index}" -
51 regenerated unconditionally every run.
55 - This is the generator which takes one @ref peano4.api.solversteps.StepToActionSets.StepToActionSets and maps it onto a header/implementation file pair.
56 - The outcome either ends up in actions/ (if user_should_modify_template() is True) or in observers/ (if False).
57 - The outcome typically is named Observer2ActionSetName.
61 - @ref page_peano_action_sets
62 - @ref peano4.api.taskgraph
66 def __init__(self,classname,namespace,subdirectory,implementation = None):
69 implementation Should be of type peano4.api.solversteps.ActionSet or
70 None. If it is None, then the generated stuff will be a
79 (peano4.api.solversteps.ActionSet.OPERATION_BEGIN_TRAVERSAL,
"void"),
80 (peano4.api.solversteps.ActionSet.OPERATION_END_TRAVERSAL,
"void")
88 signature is a long tuple. The first entry is the name of the routine,
89 the second entry is the result type. From thereon, one entry gives the
90 name of an attribute, the second one the type.
95 for i
in self.
include_files: outputfile.write(
'#include "{}"\n'.format(i) )
100 while i<len(operation):
101 result += operation[i+1]
103 result += operation[i]
113 outputfile points to file, operation to an operation object as added by the solver step
116 outputfile.write(
" virtual " )
118 outputfile.write(
" " )
119 outputfile.write( operation[1] )
120 outputfile.write(
" ")
121 outputfile.write( operation[0] )
124 outputfile.write(
" = 0")
125 outputfile.write(
";\n\n")
128 full_qualified_classname =
""
130 full_qualified_classname += i
131 full_qualified_classname +=
"::"
132 full_qualified_classname += self.
classname
133 return full_qualified_classname
137 default_overwrite =
True
139 default_overwrite =
False
141 if write_file(overwrite,default_overwrite,filename):
143 print(
"{} written by {}".format(filename, os.path.basename(inspect.getfile(self.
__class__))))
145 with open( filename,
"w" )
as outputfile:
147 include_guard =
"_{}_H_".format(full_qualified_classname.replace(
"::",
"_" ).upper())
149 outputfile.write(
"#ifndef {}\n#define {}\n\n\n".format(include_guard, include_guard))
151 outputfile.write(
"""
152#include "peano4/utils/Globals.h"
153#include "peano4/datamanagement/VertexEnumerator.h"
154#include "peano4/datamanagement/VertexMarker.h"
155#include "peano4/datamanagement/FaceEnumerator.h"
156#include "peano4/datamanagement/FaceMarker.h"
157#include "peano4/datamanagement/CellMarker.h"
158#include "peano4/grid/GridControlEvent.h"
159#include "tarch/la/Vector.h"
167 outputfile.write(
"\n\n" )
171 for i
in self.
namespace: outputfile.write(
"namespace " + i +
" {\n" )
172 outputfile.write(
" class {};\n".format(self.
classname))
173 for i
in self.
namespace: outputfile.write(
"}\n" )
175 outputfile.write(
"class " + full_qualified_classname +
"{\n" )
176 outputfile.write(
" private:\n" )
177 outputfile.write(
" static tarch::logging::Log _log;\n" )
180 outputfile.write(
" public:\n" )
181 outputfile.write(
"""
183 * Create action instance for one tree for one grid sweep
185 * <h2> Thread safety </h2>
187 * The creation of individual trees usually happens through peano4::parallel::SpacetreeSet::createObserverCloneIfRequired().
188 * This routine is called lazily when we start to traverse a subtree.
189 * Therefore, the creation of actions is not thread-safe.
192 * @param treeNumber Number of the spacetree for which we create the tree instance. Is
193 * smaller 0 if this is the prototype action used on a rank from which
194 * the real actions are constructed from.
197 outputfile.write(
" " + self.
classname +
"(int treeNumber);\n\n" )
198 outputfile.write(
" ~" + self.
classname +
"();\n\n" )
199 outputfile.write(
"""
200 std::vector< peano4::grid::GridControlEvent > createGridControlEventsForNextTraversal() const;
201 static void prepareTraversal();
202 static void unprepareTraversal();
206 outputfile.write(
"};\n\n\n" )
207 outputfile.write(
"#endif\n\n" )
214 default_overwrite =
True
216 default_overwrite =
False
217 if write_file(overwrite,default_overwrite,filename):
219 print(
"{} written by {}".format(filename, os.path.basename(inspect.getfile(self.
__class__))))
220 outputfile = open( filename,
"w" )
224 outputfile.write(
"#include \"" + self.
classname +
".h\"\n\n\n" )
229 outputfile.write(
"\n\n\n" )
233 outputfile.write(
"}\n\n\n" )
237 outputfile.write(
"}\n\n\n" )
239 outputfile.write(
"std::vector< peano4::grid::GridControlEvent > " + self.
__get_full_qualified_class_name() +
"::createGridControlEventsForNextTraversal() const {\n" )
240 outputfile.write( self.
implementation.get_implementation_of_createGridControlEventsForNextTraversal() )
241 outputfile.write(
"}\n\n\n" )
244 outputfile.write( self.
implementation.get_implementation_of_prepareTraversal() )
245 outputfile.write(
"}\n\n\n" )
248 outputfile.write( self.
implementation.get_implementation_of_unprepareTraversal() )
249 outputfile.write(
"}\n\n\n" )
252 outputfile.write( operation[1] )
253 outputfile.write(
" " )
256 outputfile.write(
" {\n" )
257 outputfile.write( self.
implementation.get_implementation_of_operation( operation[0] ) )
258 outputfile.write(
"\n" )
259 outputfile.write(
"}\n\n\n" )
262 if not os.path.exists( directory +
"/" + self.
subdirectory ):
Code generator for one action set.
__generate_operation(self, outputfile, operation)
outputfile points to file, operation to an operation object as added by the solver step
add_operation(self, name, signature)
signature is a long tuple.
__init__(self, classname, namespace, subdirectory, implementation=None)
implementation Should be of type peano4.api.solversteps.ActionSet or None.
__generate_header(self, overwrite, directory)
__get_full_qualified_class_name(self)
__generate_implementation(self, overwrite, directory)
generate(self, overwrite, directory)
__generate_includes(self, outputfile)
__get_operation_arguments(self, operation)
Action set (reactions to events)