Reference Guide  2.5.0
psyclone.dynamo0p3.DynMeshes Class Reference

Public Member Functions

def __init__ (self, invoke, unique_psy_vars)
 
def declarations (self, parent)
 
def initialise (self, parent)
 
def intergrid_kernels (self)
 

Detailed Description

Holds all mesh-related information (including colour maps if
required).  If there are no inter-grid kernels then there is only
one mesh object required (when calling kernels with operates_on==domain,
colouring, doing distributed memory or querying the reference element).
However, kernels performing inter-grid operations require multiple mesh
objects as well as mesh maps and other quantities.

There are two types of inter-grid operation; the first is "prolongation"
where a field on a coarse mesh is mapped onto a fine mesh. The second
is "restriction" where a field on a fine mesh is mapped onto a coarse
mesh.

:param invoke: the Invoke for which to extract information on all \
               required inter-grid operations.
:type invoke: :py:class:`psyclone.dynamo0p3.LFRicInvoke`
:param unique_psy_vars: list of arguments to the PSy-layer routine.
:type unique_psy_vars: list of \
                  :py:class:`psyclone.dynamo0p3.DynKernelArgument` objects.

Definition at line 2028 of file dynamo0p3.py.

Member Function Documentation

◆ declarations()

def psyclone.dynamo0p3.DynMeshes.declarations (   self,
  parent 
)
Declare variables specific to mesh objects.

:param parent: the parent node to which to add the declarations
:type parent: :py:class:`psyclone.f2pygen.BaseGen`

Definition at line 2243 of file dynamo0p3.py.

2243  def declarations(self, parent):
2244  '''
2245  Declare variables specific to mesh objects.
2246 
2247  :param parent: the parent node to which to add the declarations
2248  :type parent: :py:class:`psyclone.f2pygen.BaseGen`
2249 
2250  '''
2251  # pylint: disable=too-many-locals, too-many-statements
2252  api_config = Config.get().api_conf("dynamo0.3")
2253  const = LFRicConstants()
2254 
2255  # Since we're now generating code, any transformations must
2256  # have been applied so we can set-up colourmap information
2257  self._colourmap_init()
2258 
2259  # We'll need various typedefs from the mesh module
2260  mtype = const.MESH_TYPE_MAP["mesh"]["type"]
2261  mmod = const.MESH_TYPE_MAP["mesh"]["module"]
2262  mmap_type = const.MESH_TYPE_MAP["mesh_map"]["type"]
2263  mmap_mod = const.MESH_TYPE_MAP["mesh_map"]["module"]
2264  if self._mesh_tag_names:
2265  name = self._symbol_table.lookup_with_tag(mtype).name
2266  parent.add(UseGen(parent, name=mmod, only=True,
2267  funcnames=[name]))
2268  if self.intergrid_kernels:
2269  parent.add(UseGen(parent, name=mmap_mod, only=True,
2270  funcnames=[mmap_type]))
2271  # Declare the mesh object(s) and associated halo depths
2272  for tag_name in self._mesh_tag_names:
2273  name = self._symbol_table.lookup_with_tag(tag_name).name
2274  parent.add(TypeDeclGen(parent, pointer=True, datatype=mtype,
2275  entity_decls=[name + " => null()"]))
2276  # For each mesh we also need the maximum halo depth.
2277  if Config.get().distributed_memory:
2278  name = self._symbol_table.lookup_with_tag(
2279  f"max_halo_depth_{tag_name}").name
2280  parent.add(DeclGen(parent, datatype="integer",
2281  kind=api_config.default_kind["integer"],
2282  entity_decls=[name]))
2283 
2284  # Declare the inter-mesh map(s) and cell map(s)
2285  for kern in self.intergrid_kernels:
2286  parent.add(TypeDeclGen(parent, pointer=True,
2287  datatype=mmap_type,
2288  entity_decls=[kern.mmap + " => null()"]))
2289  parent.add(
2290  DeclGen(parent, pointer=True, datatype="integer",
2291  kind=api_config.default_kind["integer"],
2292  entity_decls=[kern.cell_map + "(:,:,:) => null()"]))
2293 
2294  # Declare the number of cells in the fine mesh and how many fine
2295  # cells there are per coarse cell
2296  parent.add(DeclGen(parent, datatype="integer",
2297  kind=api_config.default_kind["integer"],
2298  entity_decls=[kern.ncell_fine,
2299  kern.ncellpercellx,
2300  kern.ncellpercelly]))
2301  # Declare variables to hold the colourmap information if required
2302  if kern.colourmap_symbol:
2303  parent.add(
2304  DeclGen(parent, datatype="integer",
2305  kind=api_config.default_kind["integer"],
2306  pointer=True,
2307  entity_decls=[kern.colourmap_symbol.name+"(:,:)"]))
2308  parent.add(
2309  DeclGen(parent, datatype="integer",
2310  kind=api_config.default_kind["integer"],
2311  entity_decls=[kern.ncolours_var_symbol.name]))
2312  # The cell-count array is 2D if we go into the halo and 1D
2313  # otherwise (i.e. no DM or this kernel is GH_WRITE only and
2314  # does not access the halo).
2315  dim_list = len(kern.last_cell_var_symbol.datatype.shape)*":"
2316  decln = (f"{kern.last_cell_var_symbol.name}("
2317  f"{','.join(dim_list)})")
2318  parent.add(
2319  DeclGen(parent, datatype="integer", allocatable=True,
2320  kind=api_config.default_kind["integer"],
2321  entity_decls=[decln]))
2322 
2323  if not self.intergrid_kernels and (self._needs_colourmap or
2324  self._needs_colourmap_halo):
2325  # There aren't any inter-grid kernels but we do need
2326  # colourmap information
2327  base_name = "cmap"
2328  csym = self._schedule.symbol_table.lookup_with_tag("cmap")
2329  colour_map = csym.name
2330  # No. of colours
2331  base_name = "ncolour"
2332  ncolours = \
2333  self._schedule.symbol_table.find_or_create_tag(base_name).name
2334  # Add declarations for these variables
2335  parent.add(DeclGen(parent, datatype="integer",
2336  kind=api_config.default_kind["integer"],
2337  pointer=True,
2338  entity_decls=[colour_map+"(:,:)"]))
2339  parent.add(DeclGen(parent, datatype="integer",
2340  kind=api_config.default_kind["integer"],
2341  entity_decls=[ncolours]))
2342  if self._needs_colourmap_halo:
2343  last_cell = self._symbol_table.find_or_create_tag(
2344  "last_halo_cell_all_colours")
2345  parent.add(DeclGen(parent, datatype="integer",
2346  kind=api_config.default_kind["integer"],
2347  allocatable=True,
2348  entity_decls=[last_cell.name+"(:,:)"]))
2349  if self._needs_colourmap:
2350  last_cell = self._symbol_table.find_or_create_tag(
2351  "last_edge_cell_all_colours")
2352  parent.add(DeclGen(parent, datatype="integer",
2353  kind=api_config.default_kind["integer"],
2354  allocatable=True,
2355  entity_decls=[last_cell.name+"(:)"]))
2356 

