From 87a7a367ed04dc6d010d5e02792764c2be768f65 Mon Sep 17 00:00:00 2001 From: Dominic Kempf <dominic.kempf@iwr.uni-heidelberg.de> Date: Mon, 29 Jan 2018 11:29:36 +0100 Subject: [PATCH] Introduce separate PerftoolFormOptionsArray --- python/dune/perftool/options.py | 77 +++++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 24 deletions(-) diff --git a/python/dune/perftool/options.py b/python/dune/perftool/options.py index bc96b7d7..8ed41f79 100644 --- a/python/dune/perftool/options.py +++ b/python/dune/perftool/options.py @@ -25,10 +25,10 @@ class PerftoolOption(ImmutableRecord): ) -class PerftoolOptionsArray(ImmutableRecord): +class PerftoolGlobalOptionsArray(ImmutableRecord): """ A collection of form compiler arguments """ def __init__(self, **kwargs): - opts = {k: v.default for k, v in PerftoolOptionsArray.__dict__.items() if isinstance(v, PerftoolOption)} + opts = {k: v.default for k, v in PerftoolGlobalOptionsArray.__dict__.items() if isinstance(v, PerftoolOption)} opts.update(**kwargs) ImmutableRecord.__init__(self, **opts) @@ -49,13 +49,24 @@ class PerftoolOptionsArray(ImmutableRecord): yaspgrid_offset = PerftoolOption(default=False, helpstr="Set to true if you want a yasp grid where the lower left corner is not in the origin.") precision_bits = PerftoolOption(default=64, helpstr="The number of bits for the floating point type") overlapping = PerftoolOption(default=False, helpstr="Use an overlapping solver and constraints. You still need to make sure to construct a grid with overlap! The parallel option will be set automatically.") + operators = PerftoolOption(default="operator", helpstr="A comma separated list of operators, each name will be interpreted as a subsection name within the formcompiler section") # Arguments that are mainly to be set by logic depending on other options max_vector_width = PerftoolOption(default=256, helpstr=None) parallel = PerftoolOption(default=False, helpstr="Mark that this program should be run in parallel. If set to true the c++ code will check that there are more than 1 MPI-ranks involved and the error computation will use communication.") - # Form specific options + #TODO: should be form specific operator_file = PerftoolOption(helpstr="The filename for the generated local operator header") + + +class PerftoolFormOptionsArray(ImmutableRecord): + """ A collection of form-specific form compiler arguments """ + def __init__(self, **kwargs): + opts = {k: v.default for k, v in PerftoolFormOptionsArray.__dict__.items() if isinstance(v, PerftoolOption)} + opts.update(**kwargs) + ImmutableRecord.__init__(self, **opts) + + # Form specific options numerical_jacobian = PerftoolOption(default=False, helpstr="use numerical jacobians (only makes sense, if uflpdelab for some reason fails to generate analytic jacobians)") matrix_free = PerftoolOption(default=False, helpstr="Use iterative solver with matrix free jacobian application") print_transformations = PerftoolOption(default=False, helpstr="print out dot files after ufl tree transformations") @@ -82,19 +93,20 @@ class PerftoolOptionsArray(ImmutableRecord): # Until more sophisticated logic is needed, we keep the actual option data in this module -_options = PerftoolOptionsArray() +_global_options = PerftoolGlobalOptionsArray() +_form_options = {} def initialize_options(): """ Initialize the options from the command line """ - global _options - _options = update_options_from_commandline(_options) - _options = update_options_from_inifile(_options) + global _global_options + _global_options = update_options_from_commandline(_global_options) + _global_options = update_options_from_inifile(_global_options) def update_options_from_commandline(opt): """ Return an options array object with updated values from the commandline """ - assert isinstance(opt, PerftoolOptionsArray) + assert isinstance(opt, PerftoolGlobalOptionsArray) parser = ArgumentParser(description="Compile UFL files to PDELab C++ code", epilog="Please report bugs to dominic.kempf@iwr.uni-heidelberg.de", ) @@ -110,32 +122,44 @@ def update_options_from_commandline(opt): def update_options_from_inifile(opt): """ Return an options array object with updated values from an inifile """ if opt.ini_file: - def _fix_types(k, v): - if hasattr(type(opt), k) and getattr(type(opt), k).type is bool: - return bool(eval(v)) - if hasattr(type(opt), k): - return getattr(type(opt), k).type(v) - return v - ini = parse_ini_file(opt.ini_file).get("formcompiler", {}) - ini = {k: _fix_types(k, v) for k, v in ini.items()} - opt = opt.copy(**ini) + def parse_ini(section): + def _fix_types(k, v): + if hasattr(type(opt), k) and getattr(type(opt), k).type is bool: + return bool(eval(v)) + if hasattr(type(opt), k): + return getattr(type(opt), k).type(v) + return v + ini = parse_ini_file(opt.ini_file).get(section, {}) + return {k: _fix_types(k, v) for k, v in ini.items()} + + opt = opt.copy(**parse_ini("formcompiler")) + + # Also parse form-specific options + for form in opt.operators.split(","): + _form_options[form] = PerftoolFormOptionsArray(**parse_ini("formcompiler.{}".format(form))) + return opt @memoize -def process_options(opt): +def process_global_options(opt): """ Make sure that the options have been fully processed """ opt = expand_architecture_options(opt) + if opt.overlapping: + opt = opt.copy(parallel=True) + + return opt + + +@memoize +def process_form_options(opt): if opt.sumfact: opt = opt.copy(unroll_dimension_loops=True) if opt.numerical_jacobian: opt = opt.copy(generate_jacobians=False) - if opt.overlapping: - opt = opt.copy(parallel=True) - return opt @@ -157,12 +181,17 @@ def set_option(key, value): overwritten. Form compiler arguments will always be set before any other options. """ - global _options - _options = process_options(_options).copy(**{key: value}) + global _global_options + _global_options = process_options(_global_options).copy(**{key: value}) def get_option(key): - return getattr(process_options(_options), key) + processed_global_opts = process_global_options(_global_options) + if hasattr(processed_global_opts, key): + return getattr(processed_global_opts, key) + else: + processed_form_opts = process_form_options(_form_options["operator"]) + return getattr(processed_form_opts, key) def option_switch(opt): -- GitLab