calphy 1.4.2__tar.gz → 1.4.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. {calphy-1.4.2/calphy.egg-info → calphy-1.4.4}/PKG-INFO +1 -1
  2. {calphy-1.4.2 → calphy-1.4.4}/calphy/__init__.py +1 -1
  3. {calphy-1.4.2 → calphy-1.4.4}/calphy/input.py +58 -1
  4. {calphy-1.4.2 → calphy-1.4.4}/calphy/integrators.py +7 -2
  5. {calphy-1.4.2 → calphy-1.4.4}/calphy/phase.py +6 -1
  6. {calphy-1.4.2 → calphy-1.4.4}/calphy/phase_diagram.py +4 -1
  7. {calphy-1.4.2 → calphy-1.4.4}/calphy/postprocessing.py +1 -1
  8. {calphy-1.4.2 → calphy-1.4.4}/calphy/solid.py +1 -1
  9. {calphy-1.4.2 → calphy-1.4.4/calphy.egg-info}/PKG-INFO +1 -1
  10. {calphy-1.4.2 → calphy-1.4.4}/calphy.egg-info/SOURCES.txt +1 -0
  11. {calphy-1.4.2 → calphy-1.4.4}/setup.py +1 -1
  12. calphy-1.4.4/tests/test_ex07.py +25 -0
  13. {calphy-1.4.2 → calphy-1.4.4}/LICENSE +0 -0
  14. {calphy-1.4.2 → calphy-1.4.4}/MANIFEST.in +0 -0
  15. {calphy-1.4.2 → calphy-1.4.4}/README.md +0 -0
  16. {calphy-1.4.2 → calphy-1.4.4}/calphy/alchemy.py +0 -0
  17. {calphy-1.4.2 → calphy-1.4.4}/calphy/clitools.py +0 -0
  18. {calphy-1.4.2 → calphy-1.4.4}/calphy/composition_transformation.py +0 -0
  19. {calphy-1.4.2 → calphy-1.4.4}/calphy/errors.py +0 -0
  20. {calphy-1.4.2 → calphy-1.4.4}/calphy/helpers.py +0 -0
  21. {calphy-1.4.2 → calphy-1.4.4}/calphy/kernel.py +0 -0
  22. {calphy-1.4.2 → calphy-1.4.4}/calphy/liquid.py +0 -0
  23. {calphy-1.4.2 → calphy-1.4.4}/calphy/queuekernel.py +0 -0
  24. {calphy-1.4.2 → calphy-1.4.4}/calphy/routines.py +0 -0
  25. {calphy-1.4.2 → calphy-1.4.4}/calphy/scheduler.py +0 -0
  26. {calphy-1.4.2 → calphy-1.4.4}/calphy/splines.py +0 -0
  27. {calphy-1.4.2 → calphy-1.4.4}/calphy/utils.py +0 -0
  28. {calphy-1.4.2 → calphy-1.4.4}/calphy.egg-info/dependency_links.txt +0 -0
  29. {calphy-1.4.2 → calphy-1.4.4}/calphy.egg-info/entry_points.txt +0 -0
  30. {calphy-1.4.2 → calphy-1.4.4}/calphy.egg-info/not-zip-safe +0 -0
  31. {calphy-1.4.2 → calphy-1.4.4}/calphy.egg-info/requires.txt +0 -0
  32. {calphy-1.4.2 → calphy-1.4.4}/calphy.egg-info/top_level.txt +0 -0
  33. {calphy-1.4.2 → calphy-1.4.4}/setup.cfg +0 -0
  34. {calphy-1.4.2 → calphy-1.4.4}/tests/test_helpers.py +0 -0
  35. {calphy-1.4.2 → calphy-1.4.4}/tests/test_integrators.py +0 -0
  36. {calphy-1.4.2 → calphy-1.4.4}/tests/test_options.py +0 -0
  37. {calphy-1.4.2 → calphy-1.4.4}/tests/test_solid_methods.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: calphy
3
- Version: 1.4.2
3
+ Version: 1.4.4
4
4
  Summary: free energy calculation for python
5
5
  Home-page: https://github.com/ICAMS/calphy
6
6
  Author: Sarath Menon, Yury Lysogorskiy, Ralf Drautz
@@ -4,7 +4,7 @@ from calphy.solid import Solid
4
4
  from calphy.alchemy import Alchemy
5
5
  from calphy.routines import MeltingTemp
6
6
 
7
- __version__ = "1.4.2"
7
+ __version__ = "1.4.4"
8
8
 
9
9
  def addtest(a,b):
10
10
  return a+b
@@ -28,6 +28,7 @@ from pydantic import (
28
28
  Field,
29
29
  ValidationError,
30
30
  model_validator,
31
+ field_validator,
31
32
  conlist,
32
33
  PrivateAttr,
33
34
  )
@@ -48,7 +49,7 @@ from pyscal3.core import structure_dict, element_dict, _make_crystal
48
49
  from ase.io import read, write
49
50
  import shutil
50
51
 
51
- __version__ = "1.4.2"
52
+ __version__ = "1.4.4"
52
53
 