References psyclone.dynamo0p3.DynMeshes._colourmap_init(), psyclone.dynamo0p3.DynMeshes._mesh_tag_names, psyclone.dynamo0p3.DynMeshes._needs_colourmap, psyclone.dynamo0p3.DynMeshes._needs_colourmap_halo, psyclone.domain.lfric.lfric_invoke.LFRicInvoke._schedule, psyclone.dynamo0p3.DynMeshes._schedule, psyclone.gocean1p0.GOInvoke._schedule, psyclone.nemo.NemoInvoke._schedule, psyclone.psyGen.Invoke._schedule, psyclone.psyir.nodes.omp_clauses.OMPScheduleClause._schedule, psyclone.domain.lfric.lfric_collection.LFRicCollection._symbol_table, psyclone.dynamo0p3.DynMeshes._symbol_table, psyclone.dynamo0p3.HaloDepth._symbol_table, psyclone.psyGen.HaloExchange._symbol_table, psyclone.psyir.backend.sympy_writer.SymPyWriter._symbol_table, psyclone.psyir.nodes.scoping_node.ScopingNode._symbol_table, and psyclone.dynamo0p3.DynMeshes.intergrid_kernels().

Here is the call graph for this function:

◆ initialise()

def psyclone.dynamo0p3.DynMeshes.initialise (   self,
  parent 
)
Initialise parameters specific to inter-grid kernels.

:param parent: the parent node to which to add the initialisations.
:type parent: :py:class:`psyclone.f2pygen.BaseGen`

Definition at line 2357 of file dynamo0p3.py.

