relaPorous.mjs

import get from 'lodash-es/get.js'
import join from 'lodash-es/join.js'
import values from 'lodash-es/values.js'
import isNumber from 'lodash-es/isNumber.js'
import isnum from 'wsemi/src/isnum.mjs'
import isbol from 'wsemi/src/isbol.mjs'
import iseobj from 'wsemi/src/iseobj.mjs'
import cdbl from 'wsemi/src/cdbl.mjs'
import cnst from './cnst.mjs'


// //eps
// let eps = cnst.eps


//rw, 水單位重(kN/m3)
let rw = cnst.rw


function get_rd_from_GS_e(GS, e) {
    let rd = GS * rw / (1 + e)
    return rd
}


function get_rd_from_rsat_e(rsat, e) {
    let rd = rsat - (e * rw) / (1 + e)
    return rd
}


function get_rd_from_rsat_GS(rsat, GS) {
    let rd = (rsat - rw) * GS / (GS - 1)
    return rd
}


function get_rsat_from_GS_e(GS, e) {
    let rsat = (GS + e) * rw / (1 + e)
    return rsat
}


function get_rsat_from_rd_e(rd, e) {
    let rsat = rd + (e * rw) / (1 + e)
    return rsat
}


function get_rsat_from_rd_GS(rd, GS) {
    let rsat = rd * (GS - 1) / GS + rw
    return rsat
}


function get_e_from_GS_rd(GS, rd) {
    let e = (GS * rw - rd) / rd
    return e
}


function get_e_from_rd_rsat(rd, rsat) {
    let e = (rd - rsat) / (rsat - rw - rd)
    return e
}


// function get_e_from_rsat_rd(rsat, rd) {
//     let e = rw * (rsat - rd) / (1 - rw * (rsat - rd)) //結果同get_e_from_rd_rsat
//     return e
// }


function get_e_from_GS_rsat(GS, rsat) {
    let e = (GS * rw - rsat) / (rsat - rw)
    return e
}


function get_GS_from_rd_e(rd, e) {
    let GS = rd * (1 + e) / rw
    return GS
}


function get_GS_from_rd_rsat(rd, rsat) {
    let GS = rd / (rd - (rsat - rw))
    return GS
}


function get_GS_from_rsat_e(rsat, e) {
    let GS = (rsat + rsat * e - e * rw) / rw
    return GS
}