53
54
 
54
55
  def _check_equal(val):
@@ -180,6 +181,22 @@ class MeltingTemperature(BaseModel, title="Input options for melting temperature
180
181
  step: Annotated[int, Field(default=200, ge=20)]
181
182
  attempts: Annotated[int, Field(default=5, ge=1)]
182
183
 
184
+ class MaterialsProject(BaseModel, title='Input options for materials project'):
185
+ api_key: Annotated[str, Field(default="", exclude=True)]
186
+ conventional: Annotated[bool, Field(default=True)]
187
+ target_natoms: Annotated[int, Field(default=1500, description='The structure parsed from materials project would be repeated to approximately this value')]
188
+
189
+ @field_validator("api_key", mode="after")
190
+ def resolve_api_key(cls, v: str) -> str:
191
+ if not v:
192
+ return v
193
+ value = os.getenv(v)
194
+ if not value:
195
+ raise ValueError(
196
+ f"Environment variable '{v}' not found or empty. "
197
+ f"Set it before running, e.g.:\n export {v}='your_api_key_here'"
198
+ )
199
+ return value
183
200
 
184
201
  class Calculation(BaseModel, title="Main input class"):
185
202
  monte_carlo: Optional[MonteCarlo] = MonteCarlo()
@@ -191,6 +208,8 @@ class Calculation(BaseModel, title="Main input class"):
191
208
  tolerance: Optional[Tolerance] = Tolerance()
192
209
  uhlenbeck_ford_model: Optional[UFMP] = UFMP()
193
210
  melting_temperature: Optional[MeltingTemperature] = MeltingTemperature()
211
+ materials_project: Optional[MaterialsProject] = MaterialsProject()
212
+
194
213
  element: Annotated[List[str], BeforeValidator(to_list), Field(default=[])]
195
214
  n_elements: Annotated[int, Field(default=0)]
196
215
  mass: Annotated[List[float], BeforeValidator(to_list), Field(default=[])]
@@ -496,6 +515,44 @@ class Calculation(BaseModel, title="Main input class"):
496
515
  self._original_lattice = self.lattice.lower()
497
516
  write_structure_file = True
498
517
 
518
+ elif self.lattice.split('-')[0] == 'mp':
519
+ #confirm here that API key exists
520
+ if not self.materials_project.api_key:
521
+ raise ValueError('could not find API KEY, pls set it.')
522
+ #now we need to fetch the structure
523
+ try:
524
+ from mp_api.client import MPRester
525
+ except ImportError:
526
+ raise ImportError('Could not import mp_api, make sure you install mp_api package!')
527
+ #now all good
528
+ rest = {
529
+ "use_document_model": False,
530
+ "include_user_agent": True,
531
+ "api_key": self.materials_project.api_key,
532
+ }
533
+ with MPRester(**rest) as mpr:
534
+ docs = mpr.materials.summary.search(material_ids=[self.lattice])
535
+
536
+ structures = []
537
+ for doc in docs:
538
+ struct = doc['structure']
539
+ if self.materials_project.conventional:
540
+ aseatoms = struct.to_conventional().to_ase_atoms()
541
+ else:
542
+ aseatoms = struct.to_primitive().to_ase_atoms()
543
+ structures.append(aseatoms)
544
+ structure = structures[0]
545
+
546
+ if np.prod(self.repeat) == 1:
547
+ x = int(np.ceil((self.materials_project.target_natoms/len(structure))**(1/3)))
548
+ structure = structure.repeat(x)
549
+ else:
550
+ structure = structure.repeat(self.repeat)
551
+
552
+ self._natoms = len(structure)
553
+ self._original_lattice = self.lattice.lower()
554
+ write_structure_file = True
555
+
499
556
  else:
500
557
  # this is a file
501
558
  if not os.path.exists(self.lattice):
@@ -226,6 +226,7 @@ def integrate_rs(simfolder, f0, t,
226
226
 
227
227
  """
228
228
  ws = []
229
+ es = []
229
230
  p = p/(10000*160.21766208)
230
231
 
231
232
  for i in range(1, nsims+1):
@@ -245,9 +246,12 @@ def integrate_rs(simfolder, f0, t,
245
246
  wf = cumtrapz(fdx, flambda,initial=0)
246
247
  wb = cumtrapz(bdx[::-1], blambda[::-1],initial=0)
247
248
  w = (wf + wb) / (2*flambda)
249
+ e = np.max(np.abs((wf - wb)/(2*flambda)))
250
+
248
251
  ws.append(w)
249
-
252
+ es.append(e)
250
253
 
254
+ e_diss = np.min(es)
251
255
  wmean = np.mean(ws, axis=0)
252
256
  werr = np.std(ws, axis=0)
253
257
  temp = t/flambda
@@ -257,8 +261,9 @@ def integrate_rs(simfolder, f0, t,
257
261
  if not return_values:
258
262
  outfile = os.path.join(simfolder, "temperature_sweep.dat")
259
263
  np.savetxt(outfile, np.column_stack((temp, f, werr)))
264
+ return None, e_diss
260
265
  else:
261
- return (temp, f, werr)
266
+ return (temp, f, werr), e_diss
262
267
 
263
268
 
264
269
  def integrate_ps(simfolder, f0, natoms, pi, pf, nsims=1,
@@ -1206,7 +1206,7 @@ class Phase:
1206
1206
  res : list of lists of shape 1x3
1207
1207
  Only returned if `return_values` is True.
1208
1208
  """
1209
- res = integrate_rs(
1209
+ res, ediss = integrate_rs(
1210
1210
  self.simfolder,
1211
1211
  self.fe,
1212
1212
  self.calc._temperature,
@@ -1217,6 +1217,11 @@ class Phase:
1217
1217
  return_values=return_values,
1218
1218
  )
1219
1219
 
1220
+ self.logger.info(f'Maximum energy dissipation along the temperature scaling part: {ediss} eV/atom')
1221
+ if np.abs(ediss) > 1E-4:
1222
+ self.logger.warning(f'Found max energy dissipation of {ediss} along the temperature scaling path. Please ensure there are no structural changes!')
1223
+
1224
+
1220
1225
  if return_values:
1221
1226
  return res
1222
1227
 
@@ -314,7 +314,10 @@ def prepare_inputs_for_phase_diagram(inputyamlfile, calculation_base_name=None):
314
314
 
315
315
  comps = phase['composition']
316
316
  reference_element = comps["reference_element"]
317
- use_composition_scaling = bool(comps["use_composition_scaling"])
317
+ if "use_composition_scaling" in comps.keys():
318
+ use_composition_scaling = bool(comps["use_composition_scaling"])
319
+ else:
320
+ use_composition_scaling = True
318
321
  if str(phase_reference_state) == 'liquid':
319
322
  use_composition_scaling = False
320
323
 
@@ -121,7 +121,7 @@ def gather_results(mainfolder, reduce_composition=True,
121
121
  #print(inpfile)
122
122
  if not os.path.exists(outfile):
123
123
  datadict['status'].append('False')
124
- datadict['free_energy'].append(np.NaN)
124
+ datadict['free_energy'].append(np.nan)
125
125
  #check if error file is found
126
126
  errfile = os.path.join(os.getcwd(), mainfolder, folder+'.sub.err')
127
127
  datadict['error_code'][-1] = _extract_error(errfile)
@@ -299,7 +299,7 @@ class Solid(cph.Phase):
299
299
  lmp.command(f'pair_style {self.calc._pair_style_with_options[0]}')
300
300
 
301
301
  #set up structure
302
- lmp = ph.create_structure(lmp, self.calc, species=self.calc.n_elements+self.calc._ghost_element_count)
302
+ lmp = ph.create_structure(lmp, self.calc)
303
303
 
304
304
  if self.calc.potential_file is None:
305
305
  lmp.command(f'pair_coeff {self.calc.pair_coeff[0]}')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: calphy
3
- Version: 1.4.2
3
+ Version: 1.4.4
4
4
  Summary: free energy calculation for python
5
5
  Home-page: https://github.com/ICAMS/calphy
6
6
  Author: Sarath Menon, Yury Lysogorskiy, Ralf Drautz
@@ -28,6 +28,7 @@ calphy.egg-info/entry_points.txt
28
28
  calphy.egg-info/not-zip-safe
29
29
  calphy.egg-info/requires.txt
30
30
  calphy.egg-info/top_level.txt
31
+ tests/test_ex07.py
31
32
  tests/test_helpers.py
32
33
  tests/test_integrators.py
33
34
  tests/test_options.py
@@ -53,7 +53,7 @@ setup(
53
53
  packages=find_packages(include=['calphy', 'calphy.*']),
54
54
  test_suite='tests',
55
55
  url='https://github.com/ICAMS/calphy',
56
- version='1.4.2',
56
+ version='1.4.4',
57
57
  zip_safe=False,
58
58
  entry_points={
59
59
  'console_scripts': [
@@ -0,0 +1,25 @@
1
+ def test_ex07():
2
+ import calphy
3
+ from calphy.postprocessing import read_report
4
+
5
+ # def test_example07_first_cell_runs():
6
+ # notebook_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../examples/example_07/analysis.ipynb'))
7
+
8
+ # with open(notebook_path, "r", encoding="utf-8") as f:
9
+ # nb = nbformat.read(f, as_version=4)
10
+
11
+ # # Filter just the first code cell
12
+ # first_code_cell = next((cell for cell in nb.cells if cell.cell_type == "code"), None)
13
+
14
+ # if not first_code_cell:
15
+ # pytest.fail("No code cell found in example07.ipynb")
16
+
17
+ # # Create a minimal notebook with only the first cell
18
+ # nb_single = nbformat.v4.new_notebook()
19
+ # nb_single.cells = [first_code_cell]
20
+
21
+ # try:
22
+ # client = NotebookClient(nb_single, timeout=60, kernel_name="pyiron")
23
+ # client.execute()
24
+ # except Exception as e:
25
+ # pytest.fail(f"First code cell in example07.analysis.ipynb failed: {e}")
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes