Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
0b0ce58
Added common_variables to API docs
SMijin Mar 17, 2025
e1dac04
LaTeX improvements to variables
SMijin Mar 17, 2025
6c058cb
Added inline matrix term constant latex setting
SMijin Mar 17, 2025
a33cdaa
Added docstring to withLatexConst
SMijin Mar 17, 2025
13f2a62
Fixed CRM example sequencing
SMijin Mar 17, 2025
aeb9ea2
Added default latex remaps to modelbound data (experimental)
SMijin Mar 17, 2025
feb5ee0
Added automatic dual variable addition to VarlikeModelboundData
SMijin Mar 17, 2025
74febbd
Minor bug fixes
SMijin Mar 17, 2025
fde186f
Minor latex fixes
SMijin Mar 18, 2025
064bb41
black
SMijin Mar 18, 2025
e12c48b
More latex improvements
SMijin Mar 18, 2025
902c477
minor variable latex changed
SMijin Mar 19, 2025
c3146e7
Added quickDash helper function
SMijin Mar 19, 2025
441e641
Added time derivative variable subtype and more latex improvements
SMijin Mar 20, 2025
dcbbc9e
automatic setting of time variable norm at checking
SMijin Mar 20, 2025
a22cedb
Added transition population change
SMijin Mar 20, 2025
ffba2b7
Added variable kwarg tracking
SMijin Mar 20, 2025
1dc3246
Added modelbound variable extraction helper fun on context
SMijin Mar 20, 2025
9984ea8
Fixed concat error in crm_support
SMijin Apr 10, 2025
3415526
Fixed getRate and added test
SMijin Apr 10, 2025
09b749c
Added hasVarType to Species
SMijin May 29, 2025
be88291
Added support for v1.2.2 rewrite of BDE integrator
SMijin May 29, 2025
b2812fd
Added docs and updated minNonlinIters default
SMijin May 29, 2025
33f0a29
Changed version number to in docstring
SMijin May 29, 2025
bd05d84
Added DistDivStencil + formatting
SMijin Jun 23, 2025
c57c317
Fixed Fortran v number in changelog
SMijin Jun 23, 2025
2370060
Implemented support for kinetic harmonic offset in diagonal stencil
SMijin Jun 24, 2025
1d5500e
Merge pull request #65 from ukaea/dev-smijin-kin-harmonic-offset
SMijin Jun 30, 2025
b9cd0cd
Latex hotfix for CRM features
SMijin Jun 30, 2025
f561125
Fixed tutorial typo
SMijin Jul 3, 2025
c2718b9
Updated README with correct read the docs link
SMijin Jul 9, 2025
f072382
Added QoL feature to give term and model when raising various term ch…
SMijin Jul 9, 2025
d1ce310
LaTeX +- fix for AdditiveDerivation
SMijin Jul 10, 2025
f1385a0
Dashboard improvements + black formatting
SMijin Jul 10, 2025
f676011
Dashboard refactor to enable cleaner templates and easier extension
SMijin Jul 11, 2025
52228c6
Changed some defaults in dashboard and moved to MultiChoice widget
SMijin Jul 14, 2025
f1c9f6e
Added improved axis range handling in dashboard
SMijin Jul 14, 2025
7199151
Made dashboard element registration explicit
SMijin Jul 15, 2025
b7438df
Added dashboard element persistence
SMijin Jul 15, 2025
52de4ce
Added a pyproject.toml file
SMijin Jul 17, 2025
9211798
added missing .keep for advection with outflow example output dir
SMijin Jul 17, 2025
ceb4304
Fixed doubled dictionary key
SMijin Jul 22, 2025
f7f0f1a
Preparing for v2.0.0 release
SMijin Aug 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,34 @@
# CHANGELOG
## v2.0.0, 2025-08-29

- See beta.1 notes
- Support for v1.3 BDE integrator rewrite
- Support for v1.3 distribution divergence stencil
- Support for v1.3 diagonal kinetic stencil upgrade

### Breaking Changes

- See beta.1 notes

### Deprecations

- See beta.1 notes

### New Features

- See beta.1 notes
- Updated BDE integrator options
- New DistDivStencil class that includes the Jacobian in d/dx operator for distributions
- New harmonicOffset argument for diagonal stencil to allow for direct harmonic coupling
- Added option to have the first moment modelbound variables (rate1*) in CRMModelboundData living on the dual grid

### Bug Fixes

- N/A

### New Notebooks

- See beta.1 notes

## v2.0.0-beta.1, 2025-03-13

