Example #1
0
    if sx is not None and sy is not None:
        sz = ( 1e24*mass/(density*mol) )/(sx*sy)
        a.set_cell([sx,sy,sz], scale_atoms=True)
    else:
        a0 = ( 1e24*mass/(density*mol) )**(1./3)
        a.set_cell([a0,a0,a0], scale_atoms=True)
    a.set_initial_charges([0]*len(a))

    return a

###

# For coordination counting
cutoff = 1.85

els = parameter('stoichiometry')
densities  = parameter('densities')

T1 = parameter('T1', 5000*kB)
T2 = parameter('T2', 300*kB)
dt1 = parameter('dt1', 0.1*fs)
dt2 = parameter('dt2', 0.1*fs)
tau1 = parameter('tau1', 5000*fs)
tau2 = parameter('tau2', 500*fs)
dtdump = parameter('dtdump', 100*fs)
teq = parameter('teq', 50e3*fs)
tqu = parameter('tqu', 20e3*fs)

###

quick_calc = parameter('quick_calc')
Example #2
0
FITTED_CRACK_TIP = 'Ag'

###

logger = screen

###

cryst = params.cryst.copy()
cryst.set_pbc(True)
ncryst = len(cryst)

# Double check elastic constants. We're just assuming this is really a periodic
# system. (True if it comes out of the cluster routines.)

compute_elastic_constants = parameter('compute_elastic_constants', False)
elastic_fmax = parameter('elastic_fmax', 0.05)
elastic_symmetry = parameter('elastic_symmetry', 'triclinic')
fmax = parameter('fmax', 0.01)

if compute_elastic_constants:
    cryst.set_calculator(params.calc)
    log_file = open('elastic_constants.log', 'w')
    C, C_err = fit_elastic_constants(cryst, verbose=False,
                                     symmetry=elastic_symmetry,
                                     optimizer=ase.optimize.FIRE,
                                     logfile=log_file,
                                     fmax=elastic_fmax)
    log_file.close()
    print('Measured elastic constants (in GPa):')
    print(np.round(C*10/GPa)/10)
Example #3
0
ACTUAL_CRACK_TIP = 'Au'
FITTED_CRACK_TIP = 'Ag'

###

logger = screen

###

a, cryst, crk, k1g, tip_x, tip_y, bond1, bond2, boundary_mask, \
    boundary_mask_bulk, tip_mask = setup_crack(logger=logger)
ase.io.write('notch.xyz', a, format='extxyz')

# Get general parameters

basename = parameter('basename', 'energy_barrier')
calc = parameter('calc')
fmax = parameter('fmax', 0.01)

# Get parameter used for fitting crack tip position

optimize_tip_position = parameter('optimize_tip_position', False)
residual_func = parameter('residual_func', crack.displacement_residual)
_residual_func = residual_func
tip_tol = parameter('tip_tol', 1e-4)
tip_mixing_alpha = parameter('tip_mixing_alpha', 1.0)
write_trajectory_during_optimization = parameter('write_trajectory_during_optimization', False)

if optimize_tip_position:
    tip_x = (a.positions[bond1, 0] + a.positions[bond2, 0])/2
    tip_y = (a.positions[bond1, 1] + a.positions[bond2, 1])/2
Example #4
0
def setup_crack(logger=screen):
    calc = parameter('calc')

    cryst = parameter('cryst').copy()
    cryst.set_pbc(True)

    # Double check elastic constants. We're just assuming this is really a periodic
    # system. (True if it comes out of the cluster routines.)

    compute_elastic_constants = parameter('compute_elastic_constants', False)
    elastic_fmax = parameter('elastic_fmax', 0.01)
    elastic_symmetry = parameter('elastic_symmetry', 'triclinic')
    elastic_optimizer = parameter('elastic_optimizer', ase.optimize.FIRE)

    if compute_elastic_constants:
        cryst.set_calculator(calc)
        log_file = open('elastic_constants.log', 'w')
        C, C_err = fit_elastic_constants(cryst,
                                         verbose=False,
                                         symmetry=elastic_symmetry,
                                         optimizer=elastic_optimizer,
                                         logfile=log_file,
                                         fmax=elastic_fmax)
        log_file.close()
        logger.pr('Measured elastic constants (in GPa):')
        logger.pr(np.round(C * 10 / GPa) / 10)

        crk = crack.CubicCrystalCrack(parameter('crack_surface'),
                                      parameter('crack_front'),
                                      Crot=C / GPa)
    else:
        if has_parameter('C'):
            crk = crack.CubicCrystalCrack(parameter('crack_surface'),
                                          parameter('crack_front'),
                                          C=parameter('C'))
        else:
            crk = crack.CubicCrystalCrack(parameter('crack_surface'),
                                          parameter('crack_front'),
                                          parameter('C11'), parameter('C12'),
                                          parameter('C44'))

    logger.pr('Elastic constants used for boundary condition (in GPa):')
    logger.pr(np.round(crk.C * 10) / 10)

    # Get Griffith's k1.
    k1g = crk.k1g(parameter('surface_energy'))
    logger.pr('Griffith k1 = %f' % k1g)

    # Apply initial strain field.
    tip_x = parameter('tip_x', cryst.cell.diagonal()[0] / 2)
    tip_y = parameter('tip_y', cryst.cell.diagonal()[1] / 2)

    bondlength = parameter('bondlength', 2.7)
    bulk_nn = parameter('bulk_nn', 4)

    a = cryst.copy()
    a.set_pbc([False, False, True])

    hydrogenate_flag = parameter('hydrogenate', False)
    hydrogenate_crack_face_flag = parameter('hydrogenate_crack_face', True)

    if hydrogenate_flag and not hydrogenate_crack_face_flag:
        # Get surface atoms of cluster with crack
        a = hydrogenate(cryst, bondlength, parameter('XH_bondlength'), b=a)
        g = a.get_array('groups')
        g[a.numbers == 1] = -1
        a.set_array('groups', g)
        cryst = a.copy()

    k1 = parameter('k1')
    try:
        k1 = k1[0]
    except:
        pass
    ux, uy = crk.displacements(cryst.positions[:, 0], cryst.positions[:, 1],
                               tip_x, tip_y, k1 * k1g)
    a.positions[:len(cryst), 0] += ux
    a.positions[:len(cryst), 1] += uy

    # Center notched configuration in simulation cell and ensure enough vacuum.
    oldr = a[0].position.copy()
    vacuum = parameter('vacuum')
    a.center(vacuum=vacuum, axis=0)
    a.center(vacuum=vacuum, axis=1)
    tip_x += a[0].x - oldr[0]
    tip_y += a[0].y - oldr[1]

    # Choose which bond to break.
    bond1, bond2 = \
        parameter('bond', crack.find_tip_coordination(a, bondlength=bondlength, bulk_nn=bulk_nn))

    if parameter('center_crack_tip_on_bond', False):
        tip_x, tip_y, dummy = (a.positions[bond1] + a.positions[bond2]) / 2

    # Hydrogenate?
    coord = np.bincount(neighbour_list('i', a, bondlength), minlength=len(a))
    a.set_array('coord', coord)

    if parameter('optimize_full_crack_face', False):
        g = a.get_array('groups')
        gcryst = cryst.get_array('groups')
        coord = a.get_array('coord')
        g[coord != 4] = -1
        gcryst[coord != 4] = -1
        a.set_array('groups', g)
        cryst.set_array('groups', gcryst)

    if hydrogenate_flag and hydrogenate_crack_face_flag:
        # Get surface atoms of cluster with crack
        exclude = np.logical_and(a.get_array('groups') == 1, coord != 4)
        a.set_array('exclude', exclude)
        a = hydrogenate(cryst,
                        bondlength,
                        parameter('XH_bondlength'),
                        b=a,
                        exclude=exclude)
        g = a.get_array('groups')
        g[a.numbers == 1] = -1
        a.set_array('groups', g)
        basename = parameter('basename', 'energy_barrier')
        ase.io.write('{0}_hydrogenated.xyz'.format(basename),
                     a,
                     format='extxyz')

    # Move reference crystal by same amount
    cryst.set_cell(a.cell)
    cryst.set_pbc([False, False, True])
    cryst.translate(a[0].position - oldr)

    # Groups mark the fixed region and the region use for fitting the crack tip.
    g = a.get_array('groups')
    gcryst = cryst.get_array('groups')

    logger.pr('Opening bond {0}--{1}, initial bond length {2}'.format(
        bond1, bond2, a.get_distance(bond1, bond2, mic=True)))

    # centre vertically on the opening bond
    if parameter('center_cell_on_bond', True):
        a.translate([
            0., a.cell[1, 1] / 2.0 -
            (a.positions[bond1, 1] + a.positions[bond2, 1]) / 2.0, 0.
        ])

    a.info['bond1'] = bond1
    a.info['bond2'] = bond2

    return a, cryst, crk, k1g, tip_x, tip_y, bond1, bond2, g == 0, gcryst == 0, g == 1
Example #5
0
Optimizer = ase.optimize.FIRE
#Optimizer = ase.optimize.precon.LBFGS

# Atom types used for outputting the crack tip position.
ACTUAL_CRACK_TIP = 'Au'
FITTED_CRACK_TIP = 'Ag'

###

logger = screen

###

# Get general parameters

residual_func = parameter('residual_func', crack.displacement_residual)
_residual_func = residual_func

basename = parameter('basename', 'neb')
calc = parameter('calc')
fmax_neb = parameter('fmax_neb', 0.1)
maxsteps_neb = parameter('maxsteps_neb', 100)
Nimages = parameter('Nimages', 7)
k_neb = parameter('k_neb', 1.0)

a, cryst, crk, k1g, tip_x, tip_y, bond1, bond2, boundary_mask, \
    boundary_mask_bulk, tip_mask = setup_crack(logger=logger)

# Deformation gradient residual needs full Atoms object and therefore
# special treatment here.
if _residual_func == crack.deformation_gradient_residual:
Example #6
0
from ase.optimize.precon import PreconLBFGS

from matscipy import parameter
from matscipy.elasticity import fit_elastic_constants
from matscipy.fracture_mechanics.crack import CubicCrystalCrack, SinclairCrack

from scipy.optimize import fsolve, fminbound
from scipy.optimize.nonlin import NoConvergence

import sys

sys.path.insert(0, '.')

import params

calc = parameter('calc')
fmax_flex = parameter('fmax_flex', 1e-2)
fmax_arc = parameter('fmax_arc', 1e-3)
max_opt_steps = parameter('max_opt_steps', 100)
max_arc_steps = parameter('max_arc_steps', 10)
vacuum = parameter('vacuum', 10.0)
flexible = parameter('flexible', True)
continuation = parameter('continuation', False)
ds = parameter('ds', 1e-2)
nsteps = parameter('nsteps', 10)
a0 = parameter('a0')  # lattice constant
k0 = parameter('k0', 1.0)
extended_far_field = parameter('extended_far_field', False)
alpha0 = parameter('alpha0', 0.0)  # initial guess for crack position
dump = parameter('dump', False)
precon = parameter('precon', False)
Example #7
0
import ase.io
from ase.units import GPa

from matscipy import parameter
from matscipy.elasticity import fit_elastic_constants
from matscipy.fracture_mechanics.crack import CubicCrystalCrack, SinclairCrack

args = sys.argv[1:]
if not args:
    args = ['.']  # current directory only

sys.path.insert(0, args[0])
import params

calc = parameter('calc')
fmax = parameter('fmax', 1e-3)
vacuum = parameter('vacuum', 10.0)
flexible = parameter('flexible', True)
extended_far_field = parameter('extended_far_field', False)

k0 = parameter('k0', 1.0)
alpha0 = parameter('alpha0', 0.0)  # initial guess for crack position

colors = parameter('colors',
                   ["#1B9E77", "#D95F02", "#7570B3", "#E7298A", "#66A61E"])

colors = itertools.cycle(colors)

# compute elastic constants
cryst = params.cryst.copy()
Example #8
0
###

Optimizer = ase.optimize.FIRE

# Atom types used for outputting the crack tip position.
ACTUAL_CRACK_TIP = 'Au'
FITTED_CRACK_TIP = 'Ag'

###

logger = screen

###

calc = parameter('calc')

cryst = params.cryst.copy()
cryst.set_pbc(True)

# Double check elastic constants. We're just assuming this is really a periodic
# system. (True if it comes out of the cluster routines.)

compute_elastic_constants = parameter('compute_elastic_constants', False)
elastic_fmax = parameter('elastic_fmax', 0.01)
elastic_symmetry = parameter('elastic_symmetry', 'triclinic')
fmax = parameter('fmax', 0.01)

if compute_elastic_constants:
    cryst.set_calculator(calc)
    log_file = open('elastic_constants.log', 'w')
Example #9
0
    if sx is not None and sy is not None:
        sz = ( 1e24*mass/(density*mol) )/(sx*sy)
        a.set_cell([sx,sy,sz], scale_atoms=True)
    else:
        a0 = ( 1e24*mass/(density*mol) )**(1./3)
        a.set_cell([a0,a0,a0], scale_atoms=True)
    a.set_initial_charges([0]*len(a))

    return a

###

# For coordination counting
cutoff = 1.85

els = parameter('stoichiometry')
densities  = parameter('densities')

T1 = parameter('T1', 5000*kB)
T2 = parameter('T2', 300*kB)
dt1 = parameter('dt1', 0.1*fs)
dt2 = parameter('dt2', 0.1*fs)
tau1 = parameter('tau1', 5000*fs)
tau2 = parameter('tau2', 500*fs)
dtdump = parameter('dtdump', 100*fs)
teq = parameter('teq', 50e3*fs)
tqu = parameter('tqu', 20e3*fs)
nsteps_relax = parameter('nsteps_relax', 10000)

###
Example #10
0
ACTUAL_CRACK_TIP = 'Au'
FITTED_CRACK_TIP = 'Ag'

###

logger = screen

###

a, cryst, crk, k1g, tip_x, tip_y, bond1, bond2, boundary_mask, \
    boundary_mask_bulk, tip_mask = setup_crack(logger=logger)
ase.io.write('notch.xyz', a, format='extxyz')

# Get general parameters

basename = parameter('basename', 'crack_tip')
calc = parameter('calc')
fmax = parameter('fmax', 0.01)

# Get parameter used for fitting crack tip position

residual_func = parameter('residual_func', crack.displacement_residual)
_residual_func = residual_func
tip_tol = parameter('tip_tol', 1e-4)
tip_mixing_alpha = parameter('tip_mixing_alpha', 1.0)
write_trajectory_during_optimization = parameter(
    'write_trajectory_during_optimization', False)

tip_x = (a.positions[bond1, 0] + a.positions[bond2, 0]) / 2
tip_y = (a.positions[bond1, 1] + a.positions[bond2, 1]) / 2
logger.pr('Optimizing tip position -> initially centering tip bond. '
Example #11
0
Optimizer = ase.optimize.FIRE
#Optimizer = ase.optimize.precon.LBFGS

# Atom types used for outputting the crack tip position.
ACTUAL_CRACK_TIP = 'Au'
FITTED_CRACK_TIP = 'Ag'

###

logger = screen

###

# Get general parameters

residual_func = parameter('residual_func', crack.displacement_residual)
_residual_func = residual_func

basename = parameter('basename', 'neb')
calc = parameter('calc')
fmax_neb = parameter('fmax_neb', 0.1)
maxsteps_neb = parameter('maxsteps_neb', 100)
Nimages = parameter('Nimages', 7)
k_neb = parameter('k_neb', 1.0)

a, cryst, crk, k1g, tip_x, tip_y, bond1, bond2, boundary_mask, \
    boundary_mask_bulk, tip_mask = setup_crack(logger=logger)

# Deformation gradient residual needs full Atoms object and therefore
# special treatment here.
if _residual_func == crack.deformation_gradient_residual:
Example #12
0
def setup_crack(logger=screen):
    calc = parameter('calc')

    cryst = parameter('cryst').copy()
    cryst.set_pbc(True)

    # Double check elastic constants. We're just assuming this is really a periodic
    # system. (True if it comes out of the cluster routines.)

    compute_elastic_constants = parameter('compute_elastic_constants', False)
    elastic_fmax = parameter('elastic_fmax', 0.01)
    elastic_symmetry = parameter('elastic_symmetry', 'triclinic')
    elastic_optimizer = parameter('elastic_optimizer', ase.optimize.FIRE)

    if compute_elastic_constants:
        cryst.set_calculator(calc)
        log_file = open('elastic_constants.log', 'w')
        C, C_err = fit_elastic_constants(cryst, verbose=False,
                                         symmetry=elastic_symmetry,
                                         optimizer=elastic_optimizer,
                                         logfile=log_file,
                                         fmax=elastic_fmax)
        log_file.close()
        logger.pr('Measured elastic constants (in GPa):')
        logger.pr(np.round(C*10/GPa)/10)

        crk = crack.CubicCrystalCrack(parameter('crack_surface'),
                                      parameter('crack_front'),
                                      Crot=C/GPa)
    else:
        if has_parameter('C'):
            crk = crack.CubicCrystalCrack(parameter('crack_surface'),
                                          parameter('crack_front'),
                                          C=parameter('C'))
        else:
            crk = crack.CubicCrystalCrack(parameter('crack_surface'),
                                          parameter('crack_front'),
                                          parameter('C11'), parameter('C12'),
                                          parameter('C44'))


    logger.pr('Elastic constants used for boundary condition (in GPa):')
    logger.pr(np.round(crk.C*10)/10)

    # Get Griffith's k1.
    k1g = crk.k1g(parameter('surface_energy'))
    logger.pr('Griffith k1 = %f' % k1g)

    # Apply initial strain field.
    tip_x = parameter('tip_x', cryst.cell.diagonal()[0]/2)
    tip_y = parameter('tip_y', cryst.cell.diagonal()[1]/2)

    bondlength = parameter('bondlength', 2.7)
    bulk_nn = parameter('bulk_nn', 4)

    a = cryst.copy()
    a.set_pbc([False, False, True])

    hydrogenate_flag = parameter('hydrogenate', False)
    hydrogenate_crack_face_flag = parameter('hydrogenate_crack_face', True)

    if hydrogenate_flag and not hydrogenate_crack_face_flag:
        # Get surface atoms of cluster with crack
        a = hydrogenate(cryst, bondlength, parameter('XH_bondlength'), b=a)
        g = a.get_array('groups')
        g[a.numbers==1] = -1
        a.set_array('groups', g)
        cryst = a.copy()

    k1 = parameter('k1')
    try:
      k1 = k1[0]
    except:
      pass
    ux, uy = crk.displacements(cryst.positions[:,0], cryst.positions[:,1],
                               tip_x, tip_y, k1*k1g)
    a.positions[:len(cryst),0] += ux
    a.positions[:len(cryst),1] += uy

    # Center notched configuration in simulation cell and ensure enough vacuum.
    oldr = a[0].position.copy()
    vacuum = parameter('vacuum')
    a.center(vacuum=vacuum, axis=0)
    a.center(vacuum=vacuum, axis=1)
    tip_x += a[0].x - oldr[0]
    tip_y += a[0].y - oldr[1]

    # Choose which bond to break.
    bond1, bond2 = \
        parameter('bond', crack.find_tip_coordination(a, bondlength=bondlength, bulk_nn=bulk_nn))

    if parameter('center_crack_tip_on_bond', False):
        tip_x, tip_y, dummy = (a.positions[bond1]+a.positions[bond2])/2

    # Hydrogenate?
    coord = np.bincount(neighbour_list('i', a, bondlength), minlength=len(a))
    a.set_array('coord', coord)

    if parameter('optimize_full_crack_face', False):
        g = a.get_array('groups')
        gcryst = cryst.get_array('groups')
        coord = a.get_array('coord')
        g[coord!=4] = -1
        gcryst[coord!=4] = -1
        a.set_array('groups', g)
        cryst.set_array('groups', gcryst)

    if hydrogenate_flag and hydrogenate_crack_face_flag:
        # Get surface atoms of cluster with crack
        exclude = np.logical_and(a.get_array('groups')==1, coord!=4)
        a.set_array('exclude', exclude)
        a = hydrogenate(cryst, bondlength, parameter('XH_bondlength'), b=a,
                        exclude=exclude)
        g = a.get_array('groups')
        g[a.numbers==1] = -1
        a.set_array('groups', g)
        basename = parameter('basename', 'energy_barrier')
        ase.io.write('{0}_hydrogenated.xyz'.format(basename), a,
                     format='extxyz')

    # Move reference crystal by same amount
    cryst.set_cell(a.cell)
    cryst.set_pbc([False, False, True])
    cryst.translate(a[0].position - oldr)

    # Groups mark the fixed region and the region use for fitting the crack tip.
    g = a.get_array('groups')
    gcryst = cryst.get_array('groups')

    logger.pr('Opening bond {0}--{1}, initial bond length {2}'.
          format(bond1, bond2, a.get_distance(bond1, bond2, mic=True)))

    # centre vertically on the opening bond
    if parameter('center_cell_on_bond', True):
      a.translate([0., a.cell[1,1]/2.0 -
                      (a.positions[bond1, 1] +
                       a.positions[bond2, 1])/2.0, 0.])

    a.info['bond1'] = bond1
    a.info['bond2'] = bond2

    return a, cryst, crk, k1g, tip_x, tip_y, bond1, bond2, g==0, gcryst==0, g==1
Example #13
0
# Atom types used for outputting the crack tip position.
ACTUAL_CRACK_TIP = 'Au'
FITTED_CRACK_TIP = 'Ag'

###

logger = screen

###

a, cryst, crk, k1g, tip_x0, tip_y0, bond1, bond2, boundary_mask, \
    boundary_mask_bulk, tip_mask = setup_crack(logger=logger)
ase.io.write('notch.xyz', a, format='extxyz')   

# Global parameters
basename = parameter('basename', 'quasistatic_crack')
calc = parameter('calc')
fmax = parameter('fmax', 0.01)

# Determine simulation control
k1_list = parameter('k1')
old_k1 = k1_list[0]
nsteps = len(k1_list)
tip_dx_list = parameter('tip_dx', np.zeros(nsteps))
tip_dy_list = parameter('tip_dy', np.zeros(nsteps))

# Run crack calculation.
tip_x = tip_x0
tip_y = tip_y0
a.set_calculator(calc)
for i, ( k1, tip_dx, tip_dy ) in enumerate(zip(k1_list, tip_dx_list,
Example #14
0
import sys
import numpy as np

from ase.units import GPa

from matscipy import parameter
from matscipy.elasticity import fit_elastic_constants
from matscipy.fracture_mechanics.crack import CubicCrystalCrack, SinclairCrack

from scipy.optimize import fsolve

sys.path.insert(0, '.')
import params

calc = parameter('calc')
fmax = parameter('fmax', 1e-3)
max_steps = parameter('max_steps', 100)
vacuum = parameter('vacuum', 10.0)
alpha_scale = parameter('alpha_scale', 1.0)
continuation = parameter('continuation', False)
ds = parameter('ds', 1e-2)
nsteps = parameter('nsteps', 10)
method = parameter('method', 'full')
k0 = parameter('k0', 1.0)

# compute elastic constants
cryst = params.cryst.copy()
cryst.pbc = True
cryst.calc = calc
C, C_err = fit_elastic_constants(cryst,
Example #15
0
import os
import numpy as np

import ase.io
from ase.units import GPa

from matscipy import parameter
from matscipy.elasticity import fit_elastic_constants
from matscipy.fracture_mechanics.crack import CubicCrystalCrack, SinclairCrack

import sys

sys.path.insert(0, '.')
import params

calc = parameter('calc')
fmax = parameter('fmax', 1e-3)
vacuum = parameter('vacuum', 10.0)
flexible = parameter('flexible', True)
extended_far_field = parameter('extended_far_field', False)
k0 = parameter('k0', 1.0)
alpha0 = parameter('alpha0', 0.0)  # initial guess for crack position
dump = parameter('dump', False)
precon = parameter('precon', False)
prerelax = parameter('prerelax', False)

# compute elastic constants
cryst = params.cryst.copy()
cryst.pbc = True
cryst.calc = calc
C, C_err = fit_elastic_constants(cryst,
Example #16
0
import h5py
import ase.io
from ase.units import GPa

from matscipy import parameter
from matscipy.elasticity import fit_elastic_constants
from matscipy.fracture_mechanics.crack import CubicCrystalCrack, SinclairCrack

from scipy.optimize.nonlin import NoConvergence

import sys
sys.path.insert(0, '.')

import params

calc = parameter('calc')
fmax = parameter('fmax', 1e-3)
max_steps = parameter('max_steps', 100)
vacuum = parameter('vacuum', 10.0)
flexible = parameter('flexible', True)
continuation = parameter('continuation', False)
ds = parameter('ds', 1e-2)
nsteps = parameter('nsteps', 10)
k0 = parameter('k0', 1.0)
extended_far_field = parameter('extended_far_field', False)
alpha0 = parameter('alpha0', 0.0)  # initial guess for crack position
dump = parameter('dump', False)
precon = parameter('precon', False)
prerelax = parameter('prerelax', False)
traj_file = parameter('traj_file', 'x_traj.h5')
traj_interval = parameter('traj_interval', 1)