/**
 * 計算岩土孔隙參數:乾單位重rd、飽和單位重rsat、比重GS、孔隙比e之間互相轉換,至少4給2才能反推全部
 *
 * Unit Test: {@link https://github.com/yuda-lyu/w-geo/blob/master/test/relaPorous.test.js Github}
 * @memberOf w-geo
 * @param {Number} [rd=null] 輸入乾單位重數字,單位kN/m3,預設null
 * @param {Number} [rsat=null] 輸入飽和單位重數字,單位kN/m3,預設null
 * @param {Number} [GS=null] 輸入比重數字,無單位,預設null
 * @param {Number} [e=null] 輸入孔隙比數字,無單位,預設null
 * @param {Object} [opt={}] 輸入設定物件,預設{}
 * @param {Boolean} [opt.returnFuncs=false] 輸入是否回傳函數布林值,預設false
 * @returns {Object} 回傳物件,含鍵值rd、rsat、GS、e
 * @example
 *
 * let GS = 2.7
 * let e = 0.86
 * let rd = 14.240322580645163 //kN/m3
 * let rsat = 18.776129032258066 //kN/m3
 * let r
 *
 * let coreFuncs = relaPorous(null, null, null, null, { returnFuncs: true }).coreFuncs
 *
 * console.log('rd get_rd_from_GS_e', coreFuncs.get_rd_from_GS_e(GS, e))
 * // => rd get_rd_from_GS_e 14.240322580645163
 *
 * console.log('rd get_rd_from_rsat_e', coreFuncs.get_rd_from_rsat_e(rsat, e))
 * // => rd get_rd_from_rsat_e 14.240322580645163
 *
 * console.log('rd get_rd_from_rsat_GS', coreFuncs.get_rd_from_rsat_GS(rsat, GS))
 * // => rd get_rd_from_rsat_GS 14.240322580645161
 *
 * console.log('rsat get_rsat_from_GS_e', coreFuncs.get_rsat_from_GS_e(GS, e))
 * // => rsat get_rsat_from_GS_e 18.776129032258066
 *
 * console.log('rsat get_rsat_from_rd_e', coreFuncs.get_rsat_from_rd_e(rd, e))
 * // => rsat get_rsat_from_rd_e 18.776129032258066
 *
 * console.log('rsat get_rsat_from_rd_GS', coreFuncs.get_rsat_from_rd_GS(rd, GS))
 * // => rsat get_rsat_from_rd_GS 18.77612903225807
 *
 * console.log('e get_e_from_GS_rd', coreFuncs.get_e_from_GS_rd(GS, rd))
 * // => e get_e_from_GS_rd 0.8599999999999999
 *
 * console.log('e get_e_from_rd_rsat', coreFuncs.get_e_from_rd_rsat(rd, rsat))
 * // => e get_e_from_rd_rsat 0.8599999999999998
 *
 * console.log('e get_e_from_GS_rsat', coreFuncs.get_e_from_GS_rsat(GS, rsat))
 * // => e get_e_from_GS_rsat 0.86
 *
 * console.log('GS get_GS_from_rd_e', coreFuncs.get_GS_from_rd_e(rd, e))
 * // => GS get_GS_from_rd_e 2.7
 *
 * console.log('GS get_GS_from_rd_rsat', coreFuncs.get_GS_from_rd_rsat(rd, rsat))
 * // => GS get_GS_from_rd_rsat 2.6999999999999997
 *
 * console.log('GS get_GS_from_rsat_e', coreFuncs.get_GS_from_rsat_e(rsat, e))
 * // => GS get_GS_from_rsat_e 2.7
 *
 * r = relaPorous(rd, rsat, null, null)
 * console.log('rd,rsat', r)
 * // => rd,rsat {
 * //     rd: 14.240322580645163,
 * //     rsat: 18.776129032258066,
 * //     GS: 2.7,
 * //     e: 0.8599999999999998
 * // }
 *
 * r = relaPorous(rd, null, GS, null)
 * console.log('rd,GS', r)
 * // => rd,GS {
 * //     rd: 14.240322580645163,
 * //     rsat: 18.77612903225807,
 * //     GS: 2.7,
 * //     e: 0.8599999999999999
 * // }
 *
 * r = relaPorous(rd, null, null, e)
 * console.log('rd,e', r)
 * // => rd,e {
 * //     rd: 14.240322580645163,
 * //     rsat: 18.776129032258066,
 * //     GS: 2.7,
 * //     e: 0.86
 * // }
 *
 * r = relaPorous(null, rsat, GS, null)
 * console.log('rsat,GS', r)
 * // => rsat,GS {
 * //     rd: 14.240322580645161,
 * //     rsat: 18.776129032258066,
 * //     GS: 2.7,
 * //     e: 0.8600000000000001
 * // }
 *
 * r = relaPorous(null, rsat, null, e)
 * console.log('rsat,e', r)
 * // => rsat,e {
 * //     rd: 14.240322580645163,
 * //     rsat: 18.776129032258066,
 * //     GS: 2.7,
 * //     e: 0.86
 * // }
 *
 * r = relaPorous(null, null, GS, e)
 * console.log('GS,e', r)
 * // => GS,e {
 * //     rd: 14.240322580645163,
 * //     rsat: 18.776129032258066,
 * //     GS: 2.7,
 * //     e: 0.86
 * // }
 *
 * r = relaPorous(rd, rsat, GS, null)
 * console.log('rd,rsat,GS', r)
 * // => rd,rsat,GS {
 * //     rd: 14.240322580645163,
 * //     rsat: 18.776129032258066,
 * //     GS: 2.7,
 * //     e: 0.8599999999999999
 * // }
 *
 * r = relaPorous(rd, rsat, null, e)
 * console.log('rd,rsat,e', r)
 * // => rd,rsat,e {
 * //     rd: 14.240322580645163,
 * //     rsat: 18.776129032258066,
 * //     GS: 2.7,
 * //     e: 0.86
 * // }
 *
 * r = relaPorous(rd, null, GS, e)
 * console.log('rd,GS,e', r)
 * // => rd,GS,e {
 * //     rd: 14.240322580645163,
 * //     rsat: 18.776129032258066,
 * //     GS: 2.7,
 * //     e: 0.86
 * // }
 *
 * r = relaPorous(null, rsat, GS, e)
 * console.log('rsat,GS,e', r)
 * // => rsat,GS,e {
 * //     rd: 14.240322580645163,
 * //     rsat: 18.776129032258066,
 * //     GS: 2.7,
 * //     e: 0.86
 * // }
 *
 * try {
 *     r = relaPorous(13.9, null, GS, e)
 * }
 * catch (e) {
 *     r = e.toString()
 * }
 * console.log('GS,e', r)
 * // => GS,e {
 * //   rd: 13.9,
 * //   rsat: 18.776129032258066,
 * //   GS: 2.7,
 * //   e: 0.86,
 * //   err: '輸入孔隙比[0.86]與反算出孔隙比[0.9055395683453238]差距過大'
 * // }
 *
 */
