<repo_name>inowas/gwflowjs<file_sep>/src/helpers/index.js
import erf from './erf.js';
import erfc from './erfc.js';
import numericallyIntegrate from './numericallyIntegrate';

export {
    erf,
    erfc,
    numericallyIntegrate
};
<file_sep>/src/gwMounding/mounding.js
import { erf, numericallyIntegrate } from '../helpers/index';

function S(alpha, beta) {
    const func = (tau) => {
        if (tau !== 0) {
            const sqrtTau = Math.sqrt(tau);
            return erf(alpha / sqrtTau) * erf(beta / sqrtTau);
        }

        return 0;
    };

    return numericallyIntegrate(0, 1, 0.001, func);
}

export function calculateHi(x, y, w, L, W, hi, Sy, K, t) {
    const a = W / 2;
    const l = L / 2;
    const v = K * hi / Sy;
    const sqrt4vt = Math.sqrt(4 * v * t);

    const s1 = S((l + x) / sqrt4vt, (a + y) / sqrt4vt);
    const s2 = S((l + x) / sqrt4vt, (a - y) / sqrt4vt);
    const s3 = S((l - x) / sqrt4vt, (a + y) / sqrt4vt);
    const s4 = S((l - x) / sqrt4vt, (a - y) / sqrt4vt);

    return Math.sqrt(w / 2 / K * v * t * (s1 + s2 + s3 + s4) + hi * hi).toFixed(5) - hi.toFixed(5); // eq 1
}

export function calculateHMax(w, L, W, hi, Sy, K, t) {
    return calculateHi(0, 0, w, L, W, hi, Sy, K, t) + hi;
}
<file_sep>/src/transport1d/index.js
import * as transport1d from 'transport1d';

export { transport1d };
<file_sep>/src/helpers/numericallyIntegrate.js

export default function numericallyIntegrate( a, b, dx, f ) {
    // define the variable for area
    let area = 0;

    // loop to calculate the area of each trapezoid and sum.
    for ( let x1 = a + dx; x1 <= b; x1 += dx ) {
        // the x locations of the left and right side of each trapezoid
        const x0 = x1 - dx;

        // the area of each trapezoid
        const Ai = dx * ( f( x0 ) + f( x1 ) ) / 2.0;

        // cumulatively sum the areas
        area += Ai;
    }

    return area;
}
<file_sep>/README.md
# INOWAS Groundwater-Flow-Library [![Build Status](https://img.shields.io/travis/inowas/gwflowjs/master.svg)](https://travis-ci.org/inowas/gwflowjs) 

A set of analytical functions to calculate different kind of groundwater-flow processes.

## Documentation

- [1D transport model (Ogata-Banks)](https://wiki.inowas.hydro.tu-dresden.de/t08-1d-transport-model-ogata-banks/)
- [Groundwater mounding (Hantush)](https://wiki.inowas.hydro.tu-dresden.de/t02-groundwater-mounding-hantush/)

## Contribute

### Clone repository

git clone https://github.com/inowas/gwflowjs.git


### Install dependencies  

yarn install

### Run Tests 


yarn test
<file_sep>/test/transport1D.spec.js
/* global describe, it, before */

import chai from 'chai';
import {transport1d} from '../src/index';

chai.expect();

const expect = chai.expect;

describe('Given the transport1d-function (ogata-banks)', () => {
    const values = [
        [725, 15, 365, 2.592, 0.002, 0.23, 0.923, 0.01, 0.02313],
        [500, 15, 365, 2.592, 0.002, 0.23, 0.923, 0.01, 0.02313],
        [500, 13, 365, 2.592, 0.002, 0.23, 0.923, 0.01, 0.07249],
        [500, 10, 13650, 2.592, 0.002, 0.23, 0.923, 0.01, 1.0000]
    ];

    values.forEach(v => {
        const decimals = 5;

        const C0 = v[0];
        const x = v[1];
        const t = v[2];
        const K = v[3];
        const I = v[4];
        const ne = v[5];
        const alphaL = v[6];
        const Kd = v[7];
        const expected = v[8].toFixed(decimals);

        it('calculating transport1d-function should return ' + expected, () => {
            expect(transport1d.calculateC(x, t, K, I, ne, alphaL, Kd).toFixed(decimals)).to.be.equal(expected);
        });
    });
});

describe('Given the transport1d-function (ogata-banks)', () => {
    const values = [
        [725, 15, 365, 2.592, 0.002, 0.23, 0.923, 0.01, 2500],
        [500, 15, 365, 2.592, 0.002, 0.23, 0.923, 0.01, 2500],
        [500, 13, 365, 2.592, 0.002, 0.23, 0.923, 0.01, 420],
        [500, 13, 365, 40, 0.002, 0.23, 0.923, 0.01, 60],
        [500, 10, 13650, 2.592, 0.002, 0.23, 0.923, 0.01, 180]
    ];

    values.forEach(v => {
        const decimals = 5;

        const C0 = v[0];
        const x = v[1];
        const t = v[2];
        const K = v[3];
        const I = v[4];
        const ne = v[5];
        const alphaL = v[6];
        const Kd = v[7];
        const expected = v[8].toFixed(decimals);

        it('calculating Tmax-function should return ' + expected, () => {
            expect(transport1d.calculateTmax(x, K, I, ne, alphaL, Kd).toFixed(decimals)).to.be.equal(expected);
        });
    });
});

describe('Given the transport1d-function (ogata-banks)', () => {
    const values = [
        [725, 15, 365, 2.592, 0.002, 0.23, 0.923, 0.01, 20],
        [500, 15, 365, 2.592, 0.002, 0.23, 0.923, 0.01, 20],
        [500, 13, 365, 2.592, 0.002, 0.23, 0.923, 0.01, 20],
        [500, 13, 365, 40, 0.002, 0.23, 0.923, 0.01, 200],
        [500, 10, 13650, 2.592, 0.002, 0.23, 0.923, 0.01, 400]
    ];

    values.forEach(v => {
        const decimals = 5;

        const C0 = v[0];
        const x = v[1];
        const t = v[2];
        const K = v[3];
        const I = v[4];
        const ne = v[5];
        const alphaL = v[6];
        const Kd = v[7];
        const expected = v[8].toFixed(decimals);

        it('calculating XMax-function should return ' + expected, () => {
            expect(transport1d.calculateXmax(t, K, I, ne, alphaL, Kd).toFixed(decimals)).to.be.equal(expected);
        });
    });
});
<file_sep>/src/helpers/erf.js
export default function erf(x, decimals = 7) {
    const a1 = 0.254829592;
    const a2 = -0.284496736;
    const a3 = 1.421413741;
    const a4 = -1.453152027;
    const a5 = 1.061405429;
    const p = 0.3275911;

    // Save the sign of x
    let sign = 1;

    if (x < 0) sign = -1;

    const absX = Math.abs(x);
    // A & S 7.1.26 with Horners Method
    const t = 1.0 / (1.0 + p * absX);
    const y = 1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * Math.exp(-absX * absX);
    return (sign * y).toFixed(decimals);
}
