"""
 Copyright (C) 2021 Susi Lehtola

 This Source Code Form is subject to the terms of the Mozilla Public
 License, v. 2.0. If a copy of the MPL was not distributed with this
 file, You can obtain one at http://mozilla.org/MPL/2.0/.
"""

# type: gga_exc
# prefix:
#   gga_c_lypr_params *params;
#
#   assert(p->params != NULL);
#   params = (gga_c_lypr_params * )(p->params);

from libxc_codegen import *  # noqa: F401, F403

params_a_m2 = param_default("m2")
params_a_omega = param_default("omega")
params_a_a = param_default("a")
params_a_m1 = param_default("m1")

include('gga_c_lyp')

@helper
def lypr_eta(rr):
    return (
        -Integer(2)/(Integer(3)*sqrt(pi))*params_a_m2*params_a_omega
        * exp(-params_a_m2**Integer(2)*params_a_omega**Integer(2)*rr**Integer(2))
    )

@helper
def lypr_t7(rr, z, xt, xs0, xs1):
    return (
        -rr * one_minus_z_pow_n(z, Integer(2))/Integer(4) * (
        + Integer(7)/Integer(6)*(xt**Integer(2) - lyp_aux6*(xs0**Integer(2)*opz_pow_n(z,Integer(8)/Integer(3)) + xs1**Integer(2)*opz_pow_n(-z,Integer(8)/Integer(3))))
        + (Integer(1) + (Integer(1) + z)/Integer(6))*xs0**Integer(2)*lyp_aux6*opz_pow_n( z, Integer(8)/Integer(3))
        + (Integer(1) + (Integer(1) - z)/Integer(6))*xs1**Integer(2)*lyp_aux6*opz_pow_n(-z, Integer(8)/Integer(3))
        )
    )

# This functional is very similar to gga_c_lyp. One adds the two erfc and
# the extra term proportinal to eta

@helper
def f_lypr_rr(rr, z, xt, xs0, xs1):
    return (
        params_a_a*(
        + erfc(params_a_m1*params_a_omega*rr)*lyp_t1(rr, z)
        + erfc(params_a_m2*params_a_omega*rr)*lyp_omega(rr)*(
        + lyp_t2(rr, z, xt**Integer(2)) + lyp_t3(z) + lyp_t4(rr, z, xs0**Integer(2), xs1**Integer(2))
        + lyp_t5(rr, z, xs0**Integer(2), xs1**Integer(2)) + lyp_t6(z, xs0**Integer(2), xs1**Integer(2))
        )
        + lyp_omega(rr)*lypr_eta(rr)*lypr_t7(rr, z, xt, xs0, xs1)
        )
    )

# rr = rs/RS_FACTOR is equal to n_total(rs)^(-1/3)

@helper
def f_lypr(rs, z, xt, xs0, xs1):
    return f_lypr_rr(rs/RS_FACTOR, z, xt, xs0, xs1)

def f(rs, z, xt, xs0, xs1):
    return f_lypr(rs, z, xt, xs0, xs1)

TYPE = "gga_exc"
PARAMS_STRUCT = "gga_c_lypr_params"
