9090# representing fractions (between 0 and 1) of the lattice vectors `latvecs`.
9191# All symmetry information is automatically inferred.
9292function Crystal (latvecs, positions; types:: Union{Nothing, Vector{String}} = nothing , symprec= 1e-5 )
93- print_crystal_warnings (latvecs, positions)
93+ if length (positions) >= 100
94+ @warn """ Very large crystal cells are not recommended. To model chemical inhomogeneity:
95+ 1. Create the `Crystal` with an idealized chemical cell.
96+ 2. Create the `System` with large volume dimensions, `dims`.
97+ 3. Use `to_inhomogeneous` and related functions to set inhomogeneities."""
98+ end
9499 latvecs = convert (Mat3, latvecs)
95100 positions = [convert (Vec3, p) for p in positions]
96101 if isnothing (types)
@@ -106,21 +111,23 @@ function Crystal(latvecs, positions, symbol::Union{Int, String}; types::Union{No
106111 setting= nothing , choice:: Union{Nothing, String} = nothing , symprec= 1e-5 )
107112 if ! isnothing (setting)
108113 if symbol isa Integer
109- @warn """ `setting` argument is deprecated! Omit to get the ITA standard setting.
110- Alternatively, use `choice` instead."""
114+ @warn " `setting` argument is deprecated! Omit to get the ITA standard setting or use `choice`."
111115 else
112116 @warn " `setting` argument is deprecated! Use `choice` instead."
113117 end
114118 choice = setting
115119 end
116120
117- print_crystal_warnings (latvecs, positions)
118121 latvecs = Mat3 (latvecs)
119122 positions = Vec3 .(positions)
120123 if isnothing (types)
121124 types = fill (" " , length (positions))
122125 end
123126
127+ # Enforce right-handedness convention for aesthetics
128+ det (latvecs) < 0 && error (" Lattice vectors are not right-handed." )
129+
130+ # Will report an informative error if latvecs not consistent with symbol
124131 sgt = unique_spacegroup_type (symbol, latvecs; choice)
125132 sg = Spacegroup (Int (sgt. hall_number))
126133 return crystal_from_spacegroup (latvecs, positions, types, sg; symprec)
@@ -148,17 +155,6 @@ function spg_get_dataset_scaled(cell, symprec)
148155end
149156
150157
151- function print_crystal_warnings (latvecs, positions)
152- det (latvecs) < 0 && @warn " Lattice vectors are not right-handed."
153- if length (positions) >= 100
154- @info """ This a very large crystallographic cell, which Sunny does not handle well. If
155- the intention is to model chemical inhomogeneity, the recommended steps are:
156- (1) Create a `Crystal` with idealized chemical cell. (2) Create a `System`
157- with many cells, as set by the `dims` parameter. (3) Use `to_inhomogeneous`
158- and related functions to introduce model inhomogeneities."""
159- end
160- end
161-
162158"""
163159 natoms(cryst::Crystal)
164160
@@ -302,29 +298,47 @@ function conventionalize_setting(latvecs::Mat3, setting::SymOp, sgnum::Int)
302298end
303299
304300function crystal_from_inferred_symmetry (latvecs:: Mat3 , positions:: Vector{Vec3} , types:: Vector{String} ; symprec, suppress_warnings= false )
305- # Print a warning if non-conventional lattice vectors are detected.
306- try cell_type (latvecs) catch e @warn e. msg end
307-
308301 validate_positions (positions; symprec)
309302
310- cell = Spglib. Cell (latvecs, positions, types)
311- d = spg_get_dataset_scaled (cell, symprec)
303+ d = spg_get_dataset_scaled (Spglib. Cell (latvecs, positions, types), symprec)
312304 classes = d. crystallographic_orbits
313305 # classes = d.equivalent_atoms
314306 symops = SymOp .(d. rotations, d. translations)
315307 label = spacegroup_label (Int (d. hall_number))
316308 sgnum = Int (d. spacegroup_number)
309+ cell_std = cell_type (standard_setting[sgnum])
317310 setting = mapping_to_standard_setting_from_spglib_dataset (d)
318311 setting = conventionalize_setting (latvecs, setting, sgnum)
319312
320- # Spglib-inferred symops are unreliable for large cells. Empty the list to
321- # prevent faulty symmetry analysis.
322- if length (positions) > d. n_std_atoms
323- if ! suppress_warnings
324- types_str = allunique (types) ? " " : " Alternatively, break site symmetry with `types=[...]`."
325- @warn " This cell is non-standard and missing symmetry information. Consider `standardize`.$types_str "
313+ # Spglib-inferred symops are unreliable for large cells. Empty the list
314+ # to prevent faulty symmetry analysis.
315+ volume_ratio = length (positions) // d. n_std_atoms
316+ volume_ratio > 1 && empty! (symops)
317+ volume_ratio_str = number_to_math_string (volume_ratio)
318+
319+ if ! suppress_warnings
320+ if volume_ratio > 1
321+ volume_ratio_str = number_to_math_string (volume_ratio)
322+ types_str = allunique (types) ? " " : " or distinct `types=[...]`"
323+ @error " Symmetry analysis disabled! Cell is $volume_ratio_str times too large. Fix with `standardize`$types_str ."
324+ elseif volume_ratio < 1
325+ @info " Cell is $volume_ratio_str the standard size for spacegroup $sgnum . Consider `standardize`."
326+ elseif cell_std in (tetragonal, hexagonal, cubic) && setting. R ≉ I
327+ # For a tetragonal, hexagonal, trigonal or cubic space group, the
328+ # provided cell should already be Spglib-idealized.
329+ @info " Nonstandard $cell_std cell for spacegroup $sgnum . Consider `standardize`."
330+ elseif ! (cell_type (latvecs) in all_compatible_cells (cell_std))
331+ # For triclinic, monoclinic, and orthorhombic spacegroups, check
332+ # that the provided cell is symmetry-consistent (not necessarily
333+ # Spglib-idealized). For orthorhombic, arbitrary axis ordering is
334+ # acceptable. For monoclinic, arbitrary β magnitude is acceptable,
335+ # whereas Spglib finds a cell with 90 < β < 120. For triclinic,
336+ # Spglib's idealization algorithm is even more complex, involving
337+ # Niggli reduction.
338+ @info " Nonstandard $cell_std cell for spacegroup $sgnum . Consider `standardize`."
339+ elseif det (latvecs) < 0
340+ @info " Lattice vectors are not right-handed. Consider `standardize`."
326341 end
327- symops = SymOp[]
328342 end
329343
330344 sg = Spacegroup (symops, label, sgnum, setting)
511525
512526# Indices of atoms that wrap into unique positions within the primitive cell.
513527# The choice is ambiguous because the un-wrapped positions are not restricted to
514- # `latvecs * primitive_cell()`.
528+ # the parallelpiped spanned by `latvecs * primitive_cell()`.
515529function primitive_atoms_arbitrary (cryst:: Crystal )
516530 P = primitive_cell (cryst)
517531 P ≈ I && return collect (1 : natoms (cryst))
0 commit comments