2357  def initialise(self, parent):
2358  '''
2359  Initialise parameters specific to inter-grid kernels.
2360 
2361  :param parent: the parent node to which to add the initialisations.
2362  :type parent: :py:class:`psyclone.f2pygen.BaseGen`
2363 
2364  '''
2365  # pylint: disable=too-many-branches
2366  # If we haven't got any need for a mesh in this invoke then we
2367  # don't do anything
2368  if not self._mesh_tag_names:
2369  return
2370 
2371  parent.add(CommentGen(parent, ""))
2372 
2373  if len(self._mesh_tag_names) == 1:
2374  # We only require one mesh object which means that this invoke
2375  # contains no inter-grid kernels (which would require at least 2)
2376  parent.add(CommentGen(parent, " Create a mesh object"))
2377  parent.add(CommentGen(parent, ""))
2378  rhs = "%".join([self._first_var.proxy_name_indexed,
2379  self._first_var.ref_name(), "get_mesh()"])
2380  mesh_name = self._symbol_table.lookup_with_tag(
2381  self._mesh_tag_names[0]).name
2382  parent.add(AssignGen(parent, pointer=True, lhs=mesh_name, rhs=rhs))
2383  if Config.get().distributed_memory:
2384  # If distributed memory is enabled then we need the maximum
2385  # halo depth.
2386  depth_name = self._symbol_table.lookup_with_tag(
2387  f"max_halo_depth_{self._mesh_tag_names[0]}").name
2388  parent.add(AssignGen(parent, lhs=depth_name,
2389  rhs=f"{mesh_name}%get_halo_depth()"))
2390  if self._needs_colourmap or self._needs_colourmap_halo:
2391  parent.add(CommentGen(parent, ""))
2392  parent.add(CommentGen(parent, " Get the colourmap"))
2393  parent.add(CommentGen(parent, ""))
2394  # Look-up variable names for colourmap and number of colours
2395  colour_map = self._schedule.symbol_table.find_or_create_tag(
2396  "cmap").name
2397  ncolour = \
2398  self._schedule.symbol_table.find_or_create_tag("ncolour")\
2399  .name
2400  # Get the number of colours
2401  parent.add(AssignGen(
2402  parent, lhs=ncolour, rhs=f"{mesh_name}%get_ncolours()"))
2403  # Get the colour map
2404  parent.add(AssignGen(parent, pointer=True, lhs=colour_map,
2405  rhs=f"{mesh_name}%get_colour_map()"))
2406  return
2407 
2408  parent.add(CommentGen(
2409  parent,
2410  " Look-up mesh objects and loop limits for inter-grid kernels"))
2411  parent.add(CommentGen(parent, ""))
2412 
2413  # Keep a list of quantities that we've already initialised so
2414  # that we don't generate duplicate assignments
2415  initialised = []
2416 
2417  # Loop over the DynInterGrid objects
2418  for dig in self.intergrid_kernels:
2419  # We need pointers to both the coarse and the fine mesh as well
2420  # as the maximum halo depth for each.
2421  fine_mesh = self._schedule.symbol_table.find_or_create_tag(
2422  f"mesh_{dig.fine.name}").name
2423  coarse_mesh = self._schedule.symbol_table.find_or_create_tag(
2424  f"mesh_{dig.coarse.name}").name
2425  if fine_mesh not in initialised:
2426  initialised.append(fine_mesh)
2427  parent.add(
2428  AssignGen(parent, pointer=True,
2429  lhs=fine_mesh,
2430  rhs="%".join([dig.fine.proxy_name_indexed,
2431  dig.fine.ref_name(),
2432  "get_mesh()"])))
2433  if Config.get().distributed_memory:
2434  max_halo_f_mesh = (
2435  self._schedule.symbol_table.find_or_create_tag(
2436  f"max_halo_depth_mesh_{dig.fine.name}").name)
2437 
2438  parent.add(AssignGen(parent, lhs=max_halo_f_mesh,
2439  rhs=f"{fine_mesh}%get_halo_depth()"))
2440  if coarse_mesh not in initialised:
2441  initialised.append(coarse_mesh)
2442  parent.add(
2443  AssignGen(parent, pointer=True,
2444  lhs=coarse_mesh,
2445  rhs="%".join([dig.coarse.proxy_name_indexed,
2446  dig.coarse.ref_name(),
2447  "get_mesh()"])))
2448  if Config.get().distributed_memory:
2449  max_halo_c_mesh = (
2450  self._schedule.symbol_table.find_or_create_tag(
2451  f"max_halo_depth_mesh_{dig.coarse.name}").name)
2452  parent.add(AssignGen(
2453  parent, lhs=max_halo_c_mesh,
2454  rhs=f"{coarse_mesh}%get_halo_depth()"))
2455  # We also need a pointer to the mesh map which we get from
2456  # the coarse mesh
2457  if dig.mmap not in initialised:
2458  initialised.append(dig.mmap)
2459  parent.add(
2460  AssignGen(parent, pointer=True,
2461  lhs=dig.mmap,
2462  rhs=f"{coarse_mesh}%get_mesh_map({fine_mesh})"))
2463 
2464  # Cell map. This is obtained from the mesh map.
2465  if dig.cell_map not in initialised:
2466  initialised.append(dig.cell_map)
2467  parent.add(
2468  AssignGen(parent, pointer=True, lhs=dig.cell_map,
2469  rhs=dig.mmap+"%get_whole_cell_map()"))
2470 
2471  # Number of cells in the fine mesh
2472  if dig.ncell_fine not in initialised:
2473  initialised.append(dig.ncell_fine)
2474  if Config.get().distributed_memory:
2475  # TODO this hardwired depth of 2 will need changing in
2476  # order to support redundant computation
2477  parent.add(
2478  AssignGen(parent, lhs=dig.ncell_fine,
2479  rhs=(fine_mesh+"%get_last_halo_cell"
2480  "(depth=2)")))
2481  else:
2482  parent.add(
2483  AssignGen(parent, lhs=dig.ncell_fine,
2484  rhs="%".join([dig.fine.proxy_name,
2485  dig.fine.ref_name(),
2486  "get_ncell()"])))
2487 
2488  # Number of fine cells per coarse cell in x.
2489  if dig.ncellpercellx not in initialised:
2490  initialised.append(dig.ncellpercellx)
2491  parent.add(
2492  AssignGen(parent, lhs=dig.ncellpercellx,
2493  rhs=dig.mmap +
2494  "%get_ntarget_cells_per_source_x()"))
2495 
2496  # Number of fine cells per coarse cell in y.
2497  if dig.ncellpercelly not in initialised:
2498  initialised.append(dig.ncellpercelly)
2499  parent.add(
2500  AssignGen(parent, lhs=dig.ncellpercelly,
2501  rhs=dig.mmap +
2502  "%get_ntarget_cells_per_source_y()"))
2503 
2504  # Colour map for the coarse mesh (if required)
2505  if dig.colourmap_symbol:
2506  # Number of colours
2507  parent.add(AssignGen(parent, lhs=dig.ncolours_var_symbol.name,
2508  rhs=coarse_mesh + "%get_ncolours()"))
2509  # Colour map itself
2510  parent.add(AssignGen(parent, lhs=dig.colourmap_symbol.name,
2511  pointer=True,
2512  rhs=coarse_mesh + "%get_colour_map()"))
2513  # Last halo/edge cell per colour.
2514  sym = dig.last_cell_var_symbol
2515  if len(sym.datatype.shape) == 2:
2516  # Array is 2D so is a halo access.
2517  name = "%get_last_halo_cell_all_colours()"
2518  else:
2519  # Array is just 1D so go to the last edge cell.
2520  name = "%get_last_edge_cell_all_colours()"
2521  parent.add(AssignGen(parent, lhs=sym.name,
2522  rhs=coarse_mesh + name))
2523 