Expand Down Expand Up @@ -207,4 +237,4 @@

### Bug Fixes

- N/A
- N/A
20 changes: 16 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ RMK_support is a collection of tools designed to configure and analyze ReMKiT1D

ReMKiT1D runs use JSON files to configure the models and methods used by the code, and RMK_support provides convenient Python routines for the generation of these config files, while also providing features that enable analysis of data using obtained from ReMKiT1D runs.

For a high level overview of the framework and the (pre-v2.0.0) Python interface see the [code paper](https://www.sciencedirect.com/science/article/pii/S0010465524001188). For detailed documentation of the Python package see [here](https://readthedocs.org/projects/remkit1d-python/).
For a high level overview of the framework and the (pre-v2.0.0) Python interface see the [code paper](https://www.sciencedirect.com/science/article/pii/S0010465524001188). For detailed documentation of the Python package see [here](https://remkit1d-python.readthedocs.io/en/latest/).

## Prerequisites

Expand Down Expand Up @@ -181,6 +181,18 @@ The secondary feature of RMK_support modules is data analysis and visualization,

From v2.0.0 a new dynamic, composable, and extensible dashboard is available through `ElementDisplay` objects, which can be composed into a [panel](https://panel.holoviz.org/) app.

For example, running the below cell in the [advection with outflow](https://github.com/ukaea/ReMKiT1D-Python/blob/master/examples/gaussian_advection_outflow.ipynb) after running the [advection](https://github.com/ukaea/ReMKiT1D-Python/blob/master/examples/ReMKiT1D_advection_test.ipynb) example will serve the pre-built dashboard (NOTE: some issues encountered with newer versions of Firefox, try serving in another browser if the dashboard is not rendering).

```python
from RMK_support.dashboard_support import dashboard

runPaths={"outflow":rk.IOContext.HDF5Dir,"no-outflow":"./RMKOutput/RMK_advection_test/"}
plt.rcParams['figure.dpi'] = 150
hv.output(size=50,dpi=150)
dashboard(rk,runPaths=runPaths,elementsPerTab=2).servable().show()
```


![](docs/dashboard_example.png "ReMKiT1D v2.0.0 dashboard")

## Documentation, examples and tutorials
Expand All @@ -189,11 +201,11 @@ For a high level explanation of both the framework and the interface the user is

The examples in the examples directory supplement the code paper, in particular the [advection](https://github.com/ukaea/ReMKiT1D-Python/blob/master/examples/ReMKiT1D_advection_test.ipynb) example partly reproduced in this readme.

A collection of simplified tutorials which are meant to showcase the syntax without producing runnable scripts are available in the tutorials directory.
A collection of simplified tutorials which are meant to showcase the syntax without necessarily producing runnable scripts are available in the tutorials directory.

For the list of the newest example notebooks, where new features are covered, see the CHANGELOG.

Further code documentation is available [here](https://readthedocs.org/projects/remkit1d-python/), where more detailed resources can be found.
Further code documentation is available [here](https://remkit1d-python.readthedocs.io/en/latest/), where more detailed resources can be found.

## Licence

Expand All @@ -203,4 +215,4 @@ RMK_support is distributed in the hope that it will be useful, but WITHOUT ANY W

You should have received a copy of the GNU General Public License along with RMK_support. If not, see <https://www.gnu.org/licenses/>.

Copyright 2023 United Kingdom Atomic Energy Authority
Copyright 2023 United Kingdom Atomic Energy Authority
12 changes: 6 additions & 6 deletions RMK_support/calculation_tree_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,24 +320,24 @@ def latex(self, latexRemap: Dict[str, str] = {}) -> str:

else:
if self.additiveMode:
childrenResult = "+".join(
childrenResult = " + ".join(
child.latex(latexRemap) for child in self.children
)

else:
childrenResult = const + "".join(
(
"\\left(" + child.latex(latexRemap) + "\\right)"
"(" + child.latex(latexRemap) + ")"
if child.additiveMode
else child.latex(latexRemap)
)
for child in self.children
)

if self.unaryTransform is None:
return childrenResult.replace("+-", "-")
return childrenResult.replace("+ -", " - ")

return self.unaryTransform.latex(childrenResult).replace("+-", "-")
return self.unaryTransform.latex(childrenResult).replace("+ -", " - ")


class UnaryTransform:
Expand Down Expand Up @@ -542,7 +542,7 @@ def powUnary(power: Union[int, float]) -> UnaryTransform:
"ipow",
intParams=[power],
unaryCallable=func,
latexTemplate="\\left($0\\right)^{$1}",
latexTemplate="($0)^{$1}",
)
return transform

Expand All @@ -551,7 +551,7 @@ def powUnary(power: Union[int, float]) -> UnaryTransform:
"rpow",
realParams=[power],
unaryCallable=func,
latexTemplate="\\left($0\\right)^{$1}",
latexTemplate="($0)^{$1}",
)
return transform

Expand Down
2 changes: 1 addition & 1 deletion RMK_support/common_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ def implicitTemperatures(
species: List[Species],
norms: Dict[str, float],
speciesFluxes: Optional[List[Variable]] = None,
**kwargs
**kwargs,
) -> mc.Model:
"""Generate implicit temperature derivation matrix terms for each species: d*n_b*k*T_b/2 + m_b*n_b*u_b**2/2 = W_b, where d is the number of degrees of freedom. Temperatures here are assumed to be stationary and implicit variables. The kinetic energy contribution uses interpolation, so should be used with care in regions of poorly resolved flow gradients. Assumes default normalization.

Expand Down
103 changes: 89 additions & 14 deletions RMK_support/common_variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,60 @@
from .variable_container import Variable, node
from .derivations import Species
from . import derivations
from .remkit_context import RMKContext
from abc import ABC, abstractmethod


def timeDerivative(
name: str, timeNorm: float, variable: Variable, **kwargs
) -> Variable:
"""Generate a time derivative of a given variable as a variable, making sure units and grids are correct.

Args:
name (str): Variable name for the time derivative
timeNorm (float): Time normalisation
variable (Variable): Variable whose derivative should be taken

Returns:
Variable: Variable with correct time derivative units
"""

for key in [
"units",
"unitSI",
"normSI",
"isOnDualGrid",
"isDistribution",
"isSingleHarmonic",
"isScalar",
"subtype",
]:
assert key not in kwargs, key + " not allowed in time derivative variable call"

latexWrapped = "$" in variable.unitsSI
unitSI = variable.unitsSI.replace("$", "") + "/s"
if latexWrapped:
unitSI = "$" + unitSI + "$"
var = Variable(
name,
variable.grid,
**kwargs,
units=variable.unitsNorm + " / time norm.",
unitSI=unitSI,
normSI=variable.normSI / timeNorm,
isOnDualGrid=variable.isOnDualGrid,
isScalar=variable.isScalar,
isDistribution=variable.isDistribution,
isSingleHarmonics=variable.isSingleHarmonic,
subtype=variable.subtype + "_time_derivative",
)

return var


# cyclic import workaround
from .remkit_context import RMKContext


def density(name: str, context: RMKContext, **kwargs) -> Variable:
"""Generate a density variable based on normalisation data within a RMKContext. Accepts regular Variable kwargs, except for those having to do with units, which are set automatically.

Expand All @@ -29,7 +79,7 @@ def density(name: str, context: RMKContext, **kwargs) -> Variable:
**kwargs,
units="norm. density",
unitSI="$m^{-3}$",
normSI=context.normDensity
normSI=context.normDensity,
)

return var
Expand Down Expand Up @@ -57,7 +107,7 @@ def temperature(name: str, context: RMKContext, **kwargs) -> Variable:
**kwargs,
units="norm. temperature",
unitSI="eV",
normSI=context.normTemperature
normSI=context.normTemperature,
)

return var
Expand Down Expand Up @@ -85,7 +135,7 @@ def flux(name: str, context: RMKContext, **kwargs) -> Variable:
**kwargs,
units="norm. flux",
unitSI="$m^{-2}s{-1}$",
normSI=context.normDensity * context.norms["speed"]
normSI=context.normDensity * context.norms["speed"],
)

return var
Expand Down Expand Up @@ -114,7 +164,7 @@ def speed(name: str, context: RMKContext, **kwargs) -> Variable:
**kwargs,
units="norm. speed",
unitSI="$ms^{-1}$",
normSI=context.norms["speed"]
normSI=context.norms["speed"],
)

return var
Expand Down Expand Up @@ -143,7 +193,7 @@ def energyDensity(name: str, context: RMKContext, **kwargs) -> Variable:
**kwargs,
units="norm. en. density",
unitSI="$eV m^{-3}$",
normSI=context.normDensity * context.normTemperature
normSI=context.normDensity * context.normTemperature,
)

return var
Expand Down Expand Up @@ -172,7 +222,7 @@ def energyFlux(name: str, context: RMKContext, **kwargs) -> Variable:
**kwargs,
units="norm. en. flux",
unitSI="$eV m^{-2} s^{-1}$",
normSI=context.norms["heatFlux"]
normSI=context.norms["heatFlux"],
)

