def gen_code(self, parent): from f2pygen import AssignGen # We copy one element of field A (first arg) to the # corresponding element of field B (second arg). invar_name = self.array_ref(self._arguments.args[0].proxy_name) outvar_name = self.array_ref(self._arguments.args[1].proxy_name) parent.add(AssignGen(parent, lhs=outvar_name, rhs=invar_name))
def gen_code(self, parent): from f2pygen import AssignGen # In this case we're assigning a single scalar value to all # elements of a field. var_name = self.array_ref(self._arguments.args[1].proxy_name) value = self._arguments.args[0] parent.add(AssignGen(parent, lhs=var_name, rhs=value))
def gen_code(self, parent): from f2pygen import AssignGen # We sum the DoF-wise product of the supplied fields. The variable # holding the sum is initialised to zero in the psy layer. sum_name = self._reduction_ref(self._arguments.args[1].name) invar_name1 = self.array_ref(self._arguments.args[0].proxy_name) rhs_expr = sum_name + "+" + invar_name1 + "*" + invar_name1 parent.add(AssignGen(parent, lhs=sum_name, rhs=rhs_expr))
def gen_code(self, parent): from f2pygen import AssignGen # We add each element of f1 to the corresponding element of f2 # and store the result back in f1. invar_name1 = self.array_ref(self._arguments.args[0].proxy_name) invar_name2 = self.array_ref(self._arguments.args[1].proxy_name) parent.add(AssignGen(parent, lhs=invar_name1, rhs=invar_name1 + " + " + invar_name2))
def gen_code(self, parent): from f2pygen import AssignGen # In this case we're raising each element of a field to a # supplied scalar value. var_name = self.array_ref(self._arguments.args[0].proxy_name) value = self._arguments.args[1].name parent.add(AssignGen(parent, lhs=var_name, rhs=var_name + "**" + value))
def gen_code(self, parent): from f2pygen import AssignGen # Sum all the elements of a field. The variable holding the # sum is initialised to zero in the psy layer. fld_name = self.array_ref(self._arguments.args[0].proxy_name) sum_name = self._reduction_ref(self._arguments.args[1].name) rhs_expr = sum_name + "+" + fld_name parent.add(AssignGen(parent, lhs=sum_name, rhs=rhs_expr))
def gen_code(self, parent): from f2pygen import AssignGen # We multiply each element of f1 by the scalar argument and # store the result in f2. scalar_name = self._arguments.args[0].name invar_name = self.array_ref(self._arguments.args[1].proxy_name) outvar_name = self.array_ref(self._arguments.args[2].proxy_name) parent.add(AssignGen(parent, lhs=outvar_name, rhs=scalar_name + " * " + invar_name))
def gen_code(self, parent): from f2pygen import AssignGen # We divide each element of f1 by the corresponding element of # f2 and store the result in f3. invar_name1 = self.array_ref(self._arguments.args[0].proxy_name) invar_name2 = self.array_ref(self._arguments.args[1].proxy_name) outvar_name = self.array_ref(self._arguments.args[2].proxy_name) parent.add(AssignGen(parent, lhs=outvar_name, rhs=invar_name1 + " / " + invar_name2))
def gen_code(self, parent): from f2pygen import AssignGen # We multiply one element of field f2 (3rd arg) by a scalar (2nd arg), # add it to the corresponding element of a first field f1 (1st arg) # and write the value back into the element of field f1. scalar_name = self._arguments.args[1].name invar_name1 = self.array_ref(self._arguments.args[0].proxy_name) invar_name2 = self.array_ref(self._arguments.args[2].proxy_name) rhs_expr = invar_name1 + " + " + scalar_name + "*" + invar_name2 parent.add(AssignGen(parent, lhs=invar_name1, rhs=rhs_expr))
def gen_code(self, parent): from f2pygen import AssignGen # We subtract each element of f2 from the corresponding element # of f1 and store the result in f3. invar_name1 = self.array_ref(self._arguments.args[0].proxy_name) invar_name2 = self.array_ref(self._arguments.args[1].proxy_name) outvar_name = self.array_ref(self._arguments.args[2].proxy_name) assign = AssignGen(parent, lhs=outvar_name, rhs=invar_name1 + " - " + invar_name2) parent.add(assign)
def gen_code(self, parent): from f2pygen import AssignGen # We multiply one element of field f1 (2nd arg) by a scalar # (1st arg), add it to the corresponding element of a # second field (3rd arg) and write the value back into # the element of field f1. scalar_name = self._arguments.args[0].name fld_name1 = self.array_ref(self._arguments.args[1].proxy_name) fld_name2 = self.array_ref(self._arguments.args[2].proxy_name) rhs_expr = scalar_name + "*" + fld_name1 + " + " + fld_name2 parent.add(AssignGen(parent, lhs=fld_name1, rhs=rhs_expr))
def gen_code(self, parent): from f2pygen import AssignGen # We multiply one element of field f1 (2nd arg) by a scalar # (1st arg), add it to the corresponding # element of a second field (3rd arg) and write the value to the # corresponding element of field f3 (4th arg). scalar_name = self._arguments.args[0].name invar_name1 = self.array_ref(self._arguments.args[1].proxy_name) invar_name2 = self.array_ref(self._arguments.args[2].proxy_name) outvar_name = self.array_ref(self._arguments.args[3].proxy_name) rhs_expr = scalar_name + "*" + invar_name1 + " + " + invar_name2 parent.add(AssignGen(parent, lhs=outvar_name, rhs=rhs_expr))
def gen_code(self, parent): from f2pygen import AssignGen # We multiply one element of field f1 (2nd arg) by the first scalar # (1st arg), add it to the product of the corresponding element of # a second field (4th arg) with the second scalar (4rd arg) and # write the value back into the element of field f1. scalar_name1 = self._arguments.args[0].name scalar_name2 = self._arguments.args[2].name invar_name1 = self.array_ref(self._arguments.args[1].proxy_name) invar_name2 = self.array_ref(self._arguments.args[3].proxy_name) rhs_expr = (scalar_name1 + "*" + invar_name1 + " + " + scalar_name2 + "*" + invar_name2) parent.add(AssignGen(parent, lhs=invar_name1, rhs=rhs_expr))
def gen_code(self, parent): ''' Generates dynamo version 0.1 specific psy code for a call to the dynamo kernel instance. ''' from f2pygen import CallGen, DeclGen, AssignGen, UseGen # TODO: we simply choose the first field as the lookup for the moment field_name = self.arguments.args[0].name # add a dofmap lookup using first field. # TODO: This needs to be generalised to work for multiple dofmaps parent.add( CallGen(parent, field_name + "%vspace%get_cell_dofmap", ["cell", "map"])) parent.add(DeclGen(parent, datatype="integer", entity_decls=["cell"])) parent.add( DeclGen(parent, datatype="integer", pointer=True, entity_decls=["map(:)"])) # create the argument list on the fly so we can also create # appropriate variables and lookups arglist = [] arglist.append("nlayers") arglist.append("ndf") arglist.append("map") found_gauss_quad = False gauss_quad_arg = None for arg in self._arguments.args: if arg.requires_basis: basis_name = arg.function_space + "_basis_" + arg.name arglist.append(basis_name) new_parent, position = parent.start_parent_loop() new_parent.add(CallGen(new_parent, field_name + "%vspace%get_basis", [basis_name]), position=["before", position]) parent.add( DeclGen(parent, datatype="real", kind="dp", pointer=True, entity_decls=[basis_name + "(:,:,:,:,:)"])) if arg.requires_diff_basis: raise GenerationError("differential basis has not yet " "been coded") if arg.requires_gauss_quad: if found_gauss_quad: raise GenerationError("found more than one gaussian " "quadrature in this kernel") found_gauss_quad = True gauss_quad_arg = arg dataref = "%data" arglist.append(arg.name + dataref) if found_gauss_quad: gq_name = "gaussian_quadrature" arglist.append(gauss_quad_arg.name + "%" + gq_name) # generate the kernel call and associated use statement parent.add(CallGen(parent, self._name, arglist)) if not self.module_inline: parent.add( UseGen(parent, name=self._module_name, only=True, funcnames=[self._name])) # declare and initialise the number of layers and the number # of degrees of freedom. Needs to be generalised. parent.add( DeclGen(parent, datatype="integer", entity_decls=["nlayers", "ndf"])) new_parent, position = parent.start_parent_loop() new_parent.add(AssignGen(new_parent, lhs="nlayers", rhs=field_name + "%get_nlayers()"), position=["before", position]) new_parent.add(AssignGen(new_parent, lhs="ndf", rhs=field_name + "%vspace%get_ndf()"), position=["before", position])
def gen_code(self, parent): ''' Generates GOcean specific invocation code (the subroutine called by the associated invoke call in the algorithm layer). This consists of the PSy invocation subroutine and the declaration of its arguments.''' from f2pygen import SubroutineGen, DeclGen, TypeDeclGen, CommentGen,\ AssignGen # create the subroutine invoke_sub = SubroutineGen(parent, name=self.name, args=self.psy_unique_var_names) parent.add(invoke_sub) # add declarations for the variables holding the upper bounds # of loops in i and j if self.schedule.const_loop_bounds: invoke_sub.add( DeclGen(invoke_sub, datatype="INTEGER", entity_decls=[ self.schedule.iloop_stop, self.schedule.jloop_stop ])) # Generate the code body of this subroutine self.schedule.gen_code(invoke_sub) # add the subroutine argument declarations for fields if len(self.unique_args_arrays) > 0: my_decl_arrays = TypeDeclGen(invoke_sub, datatype="r2d_field", intent="inout", entity_decls=self.unique_args_arrays) invoke_sub.add(my_decl_arrays) # add the subroutine argument declarations for real scalars if len(self.unique_args_rscalars) > 0: my_decl_rscalars = DeclGen(invoke_sub, datatype="REAL", intent="inout", kind="wp", entity_decls=self.unique_args_rscalars) invoke_sub.add(my_decl_rscalars) # add the subroutine argument declarations for integer scalars if len(self.unique_args_iscalars) > 0: my_decl_iscalars = DeclGen(invoke_sub, datatype="INTEGER", intent="inout", entity_decls=self.unique_args_iscalars) invoke_sub.add(my_decl_iscalars) if self._schedule.const_loop_bounds and \ len(self.unique_args_arrays) > 0: # Look-up the loop bounds using the first field object in the # list sim_domain = self.unique_args_arrays[0] +\ "%grid%simulation_domain%" position = invoke_sub.last_declaration() invoke_sub.add(CommentGen(invoke_sub, ""), position=["after", position]) invoke_sub.add(AssignGen(invoke_sub, lhs=self.schedule.jloop_stop, rhs=sim_domain + "ystop"), position=["after", position]) invoke_sub.add(AssignGen(invoke_sub, lhs=self.schedule.iloop_stop, rhs=sim_domain + "xstop"), position=["after", position]) invoke_sub.add(CommentGen(invoke_sub, " Look-up loop bounds"), position=["after", position]) invoke_sub.add(CommentGen(invoke_sub, ""), position=["after", position])