Coverage for eminus/domains.py: 95.56%
45 statements
« prev ^ index » next coverage.py v7.6.4, created at 2024-11-01 11:47 +0000
« prev ^ index » next coverage.py v7.6.4, created at 2024-11-01 11:47 +0000
1# SPDX-FileCopyrightText: 2021 The eminus developers
2# SPDX-License-Identifier: Apache-2.0
3"""Functions to restrict real-space fields to domains."""
5import numbers
7import numpy as np
8from scipy.linalg import norm
10from .logger import log
11from .tools import center_of_mass
14def domain_cuboid(obj, length, centers=None):
15 """Generate a mask for a cuboidal real-space domain.
17 Args:
18 obj: Atoms or SCF object.
19 length: Side length or lengths of the cuboid.
21 Keyword Args:
22 centers: Center of the cuboid.
24 Defaults to the geometric center of mass of the system. For multiple coordinates,
25 multiple domains will be merged.
27 Returns:
28 Boolean mask.
29 """
30 atoms = obj._atoms
32 if isinstance(length, numbers.Real):
33 length = length * np.ones(3)
34 if centers is None:
35 centers = center_of_mass(atoms.pos)
36 centers = np.asarray(centers)
37 # Handle each dimension separately and add them together
38 if centers.ndim == 1:
39 mask1 = np.abs(centers[0] - atoms.r[:, 0]) < length[0]
40 mask2 = np.abs(centers[1] - atoms.r[:, 1]) < length[1]
41 mask3 = np.abs(centers[2] - atoms.r[:, 2]) < length[2]
42 mask = mask1 & mask2 & mask3
43 else:
44 mask = np.zeros(atoms.Ns, dtype=bool)
45 for center in centers:
46 mask1 = np.abs(center[0] - atoms.r[:, 0]) < length[0]
47 mask2 = np.abs(center[1] - atoms.r[:, 1]) < length[1]
48 mask3 = np.abs(center[2] - atoms.r[:, 2]) < length[2]
49 mask = mask | (mask1 & mask2 & mask3)
50 return mask
53def domain_isovalue(field, isovalue):
54 """Generate a mask for an isovalue real-space domain.
56 Args:
57 field: Real-space field data.
58 isovalue: Isovalue for the truncation.
60 Returns:
61 Boolean mask.
62 """
63 if field is None:
64 log.warning('The provided field is "None".')
65 return None
66 return np.abs(field) > isovalue
69def domain_sphere(obj, radius, centers=None):
70 """Generate a mask for a spherical real-space domain.
72 Args:
73 obj: Atoms or SCF object.
74 radius: Radius of the sphere.
76 Keyword Args:
77 centers: Center of the sphere.
79 Defaults to the geometric center of mass of the system. For multiple coordinates,
80 multiple domains will be merged.
82 Returns:
83 Boolean mask.
84 """
85 atoms = obj._atoms
87 if centers is None:
88 centers = center_of_mass(atoms.pos)
89 centers = np.asarray(centers)
90 if centers.ndim == 1:
91 mask = norm(centers - atoms.r, axis=1) < radius
92 else:
93 mask = np.zeros(atoms.Ns, dtype=bool)
94 for center in centers:
95 mask_tmp = norm(center - atoms.r, axis=1) < radius
96 mask = mask | mask_tmp
97 return mask
100def truncate(field, mask):
101 """Truncate field data for a given mask.
103 This will not return a smaller array but set all truncated values to zero.
105 Args:
106 field: Real-space field data.
107 mask: Boolean mask.
109 Returns:
110 Truncated field.
111 """
112 field_trunc = np.copy(field)
113 field_trunc[~mask] = 0
114 return field_trunc