34#include "../base/base_uses.f90"
39 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'cell_opt_utils'
45 mask_a,
mask_all,
mask_b,
mask_c,
mask_x,
mask_xy,
mask_xz,
mask_y,
mask_yz,
mask_z, &
66 REAL(kind=
dp),
INTENT(OUT) :: pres_ext
67 REAL(kind=
dp),
DIMENSION(3, 3),
INTENT(OUT) :: mtrx
68 REAL(kind=
dp),
DIMENSION(3, 3),
INTENT(IN) :: input_to_opt
70 REAL(kind=
dp),
PARAMETER :: eps_aniso_press = 1.0e-5_dp
74 REAL(kind=
dp),
DIMENSION(3, 3) :: pres_ext_tens
75 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pvals
79 pres_ext_tens = 0.0_dp
82 check = (
SIZE(pvals) == 1) .OR. (
SIZE(pvals) == 9)
84 cpabort(
"EXTERNAL_PRESSURE can have 1 or 9 components only!")
87 IF (
SIZE(pvals) == 9)
THEN
92 pres_ext_tens(j, i) = pvals(ind)
96 pres_ext_tens = matmul(input_to_opt, &
97 matmul(pres_ext_tens, transpose(input_to_opt)))
99 pres_ext = pres_ext + pres_ext_tens(i, i)
101 pres_ext = pres_ext/3.0_dp
103 pres_ext_tens(i, i) = pres_ext_tens(i, i) - pres_ext
109 IF (any(abs(pres_ext_tens) > eps_aniso_press))
THEN
110 mtrx = cell%deth*matmul(cell%h_inv, matmul(pres_ext_tens, transpose(cell%h_inv)))
123 CHARACTER(LEN=*),
DIMENSION(:),
INTENT(IN) :: constraint_tokens
125 LOGICAL,
INTENT(IN) :: explicit
126 INTEGER,
INTENT(OUT) :: mask
128 CHARACTER(LEN=default_string_length) :: reject_reason, token
129 INTEGER :: axis_index, nonperiodic_axis, overlap, &
130 required_mask, tok_index, tok_mask
134 IF (
SIZE(constraint_tokens) == 0 .OR. &
135 (
SIZE(constraint_tokens) == 1 .AND. len_trim(constraint_tokens(1)) == 0))
THEN
136 CALL cp_abort(__location__, &
137 "CELL_OPT CONSTRAINT requires a value.")
141 DO tok_index = 1,
SIZE(constraint_tokens)
142 token = adjustl(constraint_tokens(tok_index))
144 IF (token ==
"NONE")
THEN
147 IF (tok_index <
SIZE(constraint_tokens) .OR. mask /= 0)
THEN
148 CALL cp_abort(__location__, &
149 "CELL_OPT CONSTRAINT NONE cannot be combined "// &
150 "with other tokens.")
155 CALL parse_token(token, accepted, tok_mask, reject_reason)
156 IF (.NOT. accepted)
THEN
157 CALL cp_abort(__location__, trim(reject_reason))
159 overlap = iand(tok_mask, mask)
160 IF (overlap == tok_mask)
THEN
161 CALL cp_warn(__location__, &
162 "Redundant CELL_OPT CONSTRAINT token: "//trim(token)// &
163 " (already constrained: "// &
165 ELSE IF (overlap /= 0)
THEN
166 CALL cp_warn(__location__, &
167 "CELL_OPT CONSTRAINT token "//trim(token)//
" partially overlaps: "// &
168 "already constrained "// &
173 mask = ior(mask, tok_mask)
178 IF (count(cell%perd /= 0) == 2)
THEN
181 IF (cell%perd(axis_index) == 0) nonperiodic_axis = axis_index
184 SELECT CASE (nonperiodic_axis)
192 IF (.NOT. explicit .AND. mask == 0)
THEN
194 CALL cp_warn(__location__, &
195 "2D CELL_OPT: constraining non-periodic cell direction.")
196 ELSE IF (iand(mask, required_mask) /= required_mask)
THEN
197 CALL cp_abort(__location__, &
198 "2D CELL_OPT needs constrained non-periodic cell direction.")
210 INTEGER,
INTENT(IN) :: mask
211 CHARACTER(LEN=default_string_length) :: label
231 IF (iand(mask,
comp_ax) /= 0) label = trim(label)//
" AX"
232 IF (iand(mask,
comp_bx) /= 0) label = trim(label)//
" BX"
233 IF (iand(mask,
comp_by) /= 0) label = trim(label)//
" BY"
234 IF (iand(mask,
comp_cx) /= 0) label = trim(label)//
" CX"
235 IF (iand(mask,
comp_cy) /= 0) label = trim(label)//
" CY"
236 IF (iand(mask,
comp_cz) /= 0) label = trim(label)//
" CZ"
237 IF (iand(mask,
gfix_alpha) /= 0) label = trim(label)//
" ALPHA"
238 IF (iand(mask,
gfix_beta) /= 0) label = trim(label)//
" BETA"
239 IF (iand(mask,
gfix_gamma) /= 0) label = trim(label)//
" GAMMA"
240 label = adjustl(label)
258 INTEGER,
INTENT(IN) :: symmetry_id
259 INTEGER,
INTENT(OUT) :: mask
260 REAL(kind=
dp),
DIMENSION(n_slot, n_slot), &
262 INTEGER,
INTENT(OUT) :: n_lin_rows
263 INTEGER,
DIMENSION(2, n_geom),
INTENT(OUT) :: eq_pair
264 INTEGER,
INTENT(OUT) :: n_eq_rows
266 REAL(kind=
dp),
PARAMETER :: half_sqrt3 = 0.5_dp*
sqrt3
274 SELECT CASE (symmetry_id)
304 lin_w(
slot_ax, 2) = -half_sqrt3
311 lin_w(
slot_ax, 2) = -half_sqrt3
328 cpabort(
"Unknown cell symmetry_id")
346 TYPE(
spgr_type),
INTENT(IN),
POINTER :: spgr
348 INTEGER :: symmetry_id
350 REAL(kind=
dp),
PARAMETER :: ang_120 = 2.0_dp*
pi/3.0_dp, ang_60 =
pi/3.0_dp, &
351 ang_90 = 0.5_dp*
pi, eq_angle_tol = 1.0e-6_dp, rel_len_tol = 1.0e-6_dp, &
352 special_ang_tol = 1.0e-5_dp
354 INTEGER :: ir, n90, nop
355 REAL(kind=
dp) :: ang(3), gsym(3, 3), len_tol, lens(3), &
356 metric(3, 3), rot(3, 3)
359 nop = spgr%n_operations_subset
362 metric = matmul(transpose(cell%hmat), cell%hmat)
367 rot = real(spgr%rotations_subset(:, :, ir),
dp)
368 gsym = gsym + matmul(rot, matmul(metric, transpose(rot)))
370 gsym = gsym/real(nop,
dp)
372 lens = [sqrt(gsym(1, 1)), sqrt(gsym(2, 2)), sqrt(gsym(3, 3))]
374 len_tol = rel_len_tol*maxval(lens)
375 ang(1) = acos(max(-1.0_dp, min(1.0_dp, gsym(2, 3)/(lens(2)*lens(3)))))
376 ang(2) = acos(max(-1.0_dp, min(1.0_dp, gsym(1, 3)/(lens(1)*lens(3)))))
377 ang(3) = acos(max(-1.0_dp, min(1.0_dp, gsym(1, 2)/(lens(1)*lens(2)))))
378 n90 = count(abs(ang - ang_90) < special_ang_tol)
381 IF (abs(lens(1) - lens(2)) < len_tol .AND. abs(lens(2) - lens(3)) < len_tol)
THEN
383 ELSE IF (abs(lens(1) - lens(2)) < len_tol)
THEN
385 ELSE IF (abs(lens(1) - lens(3)) < len_tol)
THEN
387 ELSE IF (abs(lens(2) - lens(3)) < len_tol)
THEN
392 ELSE IF (n90 == 2)
THEN
393 IF (abs(ang(2) - ang_90) >= special_ang_tol)
THEN
396 ELSE IF (abs(ang(3) - ang_90) >= special_ang_tol .AND. &
397 abs(lens(1) - lens(2)) < len_tol)
THEN
398 IF (abs(ang(3) - ang_120) < special_ang_tol)
THEN
400 ELSE IF (abs(ang(3) - ang_60) < special_ang_tol)
THEN
407 IF (abs(ang(1) - ang(2)) < eq_angle_tol .AND. abs(ang(2) - ang(3)) < eq_angle_tol .AND. &
408 abs(ang(1) - ang_90) >= special_ang_tol .AND. &
409 abs(lens(1) - lens(2)) < len_tol .AND. abs(lens(2) - lens(3)) < len_tol)
THEN
426 PURE SUBROUTINE parse_token(token, accepted, token_mask, reject_reason)
427 CHARACTER(LEN=*),
INTENT(IN) :: token
428 LOGICAL,
INTENT(OUT) :: accepted
429 INTEGER,
INTENT(OUT) :: token_mask
430 CHARACTER(LEN=default_string_length),
INTENT(OUT) :: reject_reason
468 CASE (
"AY",
"AZ",
"BZ")
470 reject_reason =
"CELL_OPT CONSTRAINT token "//trim(token)//
" is always zero in "// &
471 "the cell convention (a lies along x, b lies in the xy plane) "// &
472 "and cannot be constrained."
475 reject_reason =
"Unknown CELL_OPT CONSTRAINT token: "//trim(token)// &
476 ". Accepted tokens: NONE, the directions X, Y, Z,"// &
477 " XY, XZ, YZ, the vectors A, B, C, the components"// &
478 " AX, BX, BY, CX, CY, CZ, and the angles ALPHA, BETA, GAMMA."
492 SUBROUTINE get_dg_dh(gradient, av_ptens, pres_ext, cell, mtrx, pres_int)
494 REAL(kind=
dp),
DIMENSION(n_slot),
INTENT(OUT) :: gradient
495 REAL(kind=
dp),
DIMENSION(3, 3),
INTENT(IN) :: av_ptens
496 REAL(kind=
dp),
INTENT(IN) :: pres_ext
498 REAL(kind=
dp),
DIMENSION(3, 3),
INTENT(IN) :: mtrx
499 REAL(kind=
dp),
INTENT(OUT) :: pres_int
502 REAL(kind=
dp),
DIMENSION(3, 3) :: correction, pten_hinv_old, ptens
511 pres_int = pres_int + ptens(i, i)
513 pres_int = pres_int/3.0_dp
515 ptens(1, 1) = av_ptens(1, 1) - pres_ext
516 ptens(2, 2) = av_ptens(2, 2) - pres_ext
517 ptens(3, 3) = av_ptens(3, 3) - pres_ext
519 pten_hinv_old = cell%deth*matmul(cell%h_inv, ptens)
520 correction = matmul(mtrx, cell%hmat)
522 gradient(
slot_ax) = pten_hinv_old(1, 1) - correction(1, 1)
523 gradient(
slot_bx) = pten_hinv_old(2, 1) - correction(2, 1)
524 gradient(
slot_by) = pten_hinv_old(2, 2) - correction(2, 2)
525 gradient(
slot_cx) = pten_hinv_old(3, 1) - correction(3, 1)
526 gradient(
slot_cy) = pten_hinv_old(3, 2) - correction(3, 2)
527 gradient(
slot_cz) = pten_hinv_old(3, 3) - correction(3, 3)
Reduced-coordinate parameterization of cell constraints for CELL_OPT.
integer, parameter, public comp_ax
integer, parameter, public comp_cx
integer, parameter, public geom_gamma
integer, parameter, public geom_beta
integer, parameter, public gfix_gamma
integer, parameter, public slot_cx
integer, parameter, public mask_a
integer, parameter, public slot_by
integer, parameter, public n_geom
integer, parameter, public n_slot
integer, parameter, public mask_yz
real(kind=dp), parameter, public min_cell_length
integer, parameter, public slot_ax
integer, parameter, public comp_by
integer, parameter, public mask_y
integer, parameter, public geom_a
integer, parameter, public mask_x
integer, parameter, public slot_cz
integer, parameter, public gfix_beta
integer, parameter, public mask_xy
integer, parameter, public mask_c
integer, parameter, public slot_bx
integer, parameter, public mask_b
integer, parameter, public mask_all
integer, parameter, public mask_xz
integer, parameter, public comp_cz
integer, parameter, public comp_bx
integer, parameter, public slot_cy
integer, parameter, public comp_cy
integer, parameter, public mask_z
integer, parameter, public geom_c
integer, parameter, public geom_alpha
integer, parameter, public gfix_alpha
integer, parameter, public geom_b
Parse CELL_OPT constraints, build symmetry constraint rows, and compute the cell enthalpy gradient.
subroutine, public parse_cell_constraint(constraint_tokens, cell, explicit, mask)
Parses the tokens of the CONSTRAINT keyword into a cell component mask.
subroutine, public read_external_press_tensor(geo_section, cell, pres_ext, mtrx, input_to_opt)
Reads the external pressure tensor.
subroutine, public symmetry_constraint_rows(symmetry_id, mask, lin_w, n_lin_rows, eq_pair, n_eq_rows)
Translate a crystal system into cell constraint rows.
integer function, public spgr_point_group_symmetry_id(spgr, cell)
Identify the canonical crystal system preserved by a space group's point group.
pure subroutine, public parse_token(token, accepted, token_mask, reject_reason)
Classify one CONSTRAINT token without aborting (decision half of the parser).
subroutine, public get_dg_dh(gradient, av_ptens, pres_ext, cell, mtrx, pres_int)
Computes the derivatives for the cell.
pure character(len=default_string_length) function, public cell_opt_constraint_label(mask)
Returns the label of the cell constraint mask.
Handles all functions related to the CELL.
integer, parameter, public cell_sym_monoclinic
integer, parameter, public cell_sym_triclinic
integer, parameter, public cell_sym_tetragonal_ab
integer, parameter, public cell_sym_rhombohedral
integer, parameter, public cell_sym_tetragonal_ac
integer, parameter, public cell_sym_hexagonal_gamma_60
integer, parameter, public cell_sym_orthorhombic
integer, parameter, public cell_sym_none
integer, parameter, public cell_sym_hexagonal_gamma_120
integer, parameter, public cell_sym_monoclinic_gamma_ab
integer, parameter, public cell_sym_cubic
integer, parameter, public cell_sym_tetragonal_bc
Defines the basic variable types.
integer, parameter, public dp
integer, parameter, public default_string_length
Definition of mathematical constants and functions.
real(kind=dp), parameter, public pi
real(kind=dp), parameter, public sqrt3
Space Group Symmetry Type Module (version 1.0, Ferbruary 12, 2021).
Utilities for string manipulations.
elemental subroutine, public uppercase(string)
Convert all lower case characters in a string to upper case.
Type defining parameters related to the simulation cell.