Skip to content
Snippets Groups Projects
Commit c98480fd authored by Dominic Kempf's avatar Dominic Kempf
Browse files

Fixup generation for instationary stuff as well

parent fd6bd509
No related branches found
No related tags found
No related merge requests found
Showing
with 103 additions and 62 deletions
......@@ -89,8 +89,19 @@ function(add_generated_executable)
set(GEN_INIFILE ${CMAKE_CURRENT_SOURCE_DIR}/${GEN_INIFILE})
endif()
if(NOT GEN_SOURCE)
# Generate a driver file
set(GEN_DRIVER ${GEN_TARGET}_driver.hh)
set(GEN_FORM_COMPILER_ARGS ${GEN_FORM_COMPILER_ARGS} --driver-file ${GEN_DRIVER})
add_custom_command(OUTPUT ${GEN_DRIVER}
COMMAND ${CMAKE_BINARY_DIR}/run-in-dune-env generate_driver
--uflfile ${GEN_UFLFILE}
--ini-file ${GEN_INIFILE}
--target-name ${GEN_TARGET}
--driver-file ${GEN_DRIVER}
--project-basedir ${CMAKE_BINARY_DIR}
${GEN_FORM_COMPILER_ARGS}
DEPENDS ${GEN_UFLFILE} ${UFL2PDELAB_SOURCES} ${GEN_DEPENDS} ${DUNE_PERFTOOL_ADDITIONAL_PYTHON_SOURCES}
COMMENT "Generating driver for the target ${GEN_TARGET}"
)
set(GEN_SOURCE ${GEN_TARGET}_main.cc)
dune_module_path(MODULE dune-perftool
RESULT perftool_path
......@@ -103,15 +114,15 @@ function(add_generated_executable)
OUTPUT_VARIABLE header_deps
)
add_custom_command(OUTPUT ${GEN_DRIVER} ${header_deps}
COMMAND ${CMAKE_BINARY_DIR}/run-in-dune-env ufl2pdelab
add_custom_command(OUTPUT ${header_deps}
COMMAND ${CMAKE_BINARY_DIR}/run-in-dune-env generate_operators
--project-basedir ${CMAKE_BINARY_DIR}
${GEN_FORM_COMPILER_ARGS}
--uflfile ${GEN_UFLFILE}
--ini-file ${GEN_INIFILE}
--target-name ${GEN_TARGET}
DEPENDS ${GEN_UFLFILE} ${UFL2PDELAB_SOURCES} ${GEN_DEPENDS} ${DUNE_PERFTOOL_ADDITIONAL_PYTHON_SOURCES}
COMMENT "Running ufl2pdelab for the target ${GEN_TARGET}"
COMMENT "Generating operators for the target ${GEN_TARGET}"
)
add_executable(${GEN_TARGET} ${GEN_SOURCE} ${GEN_DRIVER} ${header_deps})
......
# Return the list of generated files for a given ini file
# This is used by the build system, do not use this yourself!
from dune.testtools.parser import parse_ini_file
import sys
ini = parse_ini_file(sys.argv[1])
section = ini["formcompiler"]
operators = section.get("operators", "operator")
result = []
for operator in [i.strip() for i in operators.split(",")]:
ssection = ini.get("formcompiler.{}".format(operator), {})
if ssection.get("filename", None):
result.append(ssection["filename"])
else:
classname = ssection.get("classname", "{}Operator".format(ssection.get("form", operator)))
result.append("{}_{}_file.hh".format(sys.argv[2], classname))
sys.stdout.write(" ".join(result))
......@@ -103,17 +103,23 @@ def read_ufl(uflfile):
return data
# This function is the entrypoint of the ufl2pdelab executable
def compile_form():
def entry_generate_driver():
""" This is the entry point for driver generation """
initialize_options()
data = read_ufl(get_option("uflfile"))
with global_context(data=data):
# Generate driver file
if get_option("driver_file"):
generate_driver()
generate_driver()
def entry_generate_operators():
""" This is the entry point for operator generation """
initialize_options()
data = read_ufl(get_option("uflfile"))
with global_context(data=data):
for operator in get_option("operators").split(","):
operator = operator.strip()
with global_context(form_identifier=operator):
# Make sure cache is empty
delete_cache_items()
......
......@@ -49,7 +49,7 @@ class PerftoolGlobalOptionsArray(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")
operators = PerftoolOption(default="r", helpstr="A comma separated list of operators, each name will be interpreted as a subsection name within the formcompiler section")
target_name = PerftoolOption(default=None, helpstr="The target name from CMake")
# Arguments that are mainly to be set by logic depending on other options
......@@ -68,7 +68,7 @@ class PerftoolFormOptionsArray(ImmutableRecord):
ImmutableRecord.__init__(self, **opts)
# Form specific options
form = PerftoolOption(default="r", helpstr="The name of the UFL object representing the form in the UFL file")
form = PerftoolOption(default=None, helpstr="The name of the UFL object representing the form in the UFL file")
filename = PerftoolOption(default=None, helpstr="The filename to use for this LocalOperator")
classname = PerftoolOption(default=None, helpstr="The name of the C++ class to generate")
numerical_jacobian = PerftoolOption(default=False, helpstr="use numerical jacobians (only makes sense, if uflpdelab for some reason fails to generate analytic jacobians)")
......@@ -139,7 +139,7 @@ def update_options_from_inifile(opt):
opt = opt.copy(**parse_ini("formcompiler"))
# Also parse form-specific options
for form in opt.operators.split(","):
for form in [i.strip() for i in opt.operators.split(",")]:
_form_options[form] = PerftoolFormOptionsArray(**parse_ini("formcompiler.{}".format(form)))
return opt
......@@ -157,13 +157,16 @@ def process_global_options(opt):
@memoize
def process_form_options(opt):
def process_form_options(opt, form):
if opt.sumfact:
opt = opt.copy(unroll_dimension_loops=True)
if opt.numerical_jacobian:
opt = opt.copy(generate_jacobians=False)
if opt.form is None:
opt = opt.copy(form=form)
if opt.classname is None:
opt = opt.copy(classname="{}Operator".format(opt.form))
......@@ -205,8 +208,8 @@ def get_form_option(key, form=None):
from dune.perftool.generation import get_global_context_value
form = get_global_context_value("form_identifier", 0)
if isinstance(form, int):
form = get_option("operators").split(",")[form]
processed_form_opts = process_form_options(_form_options[form])
form = get_option("operators").split(",")[form].strip()
processed_form_opts = process_form_options(_form_options[form], form)
return getattr(processed_form_opts, key)
......
......@@ -28,23 +28,17 @@ from dune.perftool.options import (get_form_option,
# to quantities that are needed throughout the process of generating the driver!
#
def get_form_ident(index=0):
return get_option("operators").split(",")[index]
def get_form_ident():
idents = [i.strip() for i in get_option("operators").split(",")]
if len(idents) == 2:
idents.remove("mass")
assert(len(idents) == 1)
return idents[0]
def get_form(what=None):
""" Return the ith form specified """
if what is None:
what = get_global_context_value("form_identifier", 0)
if isinstance(what, int):
what = get_form_ident(what)
def get_form():
data = get_global_context_value("data")
return data.object_by_name[get_form_option("form", what)]
def get_preprocessed_form(what=None):
from dune.perftool.ufl.preprocess import preprocess_form
return preprocess_form(get_form(what)).preprocessed_form
return data.object_by_name[get_form_option("form", get_form_ident())]
def get_dimension():
......@@ -64,10 +58,7 @@ def get_trial_element():
def is_stationary():
# TODO I am completely unsure how this should work in the future
# This only fixes instationary stuff, it will break Renes adjoint stuff
return len(get_option("operators").split(",")) == 1
# return 'mass_form' not in _driver_data
return "mass" not in [i.strip() for i in get_option("operators").split(",")]
def is_linear(form=None):
......
......@@ -77,7 +77,7 @@ def name_gridoperator(form_ident):
def typedef_localoperator(name, form_ident):
ugfs = type_trial_gfs()
vgfs = type_test_gfs()
filename = get_form_option("filename")
filename = get_form_option("filename", form_ident)
include_file(filename, filetag="driver")
lopname = localoperator_basename(form_ident)
range_type = type_range()
......
from dune.perftool.generation import (include_file,
preamble,
)
from dune.perftool.pdelab.driver import (get_trial_element,
from dune.perftool.pdelab.driver import (get_form_ident,
get_trial_element,
is_linear,
name_initree,
preprocess_leaf_data,
......@@ -50,12 +51,11 @@ def solve_instationary():
@preamble
def time_loop():
ini = name_initree()
formdata = get_formdata()
params = name_parameters(formdata)
params = name_parameters(get_form_ident())
time = name_time()
element = get_trial_element()
vector_type = type_vector(formdata)
vector = name_vector(formdata)
vector_type = type_vector(get_form_ident())
vector = name_vector(get_form_ident())
interpolate_dirichlet_data(vector)
is_dirichlet = preprocess_leaf_data(element, "is_dirichlet")
......@@ -156,8 +156,8 @@ def name_timesteppingmethod():
@preamble
def typedef_instationarygridoperator(name):
include_file("dune/pdelab/gridoperator/onestep.hh", filetag="driver")
go_type = type_gridoperator(get_formdata())
mass_go_type = type_gridoperator(get_mass_formdata())
go_type = type_gridoperator(get_form_ident())
mass_go_type = type_gridoperator("mass")
explicit = get_option('explicit_time_stepping')
if explicit:
return "using {} = Dune::PDELab::OneStepGridOperator<{},{},false>;".format(name, go_type, mass_go_type)
......@@ -173,8 +173,8 @@ def type_instationarygridoperator():
@preamble
def define_instationarygridoperator(name):
igo_type = type_instationarygridoperator()
go = name_gridoperator(get_formdata())
mass_go = name_gridoperator(get_mass_formdata())
go = name_gridoperator(get_form_ident())
mass_go = name_gridoperator("mass")
return "{} {}({}, {});".format(igo_type, name, go, mass_go)
......@@ -188,7 +188,7 @@ def typedef_onestepmethod(name):
r_type = type_range()
igo_type = type_instationarygridoperator()
snp_type = type_stationarynonlinearproblemssolver(igo_type)
vector_type = type_vector(get_formdata())
vector_type = type_vector(get_form_ident())
return "using {} = Dune::PDELab::OneStepMethod<{}, {}, {}, {}, {}>;".format(name, r_type, igo_type, snp_type, vector_type, vector_type)
......@@ -217,7 +217,7 @@ def typedef_explicitonestepmethod(name):
r_type = type_range()
igo_type = type_instationarygridoperator()
ls_type = type_linearsolver()
vector_type = type_vector(get_formdata())
vector_type = type_vector(get_form_ident())
return "using {} = Dune::PDELab::ExplicitOneStepMethod<{}, {}, {}, {}>;".format(name, r_type, igo_type, ls_type, vector_type)
......
......@@ -5,6 +5,7 @@ from dune.perftool.generation import (cached,
preamble,
)
from dune.perftool.pdelab.driver import (FEM_name_mangling,
get_form_ident,
get_trial_element,
is_stationary,
preprocess_leaf_data,
......@@ -72,7 +73,7 @@ def define_boundary_function(name, dirichlet):
lambdaname,
)
else:
params = name_parameters(get_formdata())
params = name_parameters(get_form_ident())
return "auto {} = Dune::PDELab::makeInstationaryGridFunctionFromCallable({}, {}, {});".format(name,
gv,
lambdaname,
......
......@@ -178,7 +178,7 @@ def name_stationarylinearproblemsolver():
def typedef_stationarynonlinearproblemsolver(name, go_type):
include_file("dune/pdelab/newton/newton.hh", filetag="driver")
ls_type = type_linearsolver()
x_type = type_vector(form_ident)
x_type = type_vector(get_form_ident())
return "using {} = Dune::PDELab::Newton<{}, {}, {}>;".format(name, go_type, ls_type, x_type)
......
......@@ -131,7 +131,7 @@ def visualize_initial_condition():
vtkwriter = name_vtk_sequence_writer()
element = get_trial_element()
gfs = name_trial_gfs()
vector = name_vector(get_formdata())
vector = name_vector(get_form_ident())
predicate = name_predicate()
from dune.perftool.pdelab.driver.instationary import name_time
time = name_time()
......
......@@ -250,7 +250,8 @@ def boundary_predicates(expr, measure, subdomain_id):
# Get the original form and inspect the present measures
from dune.perftool.generation import get_global_context_value
original_form = get_global_context_value("formdata").original_form
data = get_global_context_value("data")
original_form = data.object_by_name[get_form_option("form")]
sd = original_form.subdomain_data()
assert len(sd) == 1
......@@ -681,10 +682,10 @@ def generate_localoperator_kernels(operator):
logger = logging.getLogger(__name__)
data = get_global_context_value("data")
form = data.object_by_name[get_form_option("form")]
original_form = data.object_by_name[get_form_option("form")]
from dune.perftool.ufl.preprocess import preprocess_form
form = preprocess_form(form).preprocessed_form
form = preprocess_form(original_form).preprocessed_form
# Reset the generation cache
from dune.perftool.generation import delete_cache_items
......@@ -768,7 +769,7 @@ def generate_localoperator_kernels(operator):
# In the case of matrix free operator evaluation we need jacobian apply methods
if get_form_option("matrix_free"):
from dune.perftool.pdelab.driver import is_linear
if is_linear(formdata.original_form):
if is_linear(original_form):
# Numeical jacobian apply base class
base_class("Dune::PDELab::NumericalJacobianApply{}<{}>".format(which, loptype), classtag="operator")
......@@ -793,7 +794,7 @@ def generate_localoperator_kernels(operator):
if not get_form_option("numerical_jacobian"):
logger.info("generate_localoperator_kernels: create jacobian methods")
from ufl import derivative
jacform = derivative(formdata.original_form, formdata.original_form.coefficients()[0])
jacform = derivative(original_form, original_form.coefficients()[0])
from dune.perftool.ufl.preprocess import preprocess_form
jacform = preprocess_form(jacform).preprocessed_form
......
......@@ -179,13 +179,14 @@ def name_quadrature_weights():
return name
def _estimate_quadrature_order():
"""Estimate quadrature order using polynomial degree estimation from UFL"""
# According to UFL documentation estimate_total_polynomial_degree
# should only be called on preprocessed forms.
from dune.perftool.pdelab.driver import get_preprocessed_form
form = get_preprocessed_form()
data = get_global_context_value("data")
form = data.object_by_name[get_form_option("form")]
from dune.perftool.ufl.preprocess import preprocess_form
form = preprocess_form(form).preprocessed_form
# Estimate polynomial degree of integrals of current type (eg 'Cell')
integral_type = get_global_context_value("integral_type")
......
......@@ -44,7 +44,7 @@ setup(name='dune.perftool',
cmdclass={'test': PyTest},
entry_points = {
"console_scripts": [
"ufl2pdelab = dune.perftool.compile:compile_form",
"picklevecstrats = dune.perftool.sumfact.vectorization:pickle_vectorization_strategies",
"generate_operators = dune.perftool.compile:entry_generate_operators",
"generate_driver = dune.perftool.compile:entry_generate_driver",
]
})
......@@ -14,6 +14,7 @@ extension = vtu
[formcompiler]
explicit_time_stepping = 0, 1 | expand scheme
compare_l2errorsquared = 1e-7
operators = mass, poisson
# Disable explicit tests for now
{__exec_suffix} == explicit | exclude
......@@ -13,7 +13,6 @@ v = TestFunction(V)
mass = (u*v)*dx
poisson = (inner(grad(u), grad(v)) - f*v)*dx
forms = [mass, poisson]
interpolate_expression = g
is_dirichlet = 1
exact_solution = g
\ No newline at end of file
......@@ -14,6 +14,7 @@ extension = vtu
[formcompiler]
explicit_time_stepping = 0, 1 | expand scheme
compare_l2errorsquared = 1e-7
operators = mass, poisson
# Disable explicit tests for now
{__exec_suffix} == explicit | exclude
......@@ -32,7 +32,6 @@ poisson = inner(grad(u), grad(v))*dx \
mass = (u*v)*dx
forms = [mass, poisson]
interpolate_expression = g
is_dirichlet = 1
exact_solution = g
\ No newline at end of file
......@@ -14,6 +14,7 @@ extension = vtu
[formcompiler]
explicit_time_stepping = 0, 1 | expand scheme
compare_l2errorsquared = 2e-4
operators = mass, poisson
[instat]
T = 1.0
......
......@@ -16,7 +16,6 @@ v = TestFunction(V)
mass = (u*v)*dx
poisson = (inner(grad(u), grad(v)) - f*v)*dx
forms = [mass, poisson]
interpolate_expression = g
is_dirichlet = 1
exact_solution = g
......@@ -13,5 +13,11 @@ name = {__name}
extension = vtu
[formcompiler]
explicit_time_stepping = 1
operators = mass, r
[formcompiler.mass]
numerical_jacobian = 1
[formcompiler.r]
numerical_jacobian = 1
explicit_time_stepping = 1
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment