def integrate_assemble_p0(family, degree): power = 5 m = UnitSquareMesh(2**power, 2**power) layers = 10 # Populate the coordinates of the extruded mesh by providing the # coordinates as a field. # TODO: provide a kernel which will describe how coordinates are extruded. mesh = ExtrudedMesh(m, layers, layer_height=0.1) fs = FunctionSpace(mesh, family, degree, name="fs") f = Function(fs) fs1 = FunctionSpace(mesh, family, degree, name="fs1") f_rhs = Function(fs1) populate_p0 = op2.Kernel( """ void populate_tracer(double *x[], double *c[]) { x[0][0] = (c[1][2] + c[0][2]) / 2; }""", "populate_tracer") coords = f.function_space().mesh().coordinates op2.par_loop(populate_p0, f.cell_set, f.dat(op2.INC, f.cell_node_map()), coords.dat(op2.READ, coords.cell_node_map())) volume = op2.Kernel( """ void comp_vol(double *rhs[], double *x[], double *y[]) { double area = x[0][0]*(x[2][1]-x[4][1]) + x[2][0]*(x[4][1]-x[0][1]) + x[4][0]*(x[0][1]-x[2][1]); if (area < 0) area = area * (-1.0); rhs[0][0] += 0.5 * area * (x[1][2] - x[0][2]) * y[0][0]; }""", "comp_vol") op2.par_loop(volume, f.cell_set, f_rhs.dat(op2.WRITE, f_rhs.cell_node_map()), coords.dat(op2.READ, coords.cell_node_map()), f.dat(op2.READ, f.cell_node_map())) g = op2.Global(1, data=0.0, name='g') reduction = op2.Kernel( """ void comp_reduction(double A[1], double *x[]) { A[0] += x[0][0]; }""", "comp_reduction") op2.par_loop(reduction, f_rhs.cell_set, g(op2.INC), f_rhs.dat(op2.READ, f_rhs.cell_node_map())) return np.abs(g.data[0] - 0.5)
def integrate_unit_square(family, degree): power = 5 m = UnitIntervalMesh(2**power) layers = 10 # Populate the coordinates of the extruded mesh by providing the # coordinates as a field. # A kernel which describes how coordinates are extruded. mesh = ExtrudedMesh(m, layers, layer_height=0.1) fs = FunctionSpace(mesh, family, degree, name="fs") f = Function(fs) area = op2.Kernel( """ void comp_area(double A[1], double *x[], double *y[]) { double area = (x[1][1]-x[0][1])*(x[2][0]-x[0][0]); if (area < 0) area = area * (-1.0); A[0] += area; }""", "comp_area") g = op2.Global(1, data=0.0, name='g') coords = f.function_space().mesh().coordinates op2.par_loop(area, f.cell_set, g(op2.INC), coords.dat(op2.READ, coords.cell_node_map()), f.dat(op2.READ, f.cell_node_map())) return np.abs(g.data[0] - 1.0)
def integrate_rhs(family, degree): power = 5 m = UnitSquareMesh(2**power, 2**power) layers = 10 # Populate the coordinates of the extruded mesh by providing the # coordinates as a field. # TODO: provide a kernel which will describe how coordinates are extruded. mesh = ExtrudedMesh(m, layers, layer_height=0.1) horiz = ufl.FiniteElement(family, "triangle", degree) vert = ufl.FiniteElement(family, "interval", degree) prod = ufl.TensorProductElement(horiz, vert) fs = FunctionSpace(mesh, prod, name="fs") f = Function(fs) populate_p0 = op2.Kernel( """ void populate_tracer(double *x[], double *c[]) { x[0][0] = ((c[1][2] + c[0][2]) / 2); }""", "populate_tracer") coords = f.function_space().mesh().coordinates op2.par_loop(populate_p0, f.cell_set, f.dat(op2.INC, f.cell_node_map()), coords.dat(op2.READ, coords.cell_node_map())) g = assemble(f * dx) return np.abs(g - 0.5)
def _form_string_kernel(body, measure, args, **kwargs): kargs = [] if body.find("][") >= 0: warning("""Your kernel body contains a double indirection.\n""" """You should update it to single indirections.\n""" """\n""" """Mail [email protected] for advice.\n""") for var, (func, intent) in args.items(): if isinstance(func, constant.Constant): if intent is not READ: raise RuntimeError("Only READ access is allowed to Constant") # Constants modelled as Globals, so no need for double # indirection ndof = func.dat.cdim kargs.append(ast.Decl(ScalarType_c, ast.Symbol(var, (ndof, )), qualifiers=["const"])) else: # Do we have a component of a mixed function? if isinstance(func, Indexed): c, i = func.ufl_operands idx = i._indices[0]._value ndof = c.function_space()[idx].finat_element.space_dimension() else: if len(func.function_space()) > 1: raise NotImplementedError("Must index mixed function in par_loop.") ndof = func.function_space().finat_element.space_dimension() if measure.integral_type() == 'interior_facet': ndof *= 2 kargs.append(ast.Decl(ScalarType_c, ast.Symbol(var, (ndof, )))) body = body.replace(var+".dofs", str(ndof)) return pyop2.Kernel(ast.FunDecl("void", "par_loop_kernel", kargs, ast.FlatBlock(body), pred=["static"]), "par_loop_kernel", **kwargs)
def _form_loopy_kernel(kernel_domains, instructions, measure, args, **kwargs): kargs = [] for var, (func, intent) in args.items(): if isinstance(func, constant.Constant): if intent is not READ: raise RuntimeError("Only READ access is allowed to Constant") # Constants modelled as Globals, so no need for double # indirection ndof = func.dat.cdim kargs.append(loopy.GlobalArg(var, dtype=func.dat.dtype, shape=(ndof,))) else: # Do we have a component of a mixed function? if isinstance(func, Indexed): c, i = func.ufl_operands idx = i._indices[0]._value ndof = c.function_space()[idx].finat_element.space_dimension() cdim = c.dat[idx].cdim dtype = c.dat[idx].dtype else: if func.function_space().ufl_element().family() == "Real": ndof = func.function_space().dim() # == 1 kargs.append(loopy.GlobalArg(var, dtype=func.dat.dtype, shape=(ndof,))) continue else: if len(func.function_space()) > 1: raise NotImplementedError("Must index mixed function in par_loop.") ndof = func.function_space().finat_element.space_dimension() cdim = func.dat.cdim dtype = func.dat.dtype if measure.integral_type() == 'interior_facet': ndof *= 2 # FIXME: shape for facets [2][ndof]? kargs.append(loopy.GlobalArg(var, dtype=dtype, shape=(ndof, cdim))) kernel_domains = kernel_domains.replace(var+".dofs", str(ndof)) if kernel_domains == "": kernel_domains = "[] -> {[]}" try: key = (kernel_domains, tuple(instructions), tuple(map(tuple, kwargs.items()))) if kernel_cache is not None: return kernel_cache[key] else: raise KeyError("No cache") except KeyError: kargs.append(...) knl = loopy.make_function(kernel_domains, instructions, kargs, seq_dependencies=True, name="par_loop_kernel", silenced_warnings=["summing_if_branches_ops"], target=loopy.CTarget()) knl = pyop2.Kernel(knl, "par_loop_kernel", **kwargs) if kernel_cache is not None: return kernel_cache.setdefault(key, knl) else: return knl
def _form_kernel(kernel, measure, args, **kwargs): kargs = [] lkernel = kernel for var, (func, intent) in args.iteritems(): if isinstance(func, constant.Constant): if intent is not READ: raise RuntimeError("Only READ access is allowed to Constant") # Constants modelled as Globals, so no need for double # indirection ndof = func.dat.cdim kargs.append( ast.Decl("double", ast.Symbol(var, (ndof, )), qualifiers=["const"])) else: # Do we have a component of a mixed function? if isinstance(func, Indexed): c, i = func.ufl_operands idx = i._indices[0]._value ndof = c.function_space()[idx].finat_element.space_dimension() else: if len(func.function_space()) > 1: raise NotImplementedError( "Must index mixed function in par_loop.") ndof = func.function_space().finat_element.space_dimension() if measure.integral_type() == 'interior_facet': ndof *= 2 if measure is direct: kargs.append(ast.Decl("double", ast.Symbol(var, (ndof, )))) else: kargs.append(ast.Decl("double *", ast.Symbol(var, (ndof, )))) lkernel = lkernel.replace(var + ".dofs", str(ndof)) body = ast.FlatBlock(lkernel) return pyop2.Kernel(ast.FunDecl("void", "par_loop_kernel", kargs, body), "par_loop_kernel", **kwargs)
def __init__(self, dim = 2, algo = 1, nbrPtfxIte=1, nbrAdap = 1, nbrSpl = 0, adaptStepFreq = 0, p = 2, N = 1000, a = 1000, hmin = 0.005, hmax = 0.3, steadyMetric = 1, T = 6, Tend = 1, n = 50, cfl = 0.95, nbrSav = 0, nbrSavTot = 0, dtSav = 0, snes_rtol = 1e8, ksp_rtol = 1e-5) : self.dim = dim # adaptation parameters self.algo = algo # 1 for ptfx, 2 for frequent remeshes self.nbrPtfxIte = nbrPtfxIte self.nbrAdap = nbrAdap self.nbrSpl = nbrSpl # including initial and final samples, so this is the actual number self.adaptStepFreq = adaptStepFreq # metrics computation parameters self.p = p self.N = N self.a = a self.hmin = hmin self.hmax = hmax self.steadyMetric = steadyMetric # if algo = 2, 1 for pain 2001, 2 for fluidity, 3 for loseille 2011 # solver parameters self.T = T self.Tend = Tend self.n = n self.cfl = cfl self.nbrSav = nbrSav # number of sol saved per sub-interval in algo 1 initial save does not count (so I actually save nbrSav+1) self.nbrSavTot = nbrSavTot # total number of solutions saved for algo 2 self.dtSav = dtSav self.nbrGlobSav = 0 # keep track of the number of saved solutions if nbrSavTot > 0: self.dtSav = self.Tend/self.nbrSavTot self.nbrSav = 0 # Petsc SNES parameters for Hessian computation self.snes_rtol = snes_rtol self.ksp_rtol = ksp_rtol op2.init() if self.dim == 2: self.absValHessian_kernel = op2.Kernel(""" void absValHessian(double * hess, double *lbdMin) { double lmin = *lbdMin; %s %s %s %s } """ % (computeEigVal_str, absValueHessian_str, truncLowHessian_str, rebuildHessian_str), "absValHessian") else: self.absValHessian_kernel = op2.Kernel(""" void absValHessian(double * hess, double *lbdMin) { double lmin = *lbdMin; %s %s %s %s } """ % (computeEigVal3_str, absValueHessian3_str, truncLowHessian3_str, rebuildHessian3_str), "absValHessian") # usa2 = 1./(self.a*self.a) # ushmin2 = 1./(self.hmin*self.hmin) # ushmax2 = 1./(self.hmax*self.hmax) # op2.Const(1, ushmax2, dtype=float, name="lbdMin"); # op2.Const(1, ushmin2, dtype=float, name="lbdMax"); # op2.Const(1, usa2, dtype=float, name="usa2"); if self.dim == 2: self.absTruncMetric_kernel = op2.Kernel(""" void absTruncMetric_kernel(double * hess, double *lbdmin, double *lbdmax, double *usa2_p) { double lmin = *lbdmin; double lmax = *lbdmax; double usa2 = *usa2_p; %s %s %s %s %s } """ % (computeEigVal_str, truncLowHessian_str, truncHighHessian_str, truncRatioHessian_str, rebuildHessian_str), "absTruncMetric_kernel") else: self.absTruncMetric_kernel = op2.Kernel(""" void absTruncMetric_kernel(double * hess, double *lbdmin, double *lbdmax, double *usa2_p) { double lmin = *lbdmin; double lmax = *lbdmax; double usa2 = *usa2_p; %s %s %s %s %s } """ % (computeEigVal3_str, truncLowHessian3_str, truncHighHessian3_str, truncRatioHessian3_str, rebuildHessian3_str), "absTruncMetric_kernel")