function relaPorous(rd, rsat, GS, e, opt = {}) {
    let kpErr = {} //非中斷報錯訊息

    //returnFuncs
    let returnFuncs = get(opt, 'returnFuncs')
    if (!isbol(returnFuncs)) {
        returnFuncs = false
    }

    //rd, 乾單位重(kN/m3)
    if (isnum(rd)) {
        rd = cdbl(rd)
        if (rd <= 0) {
            kpErr['rd'] = `乾單位重[${rd}]為數字但<=0,自動清除`
        }
        if (rd <= rw) {
            kpErr['rd'] = `乾單位重[${rd}]<=水單位重[${rw}]`
        }
    }
    else {
        rd = null
    }

    //rsat, 飽和單位重(kN/m3)
    if (isnum(rsat)) {
        rsat = cdbl(rsat)
        if (rsat <= 0) {
            kpErr['rsat'] = `飽和單位重[${rsat}]為數字但<=0,自動清除`
        }
        if (rsat <= rw) {
            kpErr['rsat'] = `飽和單位重[${rsat}]<=水單位重[${rw}]`
        }
    }
    else {
        rsat = null
    }

    //GS, 比重
    if (isnum(GS)) {
        GS = cdbl(GS)
        if (GS <= 0) {
            kpErr['GS'] = `比重[${GS}]為數字但<=0,自動清除`
        }
    }
    else {
        GS = null
    }

    //e, 孔隙比
    if (isnum(e)) {
        e = cdbl(e)
        if (e <= 0) {
            kpErr['e'] = `孔隙比[${e}]為數字但<=0,自動清除`
        }
    }
    else {
        e = null
    }

    function core() {
        let bUpdate = false

        //calc rd
        let _rd
        if (!isNumber(_rd) && isNumber(GS) && isNumber(e)) {
            _rd = get_rd_from_GS_e(GS, e)
        }
        if (!isNumber(_rd) && isNumber(rsat) && isNumber(e)) {
            _rd = get_rd_from_rsat_e(rsat, e)
        }
        if (!isNumber(_rd) && isNumber(rsat) && isNumber(GS)) {
            if (GS !== 1) {
                _rd = get_rd_from_rsat_GS(rsat, GS)
            }
        }
        if (!isNumber(rd)) {
            rd = _rd
            bUpdate = true
        }
        else {
            // console.log('rd isNumber', Math.abs(rd - _rd) > eps)
            if (Math.abs(rd - _rd) > _rd / 100 * 5) {
                kpErr['ck_rd'] = `輸入乾單位重[${rd}]與反算出乾單位重[${_rd}]差距過大`
            }
        }

        //calc rsat
        let _rsat
        if (!isNumber(_rsat) && isNumber(GS) && isNumber(e)) {
            _rsat = get_rsat_from_GS_e(GS, e)
        }
        if (!isNumber(_rsat) && isNumber(rd) && isNumber(e)) {
            _rsat = get_rsat_from_rd_e(rd, e)
        }
        if (!isNumber(_rsat) && isNumber(rd) && isNumber(GS)) {
            _rsat = get_rsat_from_rd_GS(rd, GS)
        }
        if (!isNumber(rsat)) {
            rsat = _rsat
            bUpdate = true
        }
        else {
            if (Math.abs(rsat - _rsat) > _rsat / 100 * 5) {
                kpErr['ck_rsat'] = `輸入飽和單位重[${rsat}]與反算出飽和單位重[${_rsat}]差距過大`
            }
        }

        //calc e
        let _e
        if (!isNumber(_e) && isNumber(GS) && isNumber(rd)) {
            _e = get_e_from_GS_rd(GS, rd)
        }
        if (!isNumber(_e) && isNumber(rsat) && isNumber(rd)) {
            if ((rsat - rw - rd) !== 0) {
                _e = get_e_from_rd_rsat(rd, rsat)
            }
        }
        if (!isNumber(_e) && isNumber(rsat) && isNumber(GS)) {
            if ((rsat - rw) !== 0) {
                _e = get_e_from_GS_rsat(GS, rsat)
            }
        }
        if (!isNumber(e)) {
            e = _e
            bUpdate = true
        }
        else {
            if (Math.abs(e - _e) > _e / 100 * 5) {
                kpErr['ck_e'] = `輸入孔隙比[${e}]與反算出孔隙比[${_e}]差距過大`
            }
        }

        //calc GS
        let _GS
        if (!isNumber(_GS) && isNumber(rd) && isNumber(e)) {
            _GS = get_GS_from_rd_e(rd, e)
        }
        if (!isNumber(_GS) && isNumber(rd) && isNumber(rsat)) {
            if ((rd - (rsat - rw)) !== 0) {
                _GS = get_GS_from_rd_rsat(rd, rsat)
            }
        }
        if (!isNumber(_GS) && isNumber(rsat) && isNumber(e)) {
            _GS = get_GS_from_rsat_e(rsat, e)
        }
        if (!isNumber(GS)) {
            GS = _GS
            bUpdate = true
        }
        else {
            if (Math.abs(GS - _GS) > _GS / 100 * 5) {
                kpErr['ck_GS'] = `輸入比重[${GS}]與反算出比重[${_GS}]差距過大`
            }
        }

        return bUpdate
    }

    //check 至少要2參數才進行轉換
    let ieff = 0
    ieff += isnum(rd) ? 1 : 0
    ieff += isnum(rsat) ? 1 : 0
    ieff += isnum(GS) ? 1 : 0
    ieff += isnum(e) ? 1 : 0
    if (ieff >= 2) {
        let b = core()
        while (b) {
            b = core()
        }
    }

    //r
    let r = {
        rd,
        rsat,
        GS,
        e,
    }
    if (iseobj(kpErr)) {
        let err = join(values(kpErr), ', ')
        r.err = err
    }
    if (returnFuncs) {
        r.coreFuncs = {
            get_rd_from_GS_e,
            get_rd_from_rsat_e,
            get_rd_from_rsat_GS,
            get_rsat_from_GS_e,
            get_rsat_from_rd_e,
            get_rsat_from_rd_GS,
            get_e_from_GS_rd,
            get_e_from_rd_rsat,
            get_e_from_GS_rsat,
            get_GS_from_rd_e,
            get_GS_from_rd_rsat,
            get_GS_from_rsat_e,
        }
    }

    return r
}


export default relaPorous