References psyclone.dynamo0p3.DynCellIterators._first_var, psyclone.dynamo0p3.DynMeshes._first_var, psyclone.dynamo0p3.DynMeshes._mesh_tag_names, psyclone.dynamo0p3.DynMeshes._needs_colourmap, psyclone.dynamo0p3.DynMeshes._needs_colourmap_halo, psyclone.domain.lfric.lfric_invoke.LFRicInvoke._schedule, psyclone.dynamo0p3.DynMeshes._schedule, psyclone.gocean1p0.GOInvoke._schedule, psyclone.nemo.NemoInvoke._schedule, psyclone.psyGen.Invoke._schedule, psyclone.psyir.nodes.omp_clauses.OMPScheduleClause._schedule, psyclone.domain.lfric.lfric_collection.LFRicCollection._symbol_table, psyclone.dynamo0p3.DynMeshes._symbol_table, psyclone.dynamo0p3.HaloDepth._symbol_table, psyclone.psyGen.HaloExchange._symbol_table, psyclone.psyir.backend.sympy_writer.SymPyWriter._symbol_table, psyclone.psyir.nodes.scoping_node.ScopingNode._symbol_table, and psyclone.dynamo0p3.DynMeshes.intergrid_kernels().

Here is the call graph for this function:

◆ intergrid_kernels()

def psyclone.dynamo0p3.DynMeshes.intergrid_kernels (   self)
:returns: A list of objects describing the intergrid kernels used in
    this invoke.
:rtype: list[:py:class:`psyclone.dynamo3p0.DynInterGrid`]

Definition at line 2525 of file dynamo0p3.py.

2525  def intergrid_kernels(self):
2526  '''
2527  :returns: A list of objects describing the intergrid kernels used in
2528  this invoke.
2529  :rtype: list[:py:class:`psyclone.dynamo3p0.DynInterGrid`]
2530  '''
2531  intergrids = []
2532  for call in self._schedule.coded_kernels():
2533  if call.is_intergrid:
2534  intergrids.append(call._intergrid_ref)
2535  return intergrids
2536 
2537 

References psyclone.domain.lfric.lfric_invoke.LFRicInvoke._schedule, psyclone.dynamo0p3.DynMeshes._schedule, psyclone.gocean1p0.GOInvoke._schedule, psyclone.nemo.NemoInvoke._schedule, psyclone.psyGen.Invoke._schedule, and psyclone.psyir.nodes.omp_clauses.OMPScheduleClause._schedule.

Here is the caller graph for this function:

The documentation for this class was generated from the following file: