Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
P
pymatlib
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Rahil Doshi
pymatlib
Commits
fa71279a
Commit
fa71279a
authored
3 months ago
by
Rahil Doshi
Browse files
Options
Downloads
Patches
Plain Diff
Generalize interpolation code to use x and y arrays
parent
1f716b64
Branches
Branches containing commit
Tags
Tags containing commit
No related merge requests found
Pipeline
#77204
passed
3 months ago
Stage: test
Changes
1
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/pymatlib/core/interpolators.py
+70
-70
70 additions, 70 deletions
src/pymatlib/core/interpolators.py
with
70 additions
and
70 deletions
src/pymatlib/core/interpolators.py
+
70
−
70
View file @
fa71279a
...
...
@@ -297,96 +297,96 @@ def interpolate_binary_search(
return
result
def
E
_eq_from_
E
_neq
(
E
_neq
:
np
.
ndarray
)
->
Tuple
[
np
.
ndarray
,
float
]:
delta_min
:
float
=
np
.
min
(
np
.
abs
(
np
.
diff
(
E
_neq
)))
def
y
_eq_from_
y
_neq
(
y
_neq
:
np
.
ndarray
)
->
Tuple
[
np
.
ndarray
,
float
]:
delta_min
:
float
=
np
.
min
(
np
.
abs
(
np
.
diff
(
y
_neq
)))
if
delta_min
<
1.
:
raise
ValueError
(
f
"
Energy density a
rray points are very closely spaced, delta =
{
delta_min
}
"
)
raise
ValueError
(
f
"
A
rray points are very closely spaced, delta =
{
delta_min
}
"
)
print
(
f
"
delta_min:
"
,
delta_min
)
delta_
E
_eq
=
max
(
np
.
floor
(
delta_min
*
0.95
),
1.
)
print
(
f
"
delta_
E
_eq:
"
,
delta_
E
_eq
)
E
_eq
=
np
.
arange
(
E
_neq
[
0
],
E
_neq
[
-
1
]
+
delta_
E
_eq
,
delta_
E
_eq
,
dtype
=
np
.
float64
)
print
(
f
"
np.size(
E
_eq):
"
,
np
.
size
(
E
_eq
))
inv_delta_
E
_eq
:
float
=
float
(
1.
/
(
E
_eq
[
1
]
-
E
_eq
[
0
]))
return
E
_eq
,
inv_delta_
E
_eq
def
create_idx_mapping
(
E
_neq
:
np
.
ndarray
,
E
_eq
:
np
.
ndarray
)
->
np
.
ndarray
:
"""
idx_map = np.zeros(len(
E
_eq), dtype=int)
for i, e in enumerate(
E
_eq):
idx = int(np.searchsorted(
E
_neq, e) - 1)
idx = max(0, min(idx, len(
E
_neq) - 2)) # Bound check
delta_
y
_eq
=
max
(
np
.
floor
(
delta_min
*
0.95
),
1.
)
print
(
f
"
delta_
y
_eq:
"
,
delta_
y
_eq
)
y
_eq
=
np
.
arange
(
y
_neq
[
0
],
y
_neq
[
-
1
]
+
delta_
y
_eq
,
delta_
y
_eq
,
dtype
=
np
.
float64
)
print
(
f
"
np.size(
y
_eq):
"
,
np
.
size
(
y
_eq
))
inv_delta_
y
_eq
:
float
=
float
(
1.
/
(
y
_eq
[
1
]
-
y
_eq
[
0
]))
return
y
_eq
,
inv_delta_
y
_eq
def
create_idx_mapping
(
y
_neq
:
np
.
ndarray
,
y
_eq
:
np
.
ndarray
)
->
np
.
ndarray
:
"""
idx_map = np.zeros(len(
y
_eq), dtype=int)
for i, e in enumerate(
y
_eq):
idx = int(np.searchsorted(
y
_neq, e) - 1)
idx = max(0, min(idx, len(
y
_neq) - 2)) # Bound check
idx_map[i] = idx
"""
# idx_map = np.searchsorted(
E
_neq,
E
_eq) - 1
idx_map
=
np
.
searchsorted
(
E
_neq
,
E
_eq
,
side
=
'
right
'
)
-
1
idx_map
=
np
.
clip
(
idx_map
,
0
,
len
(
E
_neq
)
-
2
)
# idx_map = np.searchsorted(
y
_neq,
y
_eq) - 1
idx_map
=
np
.
searchsorted
(
y
_neq
,
y
_eq
,
side
=
'
right
'
)
-
1
idx_map
=
np
.
clip
(
idx_map
,
0
,
len
(
y
_neq
)
-
2
)
print
(
f
"
idx_map:
{
idx_map
}
"
)
return
idx_map
.
astype
(
np
.
int32
)
def
prepare_interpolation_arrays
(
T
_array
:
np
.
ndarray
,
E
_array
:
np
.
ndarray
,
verbose
=
False
)
->
dict
:
def
prepare_interpolation_arrays
(
x
_array
:
np
.
ndarray
,
y
_array
:
np
.
ndarray
,
verbose
=
False
)
->
dict
:
"""
Validates input arrays and prepares data for interpolation.
Args:
T
_array: Array of
temperature
values
E
_array: Array of
energy densit
y values corresponding to
temperatures
x
_array: Array of
x
values
y
_array: Array of y values corresponding to
x
verbose: If True, prints diagnostic information during processing
Returns:
A dictionary with arrays and metadata for the appropriate interpolation method:
- Common keys:
'
T
_bs
'
,
'
E
_bs
'
,
'
method
'
,
'
is_equidistant
'
,
'
increment
'
- Additional keys for double_lookup method:
'
T
_eq
'
,
'
E
_neq
'
,
'
E
_eq
'
,
'
inv_delta_
E
_eq
'
,
'
idx_map
'
- Common keys:
'
x
_bs
'
,
'
y
_bs
'
,
'
method
'
,
'
is_equidistant
'
,
'
increment
'
- Additional keys for double_lookup method:
'
x
_eq
'
,
'
y
_neq
'
,
'
y
_eq
'
,
'
inv_delta_
y
_eq
'
,
'
idx_map
'
Raises:
ValueError: If arrays don
'
t meet requirements for interpolation
"""
# Convert to numpy arrays if not already
T
_array
=
np
.
asarray
(
T
_array
)
E
_array
=
np
.
asarray
(
E
_array
)
x
_array
=
np
.
asarray
(
x
_array
)
y
_array
=
np
.
asarray
(
y
_array
)
# Basic validation
if
len
(
T
_array
)
!=
len
(
E
_array
):
raise
ValueError
(
f
"
Energy densit
y array (length
{
len
(
E
_array
)
}
) and
temperature
array (length
{
len
(
T
_array
)
}
) must have the same length!
"
)
if
len
(
x
_array
)
!=
len
(
y
_array
):
raise
ValueError
(
f
"
y array (length
{
len
(
y
_array
)
}
) and
x
array (length
{
len
(
x
_array
)
}
) must have the same length!
"
)
if
not
E
_array
.
size
or
not
T
_array
.
size
:
raise
ValueError
(
"
Energy density and temperature
arrays must not be empty!
"
)
if
not
y
_array
.
size
or
not
x
_array
.
size
:
raise
ValueError
(
"
x and y
arrays must not be empty!
"
)
if
len
(
E
_array
)
<
2
:
raise
ValueError
(
f
"
Arrays must contain at least 2 elements, got
{
len
(
E
_array
)
}
!
"
)
if
len
(
y
_array
)
<
2
:
raise
ValueError
(
f
"
Arrays must contain at least 2 elements, got
{
len
(
y
_array
)
}
!
"
)
# Check if arrays are monotonic
T
_increasing
=
np
.
all
(
np
.
diff
(
T
_array
)
>
0
)
T
_decreasing
=
np
.
all
(
np
.
diff
(
T
_array
)
<
0
)
E
_increasing
=
np
.
all
(
np
.
diff
(
E
_array
)
>
0
)
E
_decreasing
=
np
.
all
(
np
.
diff
(
E
_array
)
<
0
)
x
_increasing
=
np
.
all
(
np
.
diff
(
x
_array
)
>
0
)
x
_decreasing
=
np
.
all
(
np
.
diff
(
x
_array
)
<
0
)
y
_increasing
=
np
.
all
(
np
.
diff
(
y
_array
)
>
0
)
y
_decreasing
=
np
.
all
(
np
.
diff
(
y
_array
)
<
0
)
if
not
(
T
_increasing
or
T
_decreasing
):
if
not
(
x
_increasing
or
x
_decreasing
):
raise
ValueError
(
"
Temperature array must be monotonically increasing or decreasing
"
)
if
not
(
E
_increasing
or
E
_decreasing
):
if
not
(
y
_increasing
or
y
_decreasing
):
raise
ValueError
(
"
Energy density array must be monotonically increasing or decreasing
"
)
# Check if energy increases with temperature (both increasing or both decreasing)
if
(
T
_increasing
and
E
_decreasing
)
or
(
T
_decreasing
and
E
_increasing
):
if
(
x
_increasing
and
y
_decreasing
)
or
(
x
_decreasing
and
y
_increasing
):
raise
ValueError
(
"
Energy density must increase with temperature
"
)
# Create copies to avoid modifying original arrays
T
_bs
=
np
.
copy
(
T
_array
)
E
_bs
=
np
.
copy
(
E
_array
)
x
_bs
=
np
.
copy
(
x
_array
)
y
_bs
=
np
.
copy
(
y
_array
)
# Flip arrays if temperature is in descending order
if
T
_decreasing
:
if
x
_decreasing
:
if
verbose
:
print
(
"
Temperature array is descending, flipping arrays for processing
"
)
T
_bs
=
np
.
flip
(
T
_bs
)
E
_bs
=
np
.
flip
(
E
_bs
)
x
_bs
=
np
.
flip
(
x
_bs
)
y
_bs
=
np
.
flip
(
y
_bs
)
# Check for strictly increasing values
has_warnings
=
False
try
:
check_strictly_increasing
(
T
_bs
,
"
Temperature
array
"
)
check_strictly_increasing
(
E
_bs
,
"
Energy densit
y array
"
)
check_strictly_increasing
(
x
_bs
,
"
x
array
"
)
check_strictly_increasing
(
y
_bs
,
"
y array
"
)
except
ValueError
as
e
:
has_warnings
=
True
if
verbose
:
...
...
@@ -394,34 +394,34 @@ def prepare_interpolation_arrays(T_array: np.ndarray, E_array: np.ndarray, verbo
print
(
"
Continuing with interpolation, but results may be less accurate
"
)
# Use the existing check_equidistant function to determine if suitable for double lookup
T
_incr
=
check_equidistant
(
T
_bs
)
is_equidistant
=
T
_incr
!=
0.0
x
_incr
=
check_equidistant
(
x
_bs
)
is_equidistant
=
x
_incr
!=
0.0
# Initialize result with common fields
result
=
{
"
T
_bs
"
:
T
_bs
,
"
E
_bs
"
:
E
_bs
,
"
x
_bs
"
:
x
_bs
,
"
y
_bs
"
:
y
_bs
,
"
method
"
:
"
binary_search
"
,
"
is_equidistant
"
:
is_equidistant
,
"
increment
"
:
T
_incr
if
is_equidistant
else
0.0
,
"
increment
"
:
x
_incr
if
is_equidistant
else
0.0
,
"
has_warnings
"
:
has_warnings
}
# If temperature is equidistant, prepare for double lookup
if
is_equidistant
:
if
verbose
:
print
(
f
"
Temperature
array is equidistant with increment
{
T
_incr
}
, using double lookup
"
)
print
(
f
"
x
array is equidistant with increment
{
x
_incr
}
, using double lookup
"
)
try
:
# Create equidistant energy array and mapping
E
_eq
,
inv_delta_
E
_eq
=
E
_eq_from_
E
_neq
(
E
_bs
)
idx_mapping
=
create_idx_mapping
(
E
_bs
,
E
_eq
)
y
_eq
,
inv_delta_
y
_eq
=
y
_eq_from_
y
_neq
(
y
_bs
)
idx_mapping
=
create_idx_mapping
(
y
_bs
,
y
_eq
)
result
.
update
({
"
T
_eq
"
:
T
_bs
,
"
E
_neq
"
:
E
_bs
,
"
E
_eq
"
:
E
_eq
,
"
inv_delta_
E
_eq
"
:
inv_delta_
E
_eq
,
"
x
_eq
"
:
x
_bs
,
"
y
_neq
"
:
y
_bs
,
"
y
_eq
"
:
y
_eq
,
"
inv_delta_
y
_eq
"
:
inv_delta_
y
_eq
,
"
idx_map
"
:
idx_mapping
,
"
method
"
:
"
double_lookup
"
})
...
...
@@ -430,31 +430,31 @@ def prepare_interpolation_arrays(T_array: np.ndarray, E_array: np.ndarray, verbo
print
(
f
"
Warning: Failed to create double lookup tables:
{
e
}
"
)
print
(
"
Falling back to binary search method
"
)
elif
verbose
:
print
(
"
Temperature
array is not equidistant, using binary search
"
)
print
(
"
x
array is not equidistant, using binary search
"
)
return
result
'''
# Determine if suitable for double lookup (temperature must be equidistant)
T
_diffs = np.diff(
T
_bs)
is_equidistant = np.allclose(
T
_diffs,
T
_diffs[0], rtol=1e-5)
x
_diffs = np.diff(
x
_bs)
is_equidistant = np.allclose(
x
_diffs,
x
_diffs[0], rtol=1e-5)
result = {
"
T
_bs
"
:
T
_bs,
"
E
_bs
"
:
E
_bs,
"
x
_bs
"
:
x
_bs,
"
y
_bs
"
:
y
_bs,
"
method
"
:
"
binary_search
"
}
# If temperature is equidistant, prepare for double lookup
if is_equidistant:
# Create equidistant energy array and mapping
E
_eq, inv_delta_
E
_eq =
E
_eq_from_
E
_neq(
E
_bs)
idx_mapping = create_idx_mapping(
E
_bs,
E
_eq)
y
_eq, inv_delta_
y
_eq =
y
_eq_from_
y
_neq(
y
_bs)
idx_mapping = create_idx_mapping(
y
_bs,
y
_eq)
result.update({
"
T
_eq
"
:
T
_bs,
"
E
_neq
"
:
E
_bs,
"
E
_eq
"
:
E
_eq,
"
inv_delta_
E
_eq
"
: inv_delta_
E
_eq,
"
x
_eq
"
:
x
_bs,
"
y
_neq
"
:
y
_bs,
"
y
_eq
"
:
y
_eq,
"
inv_delta_
y
_eq
"
: inv_delta_
y
_eq,
"
idx_map
"
: idx_mapping,
"
method
"
:
"
double_lookup
"
})
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment