def eval_func(func, pos, mesh_type="structured"): """ Evaluate a function on a mesh. Parameters ---------- func : :any:`callable` The function to be called. Should have the signiture f(x, [y, z]) pos : :class:`list` the position tuple, containing main direction and transversal directions (x, [y, z]) mesh_type : :class:`str`, optional 'structured' / 'unstructured' Returns ------- :class:`numpy.ndarray` Function values at the given points. """ x, y, z, dim = pos2xyz(pos, calc_dim=True) if mesh_type == "structured": x, y, z, axis_lens = reshape_axis_from_struct_to_unstruct(dim, x, y, z) res = func(*[x, y, z][:dim]) if mesh_type == "structured": res = reshape_field_from_unstruct_to_struct(dim, res, axis_lens) return res
def __call__( self, pos, seed=np.nan, point_volumes=0.0, mesh_type="unstructured" ): """Generate the spatial random field. The field is saved as `self.field` and is also returned. Parameters ---------- pos : :class:`list` the position tuple, containing main direction and transversal directions seed : :class:`int`, optional seed for RNG for reseting. Default: keep seed from generator point_volumes : :class:`float` or :class:`numpy.ndarray` If your evaluation points for the field are coming from a mesh, they are probably representing a certain element volume. This volume can be passed by `point_volumes` to apply the given variance upscaling. If `point_volumes` is ``0`` nothing is changed. Default: ``0`` mesh_type : :class:`str` 'structured' / 'unstructured' Returns ------- field : :class:`numpy.ndarray` the SRF """ # internal conversation x, y, z = pos2xyz(pos, max_dim=self.model.dim) self.pos = xyz2pos(x, y, z) self.mesh_type = mesh_type # update the model/seed in the generator if any changes were made self.generator.update(self.model, seed) # format the positional arguments of the mesh check_mesh(self.model.dim, x, y, z, mesh_type) mesh_type_changed = False if self.model.do_rotation: if mesh_type == "structured": mesh_type_changed = True mesh_type_old = mesh_type mesh_type = "unstructured" x, y, z, axis_lens = reshape_axis_from_struct_to_unstruct( self.model.dim, x, y, z ) x, y, z = unrotate_mesh(self.model.dim, self.model.angles, x, y, z) y, z = make_isotropic(self.model.dim, self.model.anis, y, z) # generate the field self.raw_field = self.generator.__call__(x, y, z, mesh_type) # reshape field if we got an unstructured mesh if mesh_type_changed: mesh_type = mesh_type_old self.raw_field = reshape_field_from_unstruct_to_struct( self.model.dim, self.raw_field, axis_lens ) # apply given conditions to the field if self.condition: ( cond_field, krige_field, err_field, krigevar, info, ) = self.cond_func(self) # store everything in the class self.field = cond_field self.krige_field = krige_field self.err_field = err_field self.krige_var = krigevar if "mean" in info: # ordinary krging estimates mean self.mean = info["mean"] else: self.field = self.raw_field + self.mean # upscaled variance if not np.isscalar(point_volumes) or not np.isclose(point_volumes, 0): scaled_var = self.upscaling_func(self.model, point_volumes) self.field -= self.mean self.field *= np.sqrt(scaled_var / self.model.sill) self.field += self.mean return self.field
def __call__(self, pos, mesh_type="unstructured"): """ Generate the ordinary kriging field. The field is saved as `self.field` and is also returned. Parameters ---------- pos : :class:`list` the position tuple, containing main direction and transversal directions (x, [y, z]) mesh_type : :class:`str` 'structured' / 'unstructured' Returns ------- field : :class:`numpy.ndarray` the kriged field krige_var : :class:`numpy.ndarray` the kriging error variance """ # internal conversation x, y, z = pos2xyz(pos, dtype=np.double, max_dim=self.model.dim) c_x, c_y, c_z = pos2xyz(self.cond_pos, dtype=np.double, max_dim=self.model.dim) self.pos = xyz2pos(x, y, z) self.mesh_type = mesh_type # format the positional arguments of the mesh check_mesh(self.model.dim, x, y, z, mesh_type) mesh_type_changed = False if mesh_type == "structured": mesh_type_changed = True mesh_type_old = mesh_type mesh_type = "unstructured" x, y, z, axis_lens = reshape_axis_from_struct_to_unstruct( self.model.dim, x, y, z) if self.model.do_rotation: x, y, z = unrotate_mesh(self.model.dim, self.model.angles, x, y, z) c_x, c_y, c_z = unrotate_mesh(self.model.dim, self.model.angles, c_x, c_y, c_z) y, z = make_isotropic(self.model.dim, self.model.anis, y, z) c_y, c_z = make_isotropic(self.model.dim, self.model.anis, c_y, c_z) # set condtions cond = np.concatenate((self.cond_val, [0])) krig_mat = inv(self._get_krig_mat((c_x, c_y, c_z), (c_x, c_y, c_z))) krig_vecs = self._get_vario_mat((c_x, c_y, c_z), (x, y, z), add=True) # generate the kriged field field, krige_var = krigesum(krig_mat, krig_vecs, cond) # calculate the estimated mean (kriging field at infinity) mean_est = np.concatenate((np.full_like(self.cond_val, self.model.sill), [1])) self.mean = np.einsum("i,ij,j", cond, krig_mat, mean_est) # reshape field if we got an unstructured mesh if mesh_type_changed: mesh_type = mesh_type_old field = reshape_field_from_unstruct_to_struct( self.model.dim, field, axis_lens) krige_var = reshape_field_from_unstruct_to_struct( self.model.dim, krige_var, axis_lens) # save the field self.krige_var = krige_var self.field = field return self.field, self.krige_var
def __call__(self, pos, mesh_type="unstructured"): """ Generate the simple kriging field. The field is saved as `self.field` and is also returned. Parameters ---------- pos : :class:`list` the position tuple, containing main direction and transversal directions (x, [y, z]) mesh_type : :class:`str` 'structured' / 'unstructured' Returns ------- field : :class:`numpy.ndarray` the kriged field krige_var : :class:`numpy.ndarray` the kriging error variance """ # internal conversation x, y, z = pos2xyz(pos, dtype=np.double, max_dim=self.model.dim) c_x, c_y, c_z = pos2xyz(self.cond_pos, dtype=np.double, max_dim=self.model.dim) self.pos = xyz2pos(x, y, z) self.mesh_type = mesh_type # format the positional arguments of the mesh check_mesh(self.model.dim, x, y, z, mesh_type) mesh_type_changed = False if mesh_type == "structured": mesh_type_changed = True mesh_type_old = mesh_type mesh_type = "unstructured" x, y, z, axis_lens = reshape_axis_from_struct_to_unstruct( self.model.dim, x, y, z) if self.model.do_rotation: x, y, z = unrotate_mesh(self.model.dim, self.model.angles, x, y, z) c_x, c_y, c_z = unrotate_mesh(self.model.dim, self.model.angles, c_x, c_y, c_z) y, z = make_isotropic(self.model.dim, self.model.anis, y, z) c_y, c_z = make_isotropic(self.model.dim, self.model.anis, c_y, c_z) # set condtions to zero mean cond = self.cond_val - self.mean krig_mat = inv(self._get_cov_mat((c_x, c_y, c_z), (c_x, c_y, c_z))) krig_vecs = self._get_cov_mat((c_x, c_y, c_z), (x, y, z)) # generate the kriged field field, krige_var = krigesum(krig_mat, krig_vecs, cond) # reshape field if we got an unstructured mesh if mesh_type_changed: mesh_type = mesh_type_old field = reshape_field_from_unstruct_to_struct( self.model.dim, field, axis_lens) krige_var = reshape_field_from_unstruct_to_struct( self.model.dim, krige_var, axis_lens) # calculate the kriging error self.krige_var = self.model.sill - krige_var # add the given mean self.field = field + self.mean return self.field, self.krige_var
def __call__( self, pos, seed=np.nan, force_moments=False, point_volumes=0.0, mesh_type="unstructured", ): """Generate the spatial random field. Parameters ---------- pos : :class:`list` the position tuple, containing main direction and transversal directions seed : :class:`int`, optional seed for RNG for reseting. Default: keep seed from generator force_moments : :class:`bool` Force the generator to exactly match mean and variance. Default: ``False`` point_volumes : :class:`float` or :class:`numpy.ndarray` If your evaluation points for the field are coming from a mesh, they are probably representing a certain element volume. This volumes can be passed by `point_volumes` to apply the given variance upscaling. If `point_volumes` is ``0`` nothing is changed. Default: ``0`` mesh_type : :class:`str` 'structured' / 'unstructured' Returns ------- field : :class:`numpy.ndarray` the SRF """ # internal conversation x, y, z = pos2xyz(pos) # update the model/seed in the generator if any changes were made self.generator.update(self.model, seed) # format the positional arguments of the mesh check_mesh(self.model.dim, x, y, z, mesh_type) mesh_type_changed = False if self.do_rotation: if mesh_type == "structured": mesh_type_changed = True mesh_type_old = mesh_type mesh_type = "unstructured" x, y, z, axis_lens = reshape_axis_from_struct_to_unstruct( self.model.dim, x, y, z) x, y, z = unrotate_mesh(self.model.dim, self.model.angles, x, y, z) y, z = make_isotropic(self.model.dim, self.model.anis, y, z) x, y, z = reshape_input(x, y, z, mesh_type) # generate the field field = self.generator.__call__(x, y, z) # reshape field if we got an unstructured mesh if mesh_type_changed: mesh_type = mesh_type_old field = reshape_field_from_unstruct_to_struct( self.model.dim, field, axis_lens) # force variance and mean to be exactly as given (if wanted) if force_moments: var_in = np.var(field) mean_in = np.mean(field) rescale = np.sqrt(self.model.sill / var_in) field = rescale * (field - mean_in) # upscaled variance scaled_var = self.upscaling_func(self.model, point_volumes) # rescale and shift the field to the mean self.field = np.sqrt(scaled_var / self.model.sill) * field + self.mean return self.field
def __call__( self, pos, mesh_type="unstructured", ext_drift=None, chunk_size=None ): """ Generate the kriging field. The field is saved as `self.field` and is also returned. The error variance is saved as `self.krige_var` and is also returned. Parameters ---------- pos : :class:`list` the position tuple, containing main direction and transversal directions (x, [y, z]) mesh_type : :class:`str`, optional 'structured' / 'unstructured' ext_drift : :class:`numpy.ndarray` or :any:`None`, optional the external drift values at the given positions (only for EDK) chunk_size : :class:`int`, optional Chunk size to cut down the size of the kriging system to prevent memory errors. Default: None Returns ------- field : :class:`numpy.ndarray` the kriged field krige_var : :class:`numpy.ndarray` the kriging error variance """ self.mesh_type = mesh_type # internal conversation x, y, z, self.pos, __, mt_changed, axis_lens = self._pre_pos( pos, mesh_type, make_unstruct=True ) point_no = len(x) # set chunk size chunk_size = point_no if chunk_size is None else int(chunk_size) chunk_no = int(np.ceil(point_no / chunk_size)) field = np.empty_like(x) krige_var = np.empty_like(x) ext_drift = self._pre_ext_drift(point_no, ext_drift) # iterate of chunks for i in range(chunk_no): # get chunk slice for actual chunk chunk_slice = (i * chunk_size, min(point_no, (i + 1) * chunk_size)) c_slice = slice(*chunk_slice) # get RHS of the kriging system k_vec = self._get_krige_vecs((x, y, z), chunk_slice, ext_drift) # generate the raw kriging field and error variance field[c_slice], krige_var[c_slice] = krigesum( self._krige_mat, k_vec, self._krige_cond ) # reshape field if we got a structured mesh if mt_changed: field = reshape_field_from_unstruct_to_struct( self.model.dim, field, axis_lens ) krige_var = reshape_field_from_unstruct_to_struct( self.model.dim, krige_var, axis_lens ) self._post_field(field, krige_var) return self.field, self.krige_var