def _create_sample_kernel(self, sample_variables): """Create the parcels kernel for sampling fields during advection.""" # make sure the fieldset has C code names assigned, etc. self.fieldset.check_complete() # string for the kernel itself f_str = "def sample_kernel(particle, fieldset, time):\n" for v in sample_variables: f_str += f"\tparticle.var_{v} = fieldset.{v}.eval(time, particle.depth, particle.lat, particle.lon, applyConversion=False)\n" else: f_str += "\tpass" # create the kernel self.sample_kernel = parcels.Kernel( self.fieldset, self.particleclass.getPType(), funcname="sample_kernel", funcvars=["particle", "fieldset", "time"], funccode=f_str, )
def make_meridionally_periodic(self, width=None): """Mark the domain as meridionally periodic. This will add a halo to the northern and southern edges of the domain, so that they may cross over during advection without being marked out of bounds. If a particle ends up within the halo after advection, it is reset to the valid portion of the domain. If the domain has already been marked as meridionally periodic, nothing happens. Due to the method of resetting particles that end up in the halo, this is incompatible with curvilinear grids. Args: width (Optional[int]): The width of the halo, defaults to 5 (per parcels). This needs to be less than half the number of points in the grid in the y direction. This may need to be adjusted for small domains, or if particles are still escaping the halo. Note: This causes the kernel to be recompiled to add another stage which resets particles that end up in the halo to the main domain. If the kernel has already been recompiled for zonal periodicity, it is again reset to include periodicity in both directions. """ # the method of resetting particles won't work on a curvilinear grid if self._curvilinear: raise Exception("curvilinear grids can not be periodic") # make sure we can't do this twice if self._is_meridionally_periodic: return # add constants that are accessible within the kernel denoting the # edges of the halo region self.fieldset.add_constant("halo_north", self._output_grid.lat[-1]) self.fieldset.add_constant("halo_south", self._output_grid.lat[0]) if width is None: self.fieldset.add_periodic_halo(meridional=True) else: self.fieldset.add_periodic_halo(meridional=True, halosize=width) # unload the previous kernel, and add the meridionally-periodic kernel self.kernel.remove_lib() if self._is_zonally_periodic: k = _doubly_periodic_BC else: k = _meridionally_periodic_BC periodic_kernel = parcels.Kernel(self.fieldset, self.particleclass.getPType(), k) self.kernel = parcels.AdvectionRK4 + periodic_kernel + self.sample_kernel self._compile(self.kernel) self._is_meridionally_periodic = True