return var
Expand Down Expand Up @@ -201,7 +251,7 @@ def electricField(name: str, context: RMKContext, **kwargs) -> Variable:
**kwargs,
units="norm. el. field",
unitSI="$Vm{-1}$",
normSI=context.norms["EField"]
normSI=context.norms["EField"],
)

return var
Expand Down Expand Up @@ -284,7 +334,12 @@ def density(self, initVals: Optional[np.ndarray] = None) -> Variable:
Returns:
Variable: Standard density variable
"""
n = density("n" + self.species.name, self.__context__, data=initVals).withDual()
n = density(
"n" + self.species.name,
self.__context__,
data=initVals,
defaultLatex="n_{" + self.species.latex() + "}",
).withDual()
if self.__associateOnCreation__:
if n.name not in self.species.associatedVarNames:
self.species.associateVar(n, n.dual)
Expand All @@ -308,7 +363,12 @@ def flux(self, initVals: Optional[np.ndarray] = None) -> Variable:
self.__context__,
isOnDualGrid=True,
data=initVals,
).withDual("G" + self.species.name)
defaultLatex="\\left(\\vec{\\Gamma}_{"
+ self.species.name
+ "}\\right)_{dual}",
).withDual(
"G" + self.species.name, "\\vec{\\Gamma}_{" + self.species.latex() + "}"
)
if self.__associateOnCreation__:
if G.name not in self.species.associatedVarNames:
self.species.associateVar(G, G.dual)
Expand All @@ -328,7 +388,10 @@ def energyDensity(self, initVals: Optional[np.ndarray] = None) -> Variable:
Variable: Standard energy density variable
"""
W = energyDensity(
"W" + self.species.name, self.__context__, data=initVals
"W" + self.species.name,
self.__context__,
data=initVals,
defaultLatex="W_{" + self.species.latex() + "}",
).withDual()
if self.__associateOnCreation__:
if W.name not in self.species.associatedVarNames:
Expand All @@ -349,7 +412,11 @@ def temperature(self, initVals: Optional[np.ndarray] = None) -> Variable:
Variable: Standard temperature variable
"""
T = temperature(
"T" + self.species.name, self.__context__, data=initVals, isStationary=True
"T" + self.species.name,
self.__context__,
data=initVals,
isStationary=True,
defaultLatex="T_{" + self.species.latex() + "}",
).withDual()
if self.__associateOnCreation__:
if T.name not in self.species.associatedVarNames:
Expand Down Expand Up @@ -379,7 +446,10 @@ def flowSpeed(self, initVals: Optional[np.ndarray] = None) -> Variable:
"n" + self.species.name + "_dual",
],
isOnDualGrid=True,
).withDual("u" + self.species.name)
defaultLatex="\\left(\\vec{u}_{"
+ self.species.latex()
+ "}\\right)_{dual}",
).withDual("u" + self.species.name, "\\vec{u}_{" + self.species.latex() + "}")
if self.__associateOnCreation__:
if u.name not in self.species.associatedVarNames:
self.species.associateVar(u, u.dual)
Expand All @@ -405,7 +475,10 @@ def heatflux(self, initVals: Optional[np.ndarray] = None) -> Variable:
isStationary=True,
isOnDualGrid=True,
subtype="heatflux",
).withDual("q" + self.species.name)
defaultLatex="\\left(\\vec{q}_{"
+ self.species.latex()
+ "}\\right)_{dual}",
).withDual("q" + self.species.name, "\\vec{q}_{" + self.species.latex() + "}")
if self.__associateOnCreation__:
if q.name not in self.species.associatedVarNames:
self.species.associateVar(q, q.dual)
Expand Down Expand Up @@ -433,6 +506,7 @@ def pressure(self, initVals: Optional[np.ndarray] = None) -> Variable:
node=node(self.density()) * node(self.temperature()),
),
subtype="pressure",
defaultLatex="p_{" + self.species.latex() + "}",
).withDual()
if self.__associateOnCreation__:
if p.name not in self.species.associatedVarNames:
Expand All @@ -458,6 +532,7 @@ def viscosity(self, initVals: Optional[np.ndarray] = None) -> Variable:
data=initVals,
isStationary=True,
subtype="viscosity",
defaultLatex="\\Pi_{" + self.species.latex() + "}",
).withDual()
if self.__associateOnCreation__:
if pi.name not in self.species.associatedVarNames:
Expand Down
Loading