• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

csdms / bmi-example-python / 16892127809

11 Aug 2025 09:05PM UTC coverage: 92.784%. Remained the same
16892127809

Pull #38

github

pre-commit-ci[bot]
[pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci
Pull Request #38: [pre-commit.ci] pre-commit autoupdate

180 of 194 relevant lines covered (92.78%)

0.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.31
/heat/bmi_heat.py
1
#! /usr/bin/env python
2
"""Basic Model Interface implementation for the 2D heat model."""
1✔
3

4
from typing import Any
1✔
5

6
import numpy as np
1✔
7
from bmipy import Bmi
1✔
8
from numpy.typing import NDArray
1✔
9

10
from .heat import Heat
1✔
11

12

13
class BmiHeat(Bmi):
1✔
14
    """Solve the heat equation for a 2D plate."""
15

16
    _name = "The 2D Heat Equation"
1✔
17
    _input_var_names = ("plate_surface__temperature",)
1✔
18
    _output_var_names = ("plate_surface__temperature",)
1✔
19

20
    def __init__(self) -> None:
1✔
21
        """Create a BmiHeat model that is ready for initialization."""
22
        # self._model: Heat | None = None
23
        self._model: Heat
1✔
24
        self._values: dict[str, NDArray[Any]] = {}
1✔
25
        self._var_units: dict[str, str] = {}
1✔
26
        self._var_loc: dict[str, str] = {}
1✔
27
        self._grids: dict[int, list[str]] = {}
1✔
28
        self._grid_type: dict[int, str] = {}
1✔
29

30
        self._start_time = 0.0
1✔
31
        self._end_time = float(np.finfo("d").max)
1✔
32
        self._time_units = "s"
1✔
33

34
    def initialize(self, filename: str | None = None) -> None:
1✔
35
        """Initialize the Heat model.
36

37
        Parameters
38
        ----------
39
        filename : str, optional
40
            Path to name of input file.
41
        """
42
        if filename is None:
1✔
43
            self._model = Heat()
1✔
44
        elif isinstance(filename, str):
1✔
45
            with open(filename) as file_obj:
1✔
46
                self._model = Heat.from_file_like(file_obj)
1✔
47
        else:
48
            self._model = Heat.from_file_like(filename)
1✔
49

50
        self._values = {"plate_surface__temperature": self._model.temperature}
1✔
51
        self._var_units = {"plate_surface__temperature": "K"}
1✔
52
        self._var_loc = {"plate_surface__temperature": "node"}
1✔
53
        self._grids = {0: ["plate_surface__temperature"]}
1✔
54
        self._grid_type = {0: "uniform_rectilinear"}
1✔
55

56
    def update(self) -> None:
1✔
57
        """Advance model by one time step."""
58
        self._model.advance_in_time()
1✔
59

60
    def update_frac(self, time_frac: float) -> None:
1✔
61
        """Update model by a fraction of a time step.
62

63
        Parameters
64
        ----------
65
        time_frac : float
66
            Fraction fo a time step.
67
        """
68
        time_step = self.get_time_step()
1✔
69
        self._model.time_step = time_frac * time_step
1✔
70
        self.update()
1✔
71
        self._model.time_step = time_step
1✔
72

73
    def update_until(self, then: float) -> None:
1✔
74
        """Update model until a particular time.
75

76
        Parameters
77
        ----------
78
        then : float
79
            Time to run model until.
80
        """
81
        n_steps = (then - self.get_current_time()) / self.get_time_step()
1✔
82

83
        for _ in range(int(n_steps)):
1✔
84
            self.update()
1✔
85
        self.update_frac(n_steps - int(n_steps))
1✔
86

87
    def finalize(self) -> None:
1✔
88
        """Finalize model."""
89
        del self._model
1✔
90
        # self._model = None
91

92
    def get_var_type(self, var_name: str) -> str:
1✔
93
        """Data type of variable.
94

95
        Parameters
96
        ----------
97
        var_name : str
98
            Name of variable as CSDMS Standard Name.
99

100
        Returns
101
        -------
102
        str
103
            Data type.
104
        """
105
        return str(self.get_value_ptr(var_name).dtype)
1✔
106

107
    def get_var_units(self, var_name: str) -> str:
1✔
108
        """Get units of variable.
109

110
        Parameters
111
        ----------
112
        var_name : str
113
            Name of variable as CSDMS Standard Name.
114

115
        Returns
116
        -------
117
        str
118
            Variable units.
119
        """
120
        return self._var_units[var_name]
1✔
121

122
    def get_var_nbytes(self, var_name: str) -> int:
1✔
123
        """Get units of variable.
124

125
        Parameters
126
        ----------
127
        var_name : str
128
            Name of variable as CSDMS Standard Name.
129

130
        Returns
131
        -------
132
        int
133
            Size of data array in bytes.
134
        """
135
        return self.get_value_ptr(var_name).nbytes
1✔
136

137
    def get_var_itemsize(self, name: str) -> int:
1✔
138
        return np.dtype(self.get_var_type(name)).itemsize
×
139

140
    def get_var_location(self, name: str) -> str:
1✔
141
        return self._var_loc[name]
×
142

143
    def get_var_grid(self, var_name: str) -> int | None:
1✔
144
        """Grid id for a variable.
145

146
        Parameters
147
        ----------
148
        var_name : str
149
            Name of variable as CSDMS Standard Name.
150

151
        Returns
152
        -------
153
        int
154
            Grid id.
155
        """
156
        for grid_id, var_name_list in self._grids.items():
1✔
157
            if var_name in var_name_list:
1✔
158
                return grid_id
1✔
159
        return None
×
160

161
    def get_grid_rank(self, grid_id: int) -> int:
1✔
162
        """Rank of grid.
163

164
        Parameters
165
        ----------
166
        grid_id : int
167
            Identifier of a grid.
168

169
        Returns
170
        -------
171
        int
172
            Rank of grid.
173
        """
174
        return len(self._model.shape)
1✔
175

176
    def get_grid_size(self, grid_id: int) -> int:
1✔
177
        """Size of grid.
178

179
        Parameters
180
        ----------
181
        grid_id : int
182
            Identifier of a grid.
183

184
        Returns
185
        -------
186
        int
187
            Size of grid.
188
        """
189
        return int(np.prod(self._model.shape))
1✔
190

191
    def get_value_ptr(self, var_name: str) -> NDArray[Any]:
1✔
192
        """Reference to values.
193

194
        Parameters
195
        ----------
196
        var_name : str
197
            Name of variable as CSDMS Standard Name.
198

199
        Returns
200
        -------
201
        array_like
202
            Value array.
203
        """
204
        return self._values[var_name]
1✔
205

206
    def get_value(self, var_name: str, dest: NDArray[Any]) -> NDArray[Any]:
1✔
207
        """Copy of values.
208

209
        Parameters
210
        ----------
211
        var_name : str
212
            Name of variable as CSDMS Standard Name.
213
        dest : ndarray
214
            A numpy array into which to place the values.
215

216
        Returns
217
        -------
218
        array_like
219
            Copy of values.
220
        """
221
        dest[:] = self.get_value_ptr(var_name).flatten()
1✔
222
        return dest
1✔
223

224
    def get_value_at_indices(
1✔
225
        self, var_name: str, dest: NDArray[Any], indices: NDArray[np.int_]
226
    ) -> NDArray[Any]:
227
        """Get values at particular indices.
228

229
        Parameters
230
        ----------
231
        var_name : str
232
            Name of variable as CSDMS Standard Name.
233
        dest : ndarray
234
            A numpy array into which to place the values.
235
        indices : array_like
236
            Array of indices.
237

238
        Returns
239
        -------
240
        array_like
241
            Values at indices.
242
        """
243
        dest[:] = self.get_value_ptr(var_name).take(indices)
1✔
244
        return dest
1✔
245

246
    def set_value(self, var_name: str, src: NDArray[Any]) -> None:
1✔
247
        """Set model values.
248

249
        Parameters
250
        ----------
251
        var_name : str
252
            Name of variable as CSDMS Standard Name.
253
        src : array_like
254
            Array of new values.
255
        """
256
        val = self.get_value_ptr(var_name)
1✔
257
        val[:] = src.reshape(val.shape)
1✔
258

259
    def set_value_at_indices(
1✔
260
        self, name: str, inds: NDArray[np.int_], src: NDArray[Any]
261
    ) -> None:
262
        """Set model values at particular indices.
263

264
        Parameters
265
        ----------
266
        var_name : str
267
            Name of variable as CSDMS Standard Name.
268
        src : array_like
269
            Array of new values.
270
        indices : array_like
271
            Array of indices.
272
        """
273
        val = self.get_value_ptr(name)
1✔
274
        val.flat[inds] = src
1✔
275

276
    def get_component_name(self) -> str:
1✔
277
        """Name of the component."""
278
        return self._name
1✔
279

280
    def get_input_item_count(self) -> int:
1✔
281
        """Get names of input variables."""
282
        return len(self._input_var_names)
1✔
283

284
    def get_output_item_count(self) -> int:
1✔
285
        """Get names of output variables."""
286
        return len(self._output_var_names)
1✔
287

288
    def get_input_var_names(self) -> tuple[str, ...]:
1✔
289
        """Get names of input variables."""
290
        return self._input_var_names
1✔
291

292
    def get_output_var_names(self) -> tuple[str, ...]:
1✔
293
        """Get names of output variables."""
294
        return self._output_var_names
1✔
295

296
    def get_grid_shape(self, grid_id: int, shape: NDArray[np.int_]) -> NDArray[np.int_]:
1✔
297
        """Number of rows and columns of uniform rectilinear grid."""
298
        var_name = self._grids[grid_id][0]
1✔
299
        shape[:] = self.get_value_ptr(var_name).shape
1✔
300
        return shape
1✔
301

302
    def get_grid_spacing(
1✔
303
        self, grid_id: int, spacing: NDArray[np.float64]
304
    ) -> NDArray[np.float64]:
305
        """Spacing of rows and columns of uniform rectilinear grid."""
306
        spacing[:] = self._model.spacing
1✔
307
        return spacing
1✔
308

309
    def get_grid_origin(
1✔
310
        self, grid_id: int, origin: NDArray[np.float64]
311
    ) -> NDArray[np.float64]:
312
        """Origin of uniform rectilinear grid."""
313
        origin[:] = self._model.origin
1✔
314
        return origin
1✔
315

316
    def get_grid_type(self, grid_id: int) -> str:
1✔
317
        """Type of grid."""
318
        return self._grid_type[grid_id]
1✔
319

320
    def get_start_time(self) -> float:
1✔
321
        """Start time of model."""
322
        return self._start_time
1✔
323

324
    def get_end_time(self) -> float:
1✔
325
        """End time of model."""
326
        return self._end_time
1✔
327

328
    def get_current_time(self) -> float:
1✔
329
        return self._model.time
1✔
330

331
    def get_time_step(self) -> float:
1✔
332
        return self._model.time_step
1✔
333

334
    def get_time_units(self) -> str:
1✔
335
        return self._time_units
×
336

337
    def get_grid_edge_count(self, grid: int) -> int:
1✔
338
        raise NotImplementedError("get_grid_edge_count")
×
339

340
    def get_grid_edge_nodes(self, grid: int, edge_nodes: NDArray[np.int_]) -> None:
1✔
341
        raise NotImplementedError("get_grid_edge_nodes")
×
342

343
    def get_grid_face_count(self, grid: int) -> None:
1✔
344
        raise NotImplementedError("get_grid_face_count")
×
345

346
    def get_grid_face_nodes(self, grid: int, face_nodes: NDArray[np.int_]) -> None:
1✔
347
        raise NotImplementedError("get_grid_face_nodes")
×
348

349
    def get_grid_node_count(self, grid: int) -> int:
1✔
350
        """Number of grid nodes.
351

352
        Parameters
353
        ----------
354
        grid : int
355
            Identifier of a grid.
356

357
        Returns
358
        -------
359
        int
360
            Size of grid.
361
        """
362
        return self.get_grid_size(grid)
×
363

364
    def get_grid_nodes_per_face(
1✔
365
        self, grid: int, nodes_per_face: NDArray[np.int_]
366
    ) -> None:
367
        raise NotImplementedError("get_grid_nodes_per_face")
×
368

369
    def get_grid_face_edges(self, grid: int, face_edges: NDArray[np.int_]) -> None:
1✔
370
        raise NotImplementedError("get_grid_face_edges")
×
371

372
    def get_grid_x(self, grid: int, x: NDArray[np.float64]) -> None:
1✔
373
        raise NotImplementedError("get_grid_x")
×
374

375
    def get_grid_y(self, grid: int, y: NDArray[np.float64]) -> None:
1✔
376
        raise NotImplementedError("get_grid_y")
×
377

378
    def get_grid_z(self, grid: int, z: NDArray[np.float64]) -> None:
1✔
379
        raise NotImplementedError("get_grid_z")
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc