ncrystal-python 3.9.81__py3-none-any.whl
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.
- NCrystal/__init__.py +85 -0
- NCrystal/__main__.py +98 -0
- NCrystal/_chooks.py +854 -0
- NCrystal/_cli_cif2ncmat.py +269 -0
- NCrystal/_cli_endf2ncmat.py +503 -0
- NCrystal/_cli_hfg2ncmat.py +144 -0
- NCrystal/_cli_mcstasunion.py +74 -0
- NCrystal/_cli_ncmat2cpp.py +31 -0
- NCrystal/_cli_ncmat2hkl.py +180 -0
- NCrystal/_cli_nctool.py +1018 -0
- NCrystal/_cli_vdos2ncmat.py +463 -0
- NCrystal/_cli_verifyatompos.py +257 -0
- NCrystal/_cliimpl.py +307 -0
- NCrystal/_cliwrap_config.py +36 -0
- NCrystal/_common.py +499 -0
- NCrystal/_coreimpl.py +114 -0
- NCrystal/_hfgdata.py +546 -0
- NCrystal/_hklobjects.py +136 -0
- NCrystal/_is_std.py +0 -0
- NCrystal/_locatelib.py +210 -0
- NCrystal/_miscimpl.py +354 -0
- NCrystal/_mmc.py +757 -0
- NCrystal/_msg.py +60 -0
- NCrystal/_ncmat2cpp_impl.py +445 -0
- NCrystal/_ncmatimpl.py +2131 -0
- NCrystal/_numpy.py +76 -0
- NCrystal/_testimpl.py +579 -0
- NCrystal/api.py +56 -0
- NCrystal/atomdata.py +177 -0
- NCrystal/cfgstr.py +77 -0
- NCrystal/cifutils.py +1795 -0
- NCrystal/cli.py +96 -0
- NCrystal/constants.py +134 -0
- NCrystal/core.py +1910 -0
- NCrystal/datasrc.py +226 -0
- NCrystal/exceptions.py +66 -0
- NCrystal/hfg2ncmat.py +270 -0
- NCrystal/mcstasutils.py +438 -0
- NCrystal/misc.py +317 -0
- NCrystal/mmc.py +35 -0
- NCrystal/ncmat.py +778 -0
- NCrystal/ncmat2cpp.py +80 -0
- NCrystal/obsolete.py +67 -0
- NCrystal/plot.py +484 -0
- NCrystal/plugins.py +49 -0
- NCrystal/test.py +76 -0
- NCrystal/vdos.py +1034 -0
- ncrystal_python-3.9.81.dist-info/LICENSE +206 -0
- ncrystal_python-3.9.81.dist-info/METADATA +515 -0
- ncrystal_python-3.9.81.dist-info/RECORD +53 -0
- ncrystal_python-3.9.81.dist-info/WHEEL +5 -0
- ncrystal_python-3.9.81.dist-info/entry_points.txt +10 -0
- ncrystal_python-3.9.81.dist-info/top_level.txt +1 -0
NCrystal/ncmat.py
ADDED
|
@@ -0,0 +1,778 @@
|
|
|
1
|
+
|
|
2
|
+
################################################################################
|
|
3
|
+
## ##
|
|
4
|
+
## This file is part of NCrystal (see https://mctools.github.io/ncrystal/) ##
|
|
5
|
+
## ##
|
|
6
|
+
## Copyright 2015-2024 NCrystal developers ##
|
|
7
|
+
## ##
|
|
8
|
+
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
|
9
|
+
## you may not use this file except in compliance with the License. ##
|
|
10
|
+
## You may obtain a copy of the License at ##
|
|
11
|
+
## ##
|
|
12
|
+
## http://www.apache.org/licenses/LICENSE-2.0 ##
|
|
13
|
+
## ##
|
|
14
|
+
## Unless required by applicable law or agreed to in writing, software ##
|
|
15
|
+
## distributed under the License is distributed on an "AS IS" BASIS, ##
|
|
16
|
+
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
|
|
17
|
+
## See the License for the specific language governing permissions and ##
|
|
18
|
+
## limitations under the License. ##
|
|
19
|
+
## ##
|
|
20
|
+
################################################################################
|
|
21
|
+
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
Utilities for NCMAT creation, most notably the NCMATComposer helper class which
|
|
25
|
+
provides a pythonic and flexible object oriented interface for creating NCMAT
|
|
26
|
+
data representing a given material, and for verifying, writing, registering, or
|
|
27
|
+
loading said data.
|
|
28
|
+
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
class NCMATComposer:
|
|
32
|
+
"""Helper class for composing an NCrystal material.
|
|
33
|
+
|
|
34
|
+
One can either start with an empty instance, or bootstrap the process by
|
|
35
|
+
starting the material from an existing NCMAT file, an NCrystal cfg-string,
|
|
36
|
+
an NCrystal.Info object, a CIF file, or from a variety of files (anything
|
|
37
|
+
that can be loaded with ASE and contains a suitable crystal
|
|
38
|
+
structure). Depending on the specifics of the problem, one will then use
|
|
39
|
+
various methods on the object to add or modify material information as
|
|
40
|
+
desired, before ultimately the create_ncmat() method can be used to create
|
|
41
|
+
the resulting NCMAT data. As a convenience the .write() and .register_as()
|
|
42
|
+
methods can be used to write this data as a physical or virtual file
|
|
43
|
+
respectively, or the .load() method can be used to directly load the
|
|
44
|
+
data. Finally, the .plot_xsect() and .inspect() methods can also be used to
|
|
45
|
+
quickly load and investigate the material. It might also be useful to print
|
|
46
|
+
the output of .create_ncmat(), to understand what material has been created.
|
|
47
|
+
|
|
48
|
+
For a more in-depth discussion and usage examples, please refer to the
|
|
49
|
+
example Jupyter-Lab notebooks in the
|
|
50
|
+
https://github.com/mctools/ncrystal-notebooks repository.
|
|
51
|
+
|
|
52
|
+
Note that the "labels" used in the various methods, to identify different
|
|
53
|
+
atoms in the materials are custom user labels. They are simply a way to
|
|
54
|
+
provide a handle associated with a particular atom role or species in the
|
|
55
|
+
material. For many simple materials, all labels will simply have the name of
|
|
56
|
+
the element or isotope ("Al", "Li6", "D", ...), and each type of element and
|
|
57
|
+
isotope will only appear once in the material. That is certainly OK, for
|
|
58
|
+
such simple materials, and in these cases there is no need to concern
|
|
59
|
+
one-self with the atomic composition of each label, since it can be inferred
|
|
60
|
+
from the label itself. However, sometimes different atoms of the same type
|
|
61
|
+
will appear in more than one role in the material (i.e. there might be one
|
|
62
|
+
group of loosely bound aluminium atoms, while a different group of aluminium
|
|
63
|
+
atoms are more tightly bound). Or, it might be that a given label is
|
|
64
|
+
actually associated with an actual mix of elements of isotopes (i.e. a label
|
|
65
|
+
might be associated with a particular isotopic enrichment, or a
|
|
66
|
+
multi-element mixture). In these cases, each label should have it's precise
|
|
67
|
+
composition defined with a call to the .set_composition(..) method.
|
|
68
|
+
|
|
69
|
+
In other words: Unless the label happens to coincide with the name of an
|
|
70
|
+
element or isotope ("Al", "Li6", "D", ...), its atomic composition MUST be
|
|
71
|
+
defined by a call to the .set_composition(..) method. And if a given element
|
|
72
|
+
has more than one role in the material, it must of course also have more
|
|
73
|
+
than one label - one for each role (e.g. "tightAl" and "looseAl").
|
|
74
|
+
|
|
75
|
+
To ensure high data quality and reliability, all crystalline materials will
|
|
76
|
+
by default have their crystal structure verified for consistency with the
|
|
77
|
+
indicated spacegroup, before it is converted to NCMAT data. For that reason,
|
|
78
|
+
the third-party module "spglib" must be installed in order for this
|
|
79
|
+
verification to take place (note that the .refine_crystal_structure() method
|
|
80
|
+
can also be invoked before the material is used, to detect the spacegroup in
|
|
81
|
+
if it was not provided). Fortunately, "spglib" is available both on PyPI and
|
|
82
|
+
in the conda-forge conda channel.
|
|
83
|
+
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
def __init__(self, data = None, fmt = None, quiet = False, plotlabel = None ):
|
|
87
|
+
"""Initialise. Either an empty instance, or if data (and possibly fmt)
|
|
88
|
+
is provided, from a variety of data. Typically, the fmt parameter can be
|
|
89
|
+
left out, but occasionally it might be needed to specify it
|
|
90
|
+
explicitly. Supported fmt's are "cif", "cfgstr", "ncmat", (for NCMAT
|
|
91
|
+
data), "info" (for NCrystal.Info or LoadedMaterial objects), ase (for
|
|
92
|
+
ASE structures). Finally, the format "via_ase" is special, since it will
|
|
93
|
+
always process the input with ASE, even if another more obvious format
|
|
94
|
+
exists (i.e. CIF files will be processed via ASE first, not passed along
|
|
95
|
+
directly to the NCrystal.CIFLoader). As an alternative to the "fmt"
|
|
96
|
+
parameter, one can also invoke the various .from_xxx(..) static
|
|
97
|
+
methods. This has the potential advantage of allowing the specification
|
|
98
|
+
of parameters dedicated only to that input data type.
|
|
99
|
+
|
|
100
|
+
If quiet=True, no informative messages will be emitted, and the plotlabel
|
|
101
|
+
will be passed along to .set_plotlabel().
|
|
102
|
+
|
|
103
|
+
"""
|
|
104
|
+
from ._ncmatimpl import NCMATComposerImpl as Impl
|
|
105
|
+
self.__impl = ( data if isinstance( data, Impl )
|
|
106
|
+
else ( data.__impl if isinstance( data, NCMATComposer )
|
|
107
|
+
else Impl( data = data, fmt = fmt, quiet = quiet ) ) )
|
|
108
|
+
if plotlabel:
|
|
109
|
+
self.set_plotlabel(plotlabel)
|
|
110
|
+
|
|
111
|
+
@staticmethod
|
|
112
|
+
def from_cif( cifsrc, quiet=False, mp_apikey = None,
|
|
113
|
+
uiso_temperature = None,
|
|
114
|
+
override_spacegroup = None, **kwargs ):
|
|
115
|
+
"""Initialise from CIF data (anything suitable for the
|
|
116
|
+
NCrystal.cifutils.CIFSource class). Internally, the loading is carried
|
|
117
|
+
out by instantiating a CIFLoader instance (from the NCrystal.cifutils
|
|
118
|
+
module), and calling it's .create_ncmat_composer() method. Any provided
|
|
119
|
+
arguments will be passsed along to the call to .create_ncmat_composer(),
|
|
120
|
+
except for the override_spacegroup argument which is used when the
|
|
121
|
+
CIFLoader is instantiated.
|
|
122
|
+
|
|
123
|
+
For advanced work, it might be better to use the CIFLoader class
|
|
124
|
+
directly.
|
|
125
|
+
"""
|
|
126
|
+
from ._ncmatimpl import NCMATComposerImpl as Impl
|
|
127
|
+
return NCMATComposer( Impl.from_cif( cifsrc=cifsrc, quiet=quiet,
|
|
128
|
+
uiso_temperature = uiso_temperature,
|
|
129
|
+
override_spacegroup = override_spacegroup,
|
|
130
|
+
mp_apikey = mp_apikey, **kwargs ) )
|
|
131
|
+
|
|
132
|
+
@staticmethod
|
|
133
|
+
def from_cfgstr( cfgstr ):
|
|
134
|
+
"""Loads an Info object from the given cfg-string, and pass it on to
|
|
135
|
+
.from_info(..)."""
|
|
136
|
+
from ._ncmatimpl import NCMATComposerImpl as Impl
|
|
137
|
+
return NCMATComposer( Impl.from_cfgstr( cfgstr = cfgstr ) )
|
|
138
|
+
|
|
139
|
+
@staticmethod
|
|
140
|
+
def from_ase( ase_obj, ase_format = None, *, quiet = False, **kwargs ):
|
|
141
|
+
"""Initialise from an ASE object. This is actually done internally by
|
|
142
|
+
first converting the ASE object to CIF data, and then subsequently
|
|
143
|
+
passing it on to the .from_cif(..) method (any **kwargs will be
|
|
144
|
+
passed along to the .from_cif call). If the provided ase_obj is not
|
|
145
|
+
actually already an ASE object, an attempt is done to load it into one
|
|
146
|
+
via the ase.io.read module (mimicking the fmt="via_ase" behaviour of the
|
|
147
|
+
__init__ method). In that case, any value in the ase_format parameter
|
|
148
|
+
will be passed along to ase.io.read's format parameter.
|
|
149
|
+
"""
|
|
150
|
+
from ._ncmatimpl import NCMATComposerImpl as Impl
|
|
151
|
+
return NCMATComposer( Impl.from_ase( ase_obj = ase_obj, quiet = quiet,
|
|
152
|
+
ase_format = ase_format, **kwargs ) )
|
|
153
|
+
|
|
154
|
+
@staticmethod
|
|
155
|
+
def from_info( info_obj ):
|
|
156
|
+
"""Initialise from provided Info (or LoadedMaterial) object.
|
|
157
|
+
|
|
158
|
+
In case the material is a gas, the temperature of the resulting
|
|
159
|
+
NCMATComposer will for safety be locked (due to the strong temperature
|
|
160
|
+
dependency of densities for gasses).
|
|
161
|
+
"""
|
|
162
|
+
from ._ncmatimpl import NCMATComposerImpl as Impl
|
|
163
|
+
return NCMATComposer( Impl.from_info( info_obj = info_obj ) )
|
|
164
|
+
|
|
165
|
+
@staticmethod
|
|
166
|
+
def from_ncmat( data ):
|
|
167
|
+
"""Loads an Info object from the given NCMAT data, and passes it on to
|
|
168
|
+
.from_info(..). If the NCMAT data has no newlines and doesn't start with
|
|
169
|
+
'NCMAT', it will actually be passed directly on to .from_cfgstr(..)
|
|
170
|
+
instead.
|
|
171
|
+
"""
|
|
172
|
+
from ._ncmatimpl import NCMATComposerImpl as Impl
|
|
173
|
+
return NCMATComposer( Impl.from_ncmat( data ) )
|
|
174
|
+
|
|
175
|
+
@staticmethod
|
|
176
|
+
def from_hfg( spec,
|
|
177
|
+
formula, *,
|
|
178
|
+
density,
|
|
179
|
+
title,
|
|
180
|
+
debyetemp = 400.0,
|
|
181
|
+
verbose = True,
|
|
182
|
+
notrim = False ):
|
|
183
|
+
"""Constructs an amorphous hydrogen-rich material via the hfg2ncmat
|
|
184
|
+
function from the NCrystal.hfg2ncmat module. Refer to that function for
|
|
185
|
+
usage instructions.
|
|
186
|
+
"""
|
|
187
|
+
from .hfg2ncmat import _default_debye_temp, hfg2ncmat
|
|
188
|
+
from ._ncmatimpl import NCMATComposerImpl as Impl
|
|
189
|
+
assert _default_debye_temp()==400.0, "from_hfg default must be updated"
|
|
190
|
+
ncmat = hfg2ncmat( spec = spec,
|
|
191
|
+
formula = formula,
|
|
192
|
+
density = density,
|
|
193
|
+
title = title,
|
|
194
|
+
debyetemp = debyetemp,
|
|
195
|
+
verbose = verbose,
|
|
196
|
+
notrim = notrim )
|
|
197
|
+
c = NCMATComposer( Impl.from_ncmat( ncmat,
|
|
198
|
+
keep_header=True ) )
|
|
199
|
+
c.set_plotlabel(title)
|
|
200
|
+
return c
|
|
201
|
+
|
|
202
|
+
def __call__( self, cfg_params = None, **kwargs ):
|
|
203
|
+
"""Convenience short-cut for the .create_ncmat() method"""
|
|
204
|
+
return self.create_ncmat( cfg_params = cfg_params, **kwargs )
|
|
205
|
+
|
|
206
|
+
def update_atomdb( self, element_or_isotope, data = None, *, mass = None, coh_scat_len=None, incoh_xs=None, abs_xs=None ):
|
|
207
|
+
"""Specify atom data for particular element or isotope. Either specify
|
|
208
|
+
the data parameter as a string (in @ATOMDB format like "28.97649466525u
|
|
209
|
+
4.7fm 0.001b 0.101b") or AtomData object, or put all four physics values
|
|
210
|
+
(mass, coh_scat_len, incoh_xs, and abs_xs) directly as floating point
|
|
211
|
+
numbers. More specifically these numbers are mass value (amu), coherent
|
|
212
|
+
scattering length (fm), incoherent cross section (barn), and absorption
|
|
213
|
+
cross section @v_n=2200m/s (barn).
|
|
214
|
+
"""
|
|
215
|
+
return self.__impl.update_atomdb( element_or_isotope,data=data,mass=mass,
|
|
216
|
+
coh_scat_len=coh_scat_len,incoh_xs=incoh_xs,abs_xs=abs_xs )
|
|
217
|
+
|
|
218
|
+
def find_label( self, element, allow_multi=False ):
|
|
219
|
+
"""Attempt to locate label which has a composition containing provided
|
|
220
|
+
element (which can be a string name or Z value like Al, 13, B10,
|
|
221
|
+
...). If exactly one such label exists, it will be returned, otherwise
|
|
222
|
+
None is returned. If allow_multi==True, the result(s) will instead be
|
|
223
|
+
returned as a list, and all matching labels will be returned.
|
|
224
|
+
"""
|
|
225
|
+
return self.__impl.find_label( element = element, allow_multi = allow_multi )
|
|
226
|
+
|
|
227
|
+
def set_composition( self, label, *composition ):
|
|
228
|
+
"""Use like .set_composition('H','D') or .set_composition('H is D'). Mixtures
|
|
229
|
+
can also be defined, for instance like .set_composition('H','0.2 H1 0.8
|
|
230
|
+
H2'). For a more in-depth discussion of the syntax, consult the @ATOMDB
|
|
231
|
+
section on https://github.com/mctools/ncrystal/wiki/NCMAT-format
|
|
232
|
+
|
|
233
|
+
Set atomic composition associated with a given label. Usage examples:
|
|
234
|
+
|
|
235
|
+
.set_composition('mylbl','Al') #mylbl now has a composition of only (natural) Al atoms.
|
|
236
|
+
.set_composition('Al','Al') #Al atoms (notice this call is not needed
|
|
237
|
+
#since the label is already an element name).
|
|
238
|
+
.set_composition('Al','Cr') #Well if you want to use confusing labels you can
|
|
239
|
+
.set_composition('mylbl','Li6') #specific isotope
|
|
240
|
+
.set_composition('mylbl','D') #deuterium is supported by either 'D' or 'H2'
|
|
241
|
+
|
|
242
|
+
More complicated mixtures are supported as well:
|
|
243
|
+
|
|
244
|
+
.set_composition('mylbl',0.95,'B10',0.05,'B11')#enriched boron
|
|
245
|
+
.set_composition('mylbl',[0.95,'B10',0.05,'B11'])#same but defined via sequence
|
|
246
|
+
.set_composition('mylbl',[(0.95,'B10'),(0.05,'B11')])#same but defined via sequence of pairs
|
|
247
|
+
.set_composition('mylbl','0.95 B10 0.05 B11')#same but via a string in @ATOMDB-like form.
|
|
248
|
+
.set_composition('mylbl is 0.95 B10 0.05 B11')#same but even more @ATOMDB like.
|
|
249
|
+
.set_composition('Al is 0.99 Al 0.005 Cr 0.005 B10')#mix and match elements and isotopes
|
|
250
|
+
"""
|
|
251
|
+
return self.__impl.set_composition( label, *composition )
|
|
252
|
+
|
|
253
|
+
def remap_atom( self, element_or_isotope, *composition ):
|
|
254
|
+
"""Calling this method updates all usage of the denoted
|
|
255
|
+
element_or_isotope marker ('C', 'Al', 'D', 'B10', ...) and replaces it
|
|
256
|
+
with the particular composition. For instance, .remap_atom('H','D') can
|
|
257
|
+
be used to fully deuterate a material. For a description of the allowed
|
|
258
|
+
compositon syntax, refer to the .set_composition method.
|
|
259
|
+
|
|
260
|
+
The remapping will only affect labels and compositions that have already
|
|
261
|
+
been added to the NCMATComposer object.
|
|
262
|
+
"""
|
|
263
|
+
return self.__impl.remap_atom( element_or_isotope, *composition )
|
|
264
|
+
|
|
265
|
+
def clear_comments( self ):
|
|
266
|
+
"""Clear comments added with the add_comments method."""
|
|
267
|
+
return self.__impl.clear_comments()
|
|
268
|
+
|
|
269
|
+
def add_comments( self, comments, add_empty_line_divider=False ):
|
|
270
|
+
"""Add comments (string or list of strings) to the top of NCMAT data."""
|
|
271
|
+
return self.__impl.add_comments( comments = comments,
|
|
272
|
+
add_empty_line_divider = add_empty_line_divider )
|
|
273
|
+
|
|
274
|
+
def clone(self):
|
|
275
|
+
"""Return a new independent NCMATComposer object which is a clone of the
|
|
276
|
+
current one."""
|
|
277
|
+
return NCMATComposer( self.__impl.clone() )
|
|
278
|
+
|
|
279
|
+
def get_cache_key( self ):
|
|
280
|
+
"""
|
|
281
|
+
Returns tuple of integers which will be unchanged if generated NCMAT
|
|
282
|
+
content is unchanged. Note that this is partially based on memory
|
|
283
|
+
addresses of python objects, so the keys are NOT reproducible outside
|
|
284
|
+
the current process.
|
|
285
|
+
"""
|
|
286
|
+
return self.__impl.get_cache_key()
|
|
287
|
+
|
|
288
|
+
def to_dict(self):
|
|
289
|
+
return self.__impl.to_dict()
|
|
290
|
+
|
|
291
|
+
def set_cellsg( self, *, a,b,c, alpha,beta,gamma, spacegroup=None ):
|
|
292
|
+
"""Assumes alpha,beta,gamma in degrees, a,b,c in Aangstrom, spacegroup
|
|
293
|
+
an int in range 1..230."""
|
|
294
|
+
return self.__impl.set_cellsg( a=a,b=b,c=c,
|
|
295
|
+
alpha=alpha,beta=beta,gamma=gamma,
|
|
296
|
+
spacegroup=spacegroup )
|
|
297
|
+
|
|
298
|
+
def set_cellsg_cubic( self, a, *, spacegroup=None ):
|
|
299
|
+
"""Like .set_cellsg but will set b=c=a and alpha=beta=gamma=90."""
|
|
300
|
+
return self.__impl.set_cellsg_cubic( a = a, spacegroup = spacegroup )
|
|
301
|
+
|
|
302
|
+
def set_atompos( self, atompos ):
|
|
303
|
+
"""The atompos parameter must be list of entries
|
|
304
|
+
(label,x,y,z) or (label,x,y,z,site_occupancy).
|
|
305
|
+
|
|
306
|
+
If provided, the site_occupancy value (a number in (0,1] must be the
|
|
307
|
+
same for all identical labels.
|
|
308
|
+
|
|
309
|
+
The site_occupancy parameter is for now highly experimental and will
|
|
310
|
+
result in generated NCMAT files with fake sterile atoms inserted for
|
|
311
|
+
technical reasons (resulting in a higher density but hopefully correct
|
|
312
|
+
physics as long as the user does not subsequently try to override the
|
|
313
|
+
density directly via the cfg-string parameters). This is perfectly fine
|
|
314
|
+
for usage in a MC simulation context where NCrystal provides the entire
|
|
315
|
+
physics of the material (e.g. McStas), but in a context where a base
|
|
316
|
+
material must be created using the composition from NCrystal
|
|
317
|
+
(e.g. Geant4 or OpenMC), it most likely will result in an error.
|
|
318
|
+
"""
|
|
319
|
+
return self.__impl.set_atompos( atompos = atompos )
|
|
320
|
+
|
|
321
|
+
def refine_crystal_structure( self, symprec = 0.01, quiet = False ):
|
|
322
|
+
"""Attempt to refine the crystal structure (does nothing if not a
|
|
323
|
+
crystalline material). This ignores the spacegroup number (if any), and
|
|
324
|
+
uses spglib to refine and standardise the crystal structure based on the
|
|
325
|
+
provided unit cell parameters and atomic positions. The unit cell
|
|
326
|
+
parameters, spacegroup number, and atomic positions, are all updated
|
|
327
|
+
accordingly.
|
|
328
|
+
"""
|
|
329
|
+
return self.__impl.refine_crystal_structure( symprec = symprec,
|
|
330
|
+
quiet = quiet )
|
|
331
|
+
|
|
332
|
+
def verify_crystal_structure( self, symprec = 0.01, quiet = False ):
|
|
333
|
+
"""Attempt to verify the crystal structure (does nothing if not a
|
|
334
|
+
crystalline material). This requires a spacegroup number to be
|
|
335
|
+
available, and uses spglib to verify that the crystal structure (unit
|
|
336
|
+
cell and atom positions) is consistent with that spacegroup
|
|
337
|
+
number. Raises an exception in case the structure could not be verified,
|
|
338
|
+
otherwise does nothing.
|
|
339
|
+
"""
|
|
340
|
+
return self.__impl.verify_crystal_structure( symprec = symprec,
|
|
341
|
+
quiet = quiet )
|
|
342
|
+
|
|
343
|
+
def set_density( self, value, unit = 'g/cm3' ):
|
|
344
|
+
"""
|
|
345
|
+
Specify material density for non-crystalline materials. If provided,
|
|
346
|
+
the unit must be a string which is one of "g/cm3" (default) , "kg/m3",
|
|
347
|
+
or "atoms/Aa3". Note that any material can have its density modified
|
|
348
|
+
with the cfg-string parameter "density", while the present method is
|
|
349
|
+
instead used to provide the basic density embedded in NCMAT format for
|
|
350
|
+
non-crystalline materials.
|
|
351
|
+
"""
|
|
352
|
+
return self.__impl.set_density( value = value, unit = unit )
|
|
353
|
+
|
|
354
|
+
def set_fraction( self, label, value ):
|
|
355
|
+
"""
|
|
356
|
+
Specify fraction of component associated with a given label. This is
|
|
357
|
+
not needed for crystalline materials, where the fractions can be
|
|
358
|
+
inferred from the unit cell contents. Note that the various
|
|
359
|
+
set_dyninfo_xxx methods have an optional fraction parameter, which can
|
|
360
|
+
also be used to set the fraction directly.
|
|
361
|
+
|
|
362
|
+
"""
|
|
363
|
+
return self.__impl.set_fraction( label = label, value = value )
|
|
364
|
+
|
|
365
|
+
def allow_fallback_dyninfo( self, debye_temp = 300.0 ):
|
|
366
|
+
"""For crystalline materials only, allow a fall-back modelling of any
|
|
367
|
+
components with absent dynamic information via a VDOS-Debye model using
|
|
368
|
+
the specified Debye temperature.
|
|
369
|
+
"""
|
|
370
|
+
return self.__impl.allow_fallback_dyninfo( debye_temp = debye_temp )
|
|
371
|
+
|
|
372
|
+
def set_dyninfo_vdos( self, label, vdos_egrid, vdos, *, fraction = None, comment = None ):
|
|
373
|
+
"""Set dynamics of component to be modelled by a 1D phonon density of
|
|
374
|
+
state (DOS) curve (VDOS="Vibrational DOS"). This is the preferred way to
|
|
375
|
+
provide dynamics for components of solid materials, as it not only
|
|
376
|
+
gives enough information to estimate the Debye-Waller factors needed for
|
|
377
|
+
elastic scattering in all such materials, but also allows realistic
|
|
378
|
+
inelastic scattering via expansion into full 2D scattering kernels.
|
|
379
|
+
This model is not appropriate for gaseous or liquid materials.
|
|
380
|
+
"""
|
|
381
|
+
return self.__impl.set_dyninfo_vdos( label = label,
|
|
382
|
+
vdos_egrid = vdos_egrid,
|
|
383
|
+
vdos = vdos,
|
|
384
|
+
comment = comment,
|
|
385
|
+
fraction = fraction )
|
|
386
|
+
|
|
387
|
+
def set_dyninfo_vdosdebye( self, label, debye_temp, *, fraction = None, comment = None ):
|
|
388
|
+
"""Set dynamics of component to be modelled by a Debye temperature. This
|
|
389
|
+
allows temperature-dependent atomic displacements and Debye-Waller
|
|
390
|
+
factors to be estimated, and inelastic scattering will be modelled based
|
|
391
|
+
on an idealised VDOS curve (a parabola up to a cutoff frequency
|
|
392
|
+
corresponding to E=k*T_debye). This model is only appropriate for solid
|
|
393
|
+
materials.
|
|
394
|
+
"""
|
|
395
|
+
return self.__impl.set_dyninfo_vdosdebye( label = label,
|
|
396
|
+
debye_temp = debye_temp,
|
|
397
|
+
comment = comment,
|
|
398
|
+
fraction = fraction )
|
|
399
|
+
|
|
400
|
+
def set_dyninfo_debyetemp( self, label, debye_temp, *, fraction = None, comment = None ):
|
|
401
|
+
"""Alias for set_dyninfo_vdosdebye."""
|
|
402
|
+
return self.set_dyninfo_vdosdebye( label=label, debye_temp=debye_temp,
|
|
403
|
+
fraction=fraction, comment=comment )
|
|
404
|
+
|
|
405
|
+
def set_dyninfo_msd( self, label, msd, *, temperature, fraction = None, comment = None, ):
|
|
406
|
+
"""Calculate and set Debye temperature based on
|
|
407
|
+
mean-squared-displacement (msd) value (in Aa^2). This also needs the
|
|
408
|
+
temperature value for which the msd value is associated (in
|
|
409
|
+
kelvin). Note that this temperature value is NOT necessarily the
|
|
410
|
+
temperature at which the material will later be used. See
|
|
411
|
+
.set_dyninfo_vdosdebye(..) for further information about the resulting
|
|
412
|
+
modelling.
|
|
413
|
+
"""
|
|
414
|
+
return self.__impl.set_dyninfo_msd( label = label,
|
|
415
|
+
msd = msd,
|
|
416
|
+
temperature = temperature,
|
|
417
|
+
comment = comment,
|
|
418
|
+
fraction = fraction )
|
|
419
|
+
|
|
420
|
+
def set_dyninfo_uiso( self, label, uiso, temperature, *, fraction = None, comment = None ):
|
|
421
|
+
"""Alias for set_dyninfo_msd. The uiso value is just another name for
|
|
422
|
+
"msd" and both have a unit of Aa^2."""
|
|
423
|
+
return self.set_dyninfo_msd( label=label, msd=uiso, temperature=temperature,
|
|
424
|
+
fraction=fraction, comment=comment )
|
|
425
|
+
|
|
426
|
+
def set_dyninfo_scatknl( self, label, *, alphagrid, betagrid, temperature,
|
|
427
|
+
sab = None, sab_scaled = None, egrid = None,
|
|
428
|
+
fraction = None, comment = None ):
|
|
429
|
+
"""Set dynamics of component to be modelled by the provided 2D
|
|
430
|
+
S(alpha,beta) ("sab") scattering kernel. Such kernels are
|
|
431
|
+
temperature-dependent, so one must also specify the temperature for
|
|
432
|
+
which the kernel is valid, which of necessity will lock the temperature
|
|
433
|
+
of the entire material at that temperature. As NCrystal currently is not
|
|
434
|
+
able to estimate atomic displacements and Debye-Waller factors from such
|
|
435
|
+
kernels, they can not be used with crystalline materials at all, and are
|
|
436
|
+
in principle not suitable for amorphous solids either, as even
|
|
437
|
+
incoherent-elastic contributions will be absent. Thus, this modelling is
|
|
438
|
+
mainly intended for liquids or gasses.
|
|
439
|
+
"""
|
|
440
|
+
return self.__impl.set_dyninfo_scatknl( label = label,
|
|
441
|
+
alphagrid = alphagrid,
|
|
442
|
+
betagrid = betagrid,
|
|
443
|
+
temperature = temperature,
|
|
444
|
+
sab = sab,
|
|
445
|
+
sab_scaled = sab_scaled,
|
|
446
|
+
egrid = egrid,
|
|
447
|
+
comment = comment,
|
|
448
|
+
fraction = fraction )
|
|
449
|
+
|
|
450
|
+
def set_dyninfo_freegas( self, label, *, fraction = None, comment = None ):
|
|
451
|
+
"""Set dynamics of component to be modelled by a free gas description (a gas
|
|
452
|
+
of non-interacting atoms). This model is not suitable for solid
|
|
453
|
+
materials, except as a crude approximation. It is specifically
|
|
454
|
+
disallowed for crystalline materials, since it does not provide atomic
|
|
455
|
+
displacements (Debye-Waller factors). See .set_dyninfo_debyetemp(..),
|
|
456
|
+
.set_dyninfo_msd(..) and .allow_fallback_dyninfo() for easy
|
|
457
|
+
(low-realism) alternatives for crystalline materials.
|
|
458
|
+
"""
|
|
459
|
+
return self.__impl.set_dyninfo_freegas( label = label,
|
|
460
|
+
comment = comment,
|
|
461
|
+
fraction = fraction )
|
|
462
|
+
|
|
463
|
+
def set_dyninfo_sterile( self, label, *, fraction = None, comment = None ):
|
|
464
|
+
"""Set dynamics of component to be modelled as being without any scattering
|
|
465
|
+
cross section. This model is obviously unrealistic and exists for
|
|
466
|
+
debugging purposes only. It can not be used for crystalline materials
|
|
467
|
+
(for these one could use .update_atomdb instead to introduce atoms with
|
|
468
|
+
no scattering cross section into the crystal).
|
|
469
|
+
"""
|
|
470
|
+
return self.__impl.set_dyninfo_sterile( label = label,
|
|
471
|
+
comment = comment,
|
|
472
|
+
fraction = fraction )
|
|
473
|
+
|
|
474
|
+
def set_dyninfo_from_object( self, label, source_dyninfo, comment = None, fraction=None ):
|
|
475
|
+
"""Set dyninfo of given label based on existing NCrystal.DynamicInfo
|
|
476
|
+
object.
|
|
477
|
+
|
|
478
|
+
Note that in principle the flow NCMAT-data -> Info -> NCMATComposer ->
|
|
479
|
+
NCMAT-data is not guaranteed to be 100% lossless, but in practice the
|
|
480
|
+
resulting physics is unlikely to be unaffected by this. For a guaranteed
|
|
481
|
+
loss-less operation, one must manually edit the NCMAT data and copy the
|
|
482
|
+
exact lines of the relevant @DYNINFO section into the new NCMAT data
|
|
483
|
+
(this is beyond the scope of the NCMATComposer).
|
|
484
|
+
"""
|
|
485
|
+
return self.__impl.set_dyninfo_from_object( label = label,
|
|
486
|
+
source_dyninfo = source_dyninfo,
|
|
487
|
+
comment = comment,
|
|
488
|
+
fraction = fraction )
|
|
489
|
+
|
|
490
|
+
def transfer_dyninfo_objects( self, source, mapping = None, allow_none = False ):
|
|
491
|
+
"""Set dyninfo from source. Source can be a list of
|
|
492
|
+
NCrystal.DynamicInfo, a single NCrystal.DynamicInfo info object, or any
|
|
493
|
+
sort of material source like an Info object, a cfg-str, NCMAT data, etc.
|
|
494
|
+
|
|
495
|
+
If a mapping dict is provided, it must be a mapping between labels used
|
|
496
|
+
on the NCMATComposer object and display labels in the source DynamicInfo
|
|
497
|
+
objects (example: {"H":"H","mylbl":"Al","O16":"O"}). If a mapping is NOT
|
|
498
|
+
provided, an automatic mapping will be attempted based on element Z
|
|
499
|
+
values between source entries and labels already registered in the
|
|
500
|
+
composer (in this case it must be possible to determine the composition
|
|
501
|
+
of all labels). Any excess entries in the source will be ignored.
|
|
502
|
+
|
|
503
|
+
An NCBadInput error will be raised if no dynamic information is actually
|
|
504
|
+
transferred, unless allow_none=True is provided.
|
|
505
|
+
|
|
506
|
+
"""
|
|
507
|
+
return self.__impl.transfer_dyninfo_objects( source = source,
|
|
508
|
+
mapping = mapping,
|
|
509
|
+
allow_none = allow_none )
|
|
510
|
+
|
|
511
|
+
def set_state_of_matter( self, state_of_matter ):
|
|
512
|
+
"""Explicitly specify the state of matter, which must be a string with
|
|
513
|
+
value of "solid", "liquid", or "gas". Call it with an empty string or
|
|
514
|
+
None to clear the information.
|
|
515
|
+
|
|
516
|
+
Note that NCrystal will automatically classify materials as "solid" if
|
|
517
|
+
they are crystalline materials and/or have dynamic information of the
|
|
518
|
+
types vdos, vdosdebye, or msd. Trying to change the state of matter
|
|
519
|
+
value for such materials will result in an error at a later stage.
|
|
520
|
+
"""
|
|
521
|
+
return self.__impl.set_state_of_matter( state_of_matter )
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
def add_secondary_phase(self, fraction, cfgstr, normalise = True ):
|
|
525
|
+
"""Add a secondary phase to the material, by specifying the phase volume
|
|
526
|
+
fraction and a cfg-strings defining the content of the secondary
|
|
527
|
+
phase. For instance a material with air bubbles inside, might be
|
|
528
|
+
emulated by calling .add_secondary_phase(0.05,"gasmix::air"), which
|
|
529
|
+
would add a secondary phase to the material, occupying 5% of the volume
|
|
530
|
+
and containing air. For details, please see the discussion under the
|
|
531
|
+
heading "The @OTHERPHASES section" in the document at
|
|
532
|
+
https://github.com/mctools/ncrystal/wiki/NCMAT-format.
|
|
533
|
+
|
|
534
|
+
Unless normalise=False, the cfg-string will be normalised with a call to
|
|
535
|
+
normaliseCfg(..) from the NCrystal.cfgstr module.
|
|
536
|
+
"""
|
|
537
|
+
return self.__impl.add_secondary_phase( fraction = fraction,
|
|
538
|
+
cfgstr = cfgstr,
|
|
539
|
+
normalise = normalise )
|
|
540
|
+
|
|
541
|
+
def add_hard_sphere_sans_model( self, sphere_radius ):
|
|
542
|
+
"""As a technology preview of future more complete SANS support, one can
|
|
543
|
+
for now use this method to add hard-sphere SANS scattering between the
|
|
544
|
+
primary phase, and the first phase added with .add_secondary_phase(..)
|
|
545
|
+
Note that as this results in a @CUSTOM_HARDSPHERESANS section in the
|
|
546
|
+
resulting NCMAT data (because it is a tech-preview), warnings will be
|
|
547
|
+
emitted when the data is subsequently loaded by NCrystal.
|
|
548
|
+
|
|
549
|
+
The implemented hard-sphere model only has a single free parameter, the
|
|
550
|
+
sphere_radius in angstrom.
|
|
551
|
+
"""
|
|
552
|
+
return self.__impl.add_hard_sphere_sans_model(sphere_radius=sphere_radius)
|
|
553
|
+
|
|
554
|
+
def add_raw_content( self, content ):
|
|
555
|
+
"""This is an experts-only method for adding raw text data to be
|
|
556
|
+
appended to the generated NCMAT data. Note that multiple calls to this
|
|
557
|
+
method will simply append more content, if you wish to remove content
|
|
558
|
+
again you must call clear_raw_content.
|
|
559
|
+
|
|
560
|
+
Note that this method does not necessarily add a newline to your content
|
|
561
|
+
if it is missing.
|
|
562
|
+
|
|
563
|
+
"""
|
|
564
|
+
return self.__impl.add_raw_content( content )
|
|
565
|
+
|
|
566
|
+
def clear_raw_content( self ):
|
|
567
|
+
"""Remove any content added by calls to .add_raw_content(..)"""
|
|
568
|
+
return self.__impl.clear_raw_content()
|
|
569
|
+
|
|
570
|
+
def get_raw_content( self ):
|
|
571
|
+
"""Return any content added by calls to .add_raw_content(..). Returns an
|
|
572
|
+
empty string if no such content was added."""
|
|
573
|
+
return self.__impl.get_raw_content()
|
|
574
|
+
|
|
575
|
+
def set_custom_section_data( self, section_name, content ):
|
|
576
|
+
"""Add a @CUSTOM_<sectionname> section with the provided content to the
|
|
577
|
+
generated NCMAT data. Note that multiple calls to this method with the
|
|
578
|
+
same section_name will simply override the content of that custom
|
|
579
|
+
section. To completely remove a previously added custom section, use the
|
|
580
|
+
.clear_custom_section_data(..) method.
|
|
581
|
+
"""
|
|
582
|
+
return self.__impl.set_custom_section_data( section_name, content )
|
|
583
|
+
|
|
584
|
+
def get_custom_section_data( self, section_name = None ):
|
|
585
|
+
"""Access any @CUSTOM_<sectionname> contents which was previously added
|
|
586
|
+
with the .set_custom_section_data(..) method. Returns None if data for
|
|
587
|
+
that section was not added. If called without parameters, a dictionary
|
|
588
|
+
of all such data in the form { section_name : content, ... } is
|
|
589
|
+
returned instead.
|
|
590
|
+
"""
|
|
591
|
+
return self.__impl.get_custom_section_data( section_name )
|
|
592
|
+
|
|
593
|
+
def clear_custom_section_data( self, section_name = None ):
|
|
594
|
+
"""Remove any @CUSTOM_<sectionname> section previously added by calling
|
|
595
|
+
set_custom_section_data. Does nothing if no such section was previously
|
|
596
|
+
added. Calling with no arguments clears all custom section data.
|
|
597
|
+
"""
|
|
598
|
+
return self.__impl.clear_custom_section_data( section_name )
|
|
599
|
+
|
|
600
|
+
def lock_temperature( self, value ):
|
|
601
|
+
"""
|
|
602
|
+
Lock the temperature of the material to the given value. This not
|
|
603
|
+
only changes the default temperature of the material, but also "locks"
|
|
604
|
+
it in the sense that any attempts at using the cfg-level variable "temp"
|
|
605
|
+
to modify the temperature will result in an error. See also the
|
|
606
|
+
.set_default_temperature() method. Call with value=None to clear any
|
|
607
|
+
previous effects of .lock_temperature() or .set_default_temperature().
|
|
608
|
+
"""
|
|
609
|
+
return self.__impl.lock_temperature( value )
|
|
610
|
+
|
|
611
|
+
def set_default_temperature( self, value ):
|
|
612
|
+
"""
|
|
613
|
+
Modify the default temperature of the material from the usual
|
|
614
|
+
293.15K. The temperature value can still be modified subsequently using
|
|
615
|
+
the cfg parameter "temp" as usual. To prevent this, use the
|
|
616
|
+
.lock_temperature() method instead. Call with value=None to clear any
|
|
617
|
+
previous effects of .lock_temperature() or .set_default_temperature().
|
|
618
|
+
"""
|
|
619
|
+
return self.__impl.set_default_temperature( value )
|
|
620
|
+
|
|
621
|
+
def get_temperature_setting( self ):
|
|
622
|
+
"""Returns the temperature setting resulting from calls to
|
|
623
|
+
.lock_temperature() or .set_default_temperature(). Returns a tuple of
|
|
624
|
+
two values: the temperature value in kelvin, and a boolean indicating
|
|
625
|
+
whether the value has been locked or is merely a changed
|
|
626
|
+
default. Returns (None,None) in the absence of such a setting.
|
|
627
|
+
"""
|
|
628
|
+
return self.__impl.get_temperature_setting()
|
|
629
|
+
|
|
630
|
+
@property
|
|
631
|
+
def state_of_matter( self ):
|
|
632
|
+
"""
|
|
633
|
+
Access the state of matter which will be one of "solid", "liquid",
|
|
634
|
+
or "gas". However, this is only available if explicitly set, otherwise
|
|
635
|
+
None is returned.
|
|
636
|
+
"""
|
|
637
|
+
return self.__impl.get_state_of_matter()
|
|
638
|
+
|
|
639
|
+
def get_labels( self ):
|
|
640
|
+
"""List of all labels registered so far."""
|
|
641
|
+
return self.__impl.get_labels()
|
|
642
|
+
|
|
643
|
+
def write( self, path, cfg_params = None ):
|
|
644
|
+
"""Produce NCMAT data and write it to the provided file path. If any
|
|
645
|
+
cfg_params are provided, they will be embedded in the NCMAT data using
|
|
646
|
+
the NCRYSTALMATCFG[..] syntax.
|
|
647
|
+
"""
|
|
648
|
+
return self.__impl.write( path = path,
|
|
649
|
+
cfg_params = cfg_params )
|
|
650
|
+
|
|
651
|
+
def register_as( self, virtual_filename, cfg_params = None ):
|
|
652
|
+
"""Produce NCMAT data and register it in memory with the provided
|
|
653
|
+
virtual file-name, using the registerInMemoryFileData(..) function from
|
|
654
|
+
the NCrystal.datasrc module. If any cfg_params are provided, they will
|
|
655
|
+
be embedded in the NCMAT data using the NCRYSTALMATCFG[..] syntax.
|
|
656
|
+
"""
|
|
657
|
+
return self.__impl.register_as( virtual_filename = virtual_filename,
|
|
658
|
+
cfg_params = cfg_params )
|
|
659
|
+
|
|
660
|
+
def load(self, cfg_params = None, *, force = False ):
|
|
661
|
+
"""Will create NCMAT and load it with the directLoad(..) function of the
|
|
662
|
+
NCrystal.core module. The cfg_params parameter can be used to apply cfg
|
|
663
|
+
parameters (e.g. cfg_params="temp=200K;dcutoff=0.1")., while force=True
|
|
664
|
+
will prevent the NCMATComposer from simply returning a previously loaded
|
|
665
|
+
material (usually one should just leave the default force=False value
|
|
666
|
+
untouched).
|
|
667
|
+
"""
|
|
668
|
+
return self.__impl.load( cfg_params = cfg_params, force = force )
|
|
669
|
+
|
|
670
|
+
def plot_xsect( self, cfg_params = None, **kwargs_plot_xsect ):
|
|
671
|
+
"""
|
|
672
|
+
Quick plot (with matplotlib) showing the cross sections produced by
|
|
673
|
+
current material, possibly after appending certain cfg_params. This is
|
|
674
|
+
using the plot_xsect function from the NCrystal.plot module, so refer to
|
|
675
|
+
that function for available arguments.
|
|
676
|
+
"""
|
|
677
|
+
return self.__impl.plot_xsect( self, cfg_params, kwargs_plot_xsect )
|
|
678
|
+
|
|
679
|
+
def inspect( self, cfg_params = None, **kwargs_plot_xsect ):
|
|
680
|
+
"""Similar to the plot_xsect(..) function, but will also print out
|
|
681
|
+
information (e.g. .dump()) about the Info, Scatter, and Absorption
|
|
682
|
+
objects.
|
|
683
|
+
"""
|
|
684
|
+
return self.__impl.inspect( self, cfg_params, kwargs_plot_xsect )
|
|
685
|
+
|
|
686
|
+
def get_chemical_composition( self, as_str = False ):
|
|
687
|
+
"""Chemical composition as list of [(elemiso,count),...] where elemiso
|
|
688
|
+
is a marker like "Al", "D", "B10", .... For crystals, the counts will
|
|
689
|
+
represent the number of elements/isotopes per unit cell. Returns None in
|
|
690
|
+
case of incomplete information.
|
|
691
|
+
|
|
692
|
+
If as_str = True, the result will instead be returned encoded in a
|
|
693
|
+
string (e.g. "H2O").
|
|
694
|
+
"""
|
|
695
|
+
return self.__impl.get_chemical_composition( as_str=as_str )
|
|
696
|
+
|
|
697
|
+
def create_ncmat( self, cfg_params = None, *,
|
|
698
|
+
meta_data = False,
|
|
699
|
+
verify_crystal_structure = True ):
|
|
700
|
+
"""Creates and returns NCMAT data based on the material settings
|
|
701
|
+
provided so far. Any cfg_params provided here will be embedded into the
|
|
702
|
+
NCMAT data itself, using the NCRYSTALMATCFG[..] syntax.
|
|
703
|
+
|
|
704
|
+
If meta_data=True, the return value will be a tuple whose first element
|
|
705
|
+
is the created NCMAT data, and whose second element is a dictionary with
|
|
706
|
+
a high-level meta-data concerning the material (like chemical
|
|
707
|
+
composition, spacegroup, etc.).
|
|
708
|
+
|
|
709
|
+
Unless verify_crystal_structure=False (not recommended!) any crystalline
|
|
710
|
+
material will have its structure verified by calling
|
|
711
|
+
.verify_crystal_structure(), possibly raising an exception in case of
|
|
712
|
+
issues found. Depending on the scenario, it might be possible to prevent
|
|
713
|
+
this by calling .refine_crystal_structure(), which will hopefully fix it
|
|
714
|
+
up before verification (but be vigilant and double-check that the
|
|
715
|
+
refinement did not simply hide some fundamental flaw of the input data).
|
|
716
|
+
"""
|
|
717
|
+
return self.__impl.create_ncmat( cfg_params = cfg_params,
|
|
718
|
+
meta_data = meta_data,
|
|
719
|
+
verify_crystal_structure = verify_crystal_structure )
|
|
720
|
+
|
|
721
|
+
|
|
722
|
+
def set_plotlabel( self, lbl ):
|
|
723
|
+
"""Sets the plotlabel (cf. .plotlabel)."""
|
|
724
|
+
return self.__impl.set_plotlabel(lbl)
|
|
725
|
+
|
|
726
|
+
@property
|
|
727
|
+
def plotlabel( self ):
|
|
728
|
+
"""An optional label for the material, which can be used for plotting
|
|
729
|
+
purposes in legends, etc.
|
|
730
|
+
"""
|
|
731
|
+
return self.__impl.plotlabel
|
|
732
|
+
|
|
733
|
+
def as_spglib_cell( self ):
|
|
734
|
+
"""For a crystalline material, return the unit cell definition in a
|
|
735
|
+
format suitable for usage in spglib calls."""
|
|
736
|
+
return self.__impl.as_spglib_cell()
|
|
737
|
+
|
|
738
|
+
def _unofficial_vdos2sab_ignore( self, *, order_low, order_high = None, mode = None ):
|
|
739
|
+
"""This expert-only method can be used to exclude certain phonon orders
|
|
740
|
+
from the scattering kernel during vdos2sab expansion. It is primarily
|
|
741
|
+
intended as a debugging aid for visualisation purposes, or for
|
|
742
|
+
developers intending to develop coherent single-phonon physics.
|
|
743
|
+
|
|
744
|
+
Be aware that, for now, trying to use the Info.DI_VDOS[Debye].loadKernel
|
|
745
|
+
or .plot_knl(), will NOT reflect this hack!
|
|
746
|
+
"""
|
|
747
|
+
return self.__impl._unofficial_vdos2sab_ignore( order_low = order_low,
|
|
748
|
+
order_high = order_high,
|
|
749
|
+
mode = mode )
|
|
750
|
+
|
|
751
|
+
def _get_impl_obj( self ):
|
|
752
|
+
return self.__impl
|
|
753
|
+
|
|
754
|
+
def formatVectorForNCMAT(name,values,indent=' '):
|
|
755
|
+
"""Utility function for help in python scripts composing .ncmat files,
|
|
756
|
+
transforming an array of of values into a properly formatted text string,
|
|
757
|
+
with word-wrapping, usage of <val>r<n> syntax, etc.
|
|
758
|
+
"""
|
|
759
|
+
from ._ncmatimpl import formatVectorForNCMAT as _
|
|
760
|
+
return _( name = name,
|
|
761
|
+
values = values,
|
|
762
|
+
indent = indent )
|
|
763
|
+
|
|
764
|
+
def _rawParseNCMAT(text_data_name,*,asJSONStr=False):
|
|
765
|
+
"""Parses NCMAT content and returns as Python data structure (a dictionary). The
|
|
766
|
+
format of this data structure should be mostly self-evident by
|
|
767
|
+
inspection, and is not guaranteed to stay the same across NCrystal
|
|
768
|
+
versions. If asJSONStr=true, the data structure will be returned as a
|
|
769
|
+
JSON-encoded string, instead of a Python dictionary.
|
|
770
|
+
|
|
771
|
+
WARNING: This function is considered experimental and is currently NOT
|
|
772
|
+
feature complete. It only returns data from a few select NCMAT sections."""
|
|
773
|
+
from ._chooks import _get_raw_cfcts
|
|
774
|
+
_js = _get_raw_cfcts()['nc_ncmat2json'](text_data_name if not hasattr(text_data_name,'rawData') else text_data_name.rawData )
|
|
775
|
+
if asJSONStr:
|
|
776
|
+
return _js
|
|
777
|
+
import json
|
|
778
|
+
return json.loads(_js)
|