3from .DaStGenToLegacyTool
import DaStGenToLegacyTool
22 Output artefact which writes one DaStGen2 data model into the project
24 The generators below do not write their data models straightaway, as they
25 do not know the directory of the project when they construct the output.
26 Instead, they register one artefact per data model with the output, which
27 writes the header and the implementation once the output is generated
28 into the project directory, as @ref peano4.api.output.Output "the output"
29 calls generate() on each of its artefacts.
32 def __init__(self, data_model, file_name_without_extension):
35 @param data_model: dastgen2.DataModel
36 Data model to write. Its full qualified name has to be set already.
38 @param file_name_without_extension: str
39 File name relative to the project directory.
48 self.
_data_model.write_header_file( file_name +
".h" )
49 self.
_data_model.write_implementation_file( file_name +
".cpp" )
56 Simple generator mapping a DaStGen2 object onto a plain C++ class
64 return "peano4::stacks::STDVectorStack< " + self.
_data.get_full_qualified_type() +
" >";
68 return "#include \"peano4/stacks/STDVectorStack.h\" \n \
69 #include \"" + self.
_data.namespace[-1] +
"/" + self.
_data.name +
".h\""
75 Finally construct the output
77 Pass in an instance of the output object. We use this output
78 object only to register the generated C++ file with the build
82 full_qualified_name =
""
83 for i
in self.
_data.namespace:
84 full_qualified_name += i
85 full_qualified_name +=
"::"
86 full_qualified_name += self.
_data.name
87 self.
_data.data.set_full_qualified_name(full_qualified_name)
90 output.makefile.add_cpp_file( self.
_data.subdirectory + self.
_data.namespace[-1] +
"/" + self.
_data.name +
".cpp", generated=
True )
97 Simple generator mapping a DaStGen2 object onto a plain C++ class
99 The generator is very similar to DaStGen2Generator, but it has to take
100 extra care as we assume that some objects host smart pointers. Therefore,
101 we do two things: We dump the smart pointer version, and we create a
102 flattene version, too.
110 return "peano4::stacks::STDVectorStackOverObjectsWithSmartPointers< " + self.
_data.get_full_qualified_type() +
" >";
114 return "#include \"peano4/stacks/STDVectorStackOverObjectsWithSmartPointers.h\" \n \
115 #include \"" + self.
_data.namespace[-1] +
"/" + self.
_data.name +
".h\""
121 Finally construct the output
123 Pass in an instance of the output object. We use this output
124 object only to register the generated C++ file with the build
125 environment. This part is exactly the same as for a plain 1:1
128 Further to the default generator, this routine does a little bit
131 - Make a deep copy of the data object and replace each instance of
132 a smart pointer with its plain counterpart. This new data object
133 is identified by the extension _Flattened.
134 - Make the new helper data structure include the original class with
136 - Declare this one as an embedded type via using.
137 - Add a new copy constructor/conversion routine which really just maps
138 the two data types onto each other by using the setters and getters.
139 - Replace the MPI aspect in the original object with an with the
140 variant for smart pointers
143 full_qualified_name =
""
144 for i
in self.
_data.namespace:
145 full_qualified_name += i
146 full_qualified_name +=
"::"
147 full_qualified_name += self.
_data.name
149 print(
"No of aspects for {}: {}".format( full_qualified_name, len(self.
_data.data._aspects) ))
152 flattened_data_object = copy.copy(self.
_data.data)
153 old_attributes = self.
_data.data._attributes
154 old_aspects = flattened_data_object._aspects
155 flattened_data_object._attributes = []
156 self.
_data.data._aspects = []
157 for attribute
in old_attributes:
160 cardinality = attribute._cardinality,
161 ifdefs = attribute.ifdefs
164 flattened_data_object._attributes.append( attribute )
166 for aspect
in old_aspects:
170 self.
_data.peano4_mpi_and_storage_aspect = aspect
171 self.
_data.data._aspects.append( self.
_data.peano4_mpi_and_storage_aspect )
173 self.
_data.data._aspects.append( aspect )
175 extension =
"_Flattened"
176 full_qualified_name_flattened = full_qualified_name + extension
177 full_qualified_file_without_extension_flattened = self.
_data.subdirectory + self.
_data.namespace[-1] +
"/" + self.
_data.name + extension
179 self.
_data.data.set_full_qualified_name(full_qualified_name)
181 output.makefile.add_cpp_file( self.
_data.subdirectory + self.
_data.namespace[-1] +
"/" + self.
_data.name +
".cpp", generated=
True )
183 flattened_data_object.set_full_qualified_name(full_qualified_name_flattened)
184 output.add(
DaStGen2Artefact( flattened_data_object, full_qualified_file_without_extension_flattened ) )
185 output.makefile.add_cpp_file( full_qualified_file_without_extension_flattened +
".cpp", generated=
True )
191 Default superclass for any data model in Peano which is stored within the grid
193 A DaStGen2 data type generator. To add fields to this object, just
194 use the DaStGen2 instance data of this field, i.e. data.add_attribute().
196 @image html dof-class-diagram.png
198 By default, we add x and h to the attributes. The DataModel object also can
199 host aspects, i.e. classes which inject technical code snippets into each
200 and every instance. By default, we add peano4.api.dastgen2.MPIAndStorageAspect
201 and dastgen2.aspect.MPI, but yuo might want to add further ones.
203 The actual dump into a C++ file is not done by the DaStGen2 object.
204 Instead, we hold a generator object which does this translation. In that
205 sense, the DaStGen2 object is almost an empty wrapper which tailors the
206 underlying data model, but adds no further specific behaviour.
208 There are two code generations: The default one, and then one that we have
209 to employ if the underlying data object hosts a smart pointer.
214 data: dastgen2.DataModel
215 Add elements to this guy to enrich your data model.
217 peano4_mpi_and_storage_aspect: peano4.api.dastgen2.MPIAndStorageAspect
218 This aspect adds the Peano-specific MPI routines to the data type,
219 i.e. routines used for boundary and re-balancing exchange. Modify
220 this one if you want to control certain data exchange or merge
226 I can control when to store data through the peano4_mpi_and_storage_aspect.
231 If you want to add your own MPI merge implementation, you have to
232 alter the attribute peano4_mpi_and_storage_aspect.
244 readme_descriptor =
"""
248 readme_package_descriptor =
"""
249### Data structure modelling
251Peano models its data structures via a tool called DaStGen. The actual DaStGen
252version in use is the second generation of DaStGen which is integrated into
253LLVM, e.g. The first generation of DaStGen has been a stand-alone Java tool
254which serves as a precompiler. As DaStGen 2 is not published yet, we appreciate
255a citation of the two original DaStGen papers when you discuss the memory needs:
258 @InProceedings{Bungartz:2008:DaStGen,
259 author={Bungartz, Hans--Joachim and Eckhardt, Wolfgang and Mehl, Miriam and Weinzierl, Tobias}, "
260 editor={Bubak, Marian and van Albada, Geert Dick and Dongarra, Jack and Sloot, Peter M. A.},
261 title={DaStGen---A Data Structure Generator for Parallel C++ HPC Software},
262 booktitle={Computational Science -- ICCS 2008},
264 publisher={Springer Berlin Heidelberg},
265 address={Berlin, Heidelberg}, "
267 isbn={978-3-540-69389-5}
271 @article{Bungartz:2010:DaStGen,
272 title = {A precompiler to reduce the memory footprint of multiscale PDE solvers in C++},
273 journal = {Future Generation Computer Systems},"
279 doi = {https://doi.org/10.1016/j.future.2009.05.011},
280 url = {https://www.sciencedirect.com/science/article/pii/S0167739X09000673},
281 author = {H.-J. Bungartz and W. Eckhardt and T. Weinzierl and C. Zenger},
282 keywords = {Data compaction and compression, Code generation, Multigrid and multilevel methods},
283 abstract = {A PDE solver's value is increasingly co-determined by its memory footprint, as the increase of computational multicore power overtakes the memory access speed, and as memory restricts the maximum experiment size. Tailoring a code to require less memory is technical challenging, error-prone, and hardware-dependent. Object-oriented code typically consumes much memory, though developers favour such high-level languages offering meaningful models and good maintainability. We augment the language C++ with new keywords branding records to be memory-critical. Our precompiler DaStGen then transforms this augmented specification into plain C++ optimised for low memory requirements. Hereby, it encodes multiple attributes with fixed range within one variable, and it reduces the number of bits per floating point value. The tool also generates one user-defined MPI data type per class and, thus, facilitates the construction of parallel codes with small messages.}
291 Construct a DaStGen2 object
293 We hold the data model and a dedicated data generator. By default, the data
294 model is augmented with geometric debug information. Every Peano data
295 object has an MPI aspect, i.e. can, in principle, be sent and received
298 By default, each Peano dat model also realises the MPIAndStorageAspect
299 which requires special treatment:
301 ## MPI and storage aspect
303 Normally, we just hold all the aspects in a long list and generate them one
304 by one. The MPI and storage aspect is a little bit different: If we add the
305 Peano-specific one, we still want later to modify parts of it. That is, we
306 would have to run through all the aspects one by one, pick out the MPI and
307 storage one, and then alter this one. So what we do instead is that we hold
308 it as a dedicated attribute and also add it to the list.
311 super(DaStGen2, self).
__init__(name)
327 def configure(self, namespace, association, subdirectory=""):
332 Configuring an output means setting the right output directory and
333 taking into account whether we are associated to a vertex, face or
336 I always need the MPI aspect, but I can't add the right one in the
337 constructor, as I don't know whether this DaStGen model is used for
338 vertices, faces or cells. Such context however is important to generate
339 the correct merge routines with the correct signature. Therefore, I
340 hook into this routine.
343 super(DaStGen2, self).
configure(namespace,association,subdirectory)
357 @additional_load_and_store_arguments.setter
360 for new_argument
in new_arguments:
362#include \"""" + new_argument[1].replace(
"::",
"/") +
""".h"
370 Does class host a smart pointer attribute
372 The context is important when we pick the data generator, as objects with
373 a smart poiner have to be handled differently compared to plain objects.
376 for attribute
in self.
data._attributes:
Represents on DaStGen2 object, i.e.
Represents the MPI aspect injected into a DaStGen model.
Represents the MPI aspect injected into a DaStGen model.
Represents Peano's MPI and storage aspect injected into a DaStGen model.
Specialisation of array using Peano's tarch.
Specialisation of array using Peano's tarch with a smart pointer.
Output artefact which writes one DaStGen2 data model into the project.
_file_name_without_extension
generate(self, overwrite, directory)
__init__(self, data_model, file_name_without_extension)
Simple generator mapping a DaStGen2 object onto a plain C++ class.
get_stack_container(self)
construct_output(self, output)
Finally construct the output.
get_header_file_include(self)
Simple generator mapping a DaStGen2 object onto a plain C++ class.
construct_output(self, output)
Finally construct the output.
get_stack_container(self)
get_header_file_include(self)
Default superclass for any data model in Peano which is stored within the grid.
peano4_mpi_and_storage_aspect
__init__(self, name)
Construct a DaStGen2 object.
hosts_smart_pointer_attribute(self)
Does class host a smart pointer attribute.
additional_load_and_store_arguments(self)
_additional_load_and_store_arguments
configure(self, namespace, association, subdirectory="")
Configure output.
Base class for any degree of freedom object.
_additional_load_and_store_arguments