// Update the coefficients associated with the patch field
void tractionDisplacementFvPatchVectorField::updateCoeffs()
{
    if (updated())
    {
        return;
    }

    const dictionary& mechanicalProperties =
        db().lookupObject<IOdictionary>("mechanicalProperties");

    const dictionary& thermalProperties =
        db().lookupObject<IOdictionary>("thermalProperties");

    dimensionedScalar rho(mechanicalProperties.lookup("rho"));
    dimensionedScalar rhoE(mechanicalProperties.lookup("E"));
    dimensionedScalar nu(mechanicalProperties.lookup("nu"));

    dimensionedScalar E = rhoE/rho;
    dimensionedScalar mu = E/(2.0*(1.0 + nu));
    dimensionedScalar lambda = nu*E/((1.0 + nu)*(1.0 - 2.0*nu));
    dimensionedScalar threeK = E/(1.0 - 2.0*nu);

    Switch planeStress(mechanicalProperties.lookup("planeStress"));

    if (planeStress)
    {
        lambda = nu*E/((1.0 + nu)*(1.0 - nu));
        threeK = E/(1.0 - nu);
    }

    vectorField n = patch().nf();

    const fvPatchField<tensor>& gradU =
        patch().lookupPatchField<volTensorField, tensor>("grad(U)");

    gradient() =
    (
        (traction_ - pressure_*n)/rho.value()
      - (n & (mu.value()*gradU.T() - (mu + lambda).value()*gradU))
      - n*tr(gradU)*lambda.value()
    )/(2.0*mu + lambda).value();


    Switch thermalStress(thermalProperties.lookup("thermalStress"));

    if (thermalStress)
    {
        dimensionedScalar alpha(thermalProperties.lookup("alpha"));
        dimensionedScalar threeKalpha = threeK*alpha;

        const fvPatchField<scalar>& T =
            patch().lookupPatchField<volScalarField, scalar>("T");

        gradient() += n*threeKalpha.value()*T/(2.0*mu + lambda).value();
    }

    fixedGradientFvPatchVectorField::updateCoeffs();
}
void tractionDisplacementFvPatchVectorField::updateCoeffs()
{
    if (updated())
    {
        return;
    }

    const dictionary& mechanicalProperties =
        db().lookupObject<IOdictionary>("mechanicalProperties");

    const dictionary& thermalProperties =
        db().lookupObject<IOdictionary>("thermalProperties");

    dimensionedScalar rho(mechanicalProperties.lookup("rho"));
    dimensionedScalar rhoE(mechanicalProperties.lookup("E"));
    dimensionedScalar nu(mechanicalProperties.lookup("nu"));

    dimensionedScalar E = rhoE/rho;
    dimensionedScalar mu = E/(2.0*(1.0 + nu));
    dimensionedScalar lambda = nu*E/((1.0 + nu)*(1.0 - 2.0*nu));
    dimensionedScalar threeK = E/(1.0 - 2.0*nu);

    Switch planeStress(mechanicalProperties.lookup("planeStress"));

    if (planeStress)
    {
        lambda = nu*E/((1.0 + nu)*(1.0 - nu));
        threeK = E/(1.0 - nu);
    }

    scalar twoMuLambda = (2*mu + lambda).value();

    vectorField n(patch().nf());

    const fvPatchField<symmTensor>& sigmaD =
        patch().lookupPatchField<volSymmTensorField, symmTensor>("sigmaD");

    gradient() =
    (
        (traction_ + pressure_*n)/rho.value()
      + twoMuLambda*fvPatchField<vector>::snGrad() - (n & sigmaD)
    )/twoMuLambda;

    Switch thermalStress(thermalProperties.lookup("thermalStress"));

    if (thermalStress)
    {
        dimensionedScalar alpha(thermalProperties.lookup("alpha"));
        dimensionedScalar threeKalpha = threeK*alpha;

        const fvPatchField<scalar>& T =
            patch().lookupPatchField<volScalarField, scalar>("T");

        gradient() += n*threeKalpha.value()*T/twoMuLambda;
    }

    fixedGradientFvPatchVectorField::updateCoeffs();
}
// Update the coefficients associated with the patch field
void tractionDisplacementCorrectionFvPatchVectorField::updateCoeffs()
{
    if (updated())
    {
        return;
    }

    const dictionary& mechanicalProperties = db().lookupObject<IOdictionary>
    (
        "mechanicalProperties"
    );

    const fvPatchField<scalar>& rho =
        patch().lookupPatchField<volScalarField, scalar>("rho");

    const fvPatchField<scalar>& rhoE =
        patch().lookupPatchField<volScalarField, scalar>("E");

    const fvPatchField<scalar>& nu =
        patch().lookupPatchField<volScalarField, scalar>("nu");

    scalarField E(rhoE/rho);
    scalarField mu(E/(2.0*(1.0 + nu)));
    scalarField lambda(nu*E/((1.0 + nu)*(1.0 - 2.0*nu)));

    Switch planeStress(mechanicalProperties.lookup("planeStress"));

    if (planeStress)
    {
        lambda = nu*E/((1.0 + nu)*(1.0 - nu));
    }

    vectorField n(patch().nf());

    const fvPatchField<symmTensor>& sigmaD =
        patch().lookupPatchField<volSymmTensorField, symmTensor>("sigmaD");

    const fvPatchField<tensor>& sigmaExp =
        patch().lookupPatchField<volTensorField, tensor>("sigmaExp");

    gradient() =
    (
        (traction_ + pressure_*n)/rho - (n & (sigmaD + sigmaExp))
    )/(2.0*mu + lambda);

    fixedGradientFvPatchVectorField::updateCoeffs();
}
void fixedTractionFvPatchVectorField::updateCoeffs()
{
    if (updated())
    {
        return;
    }

    const dictionary& materialProperties =
        db().lookupObject<IOdictionary>("materialProperties");

    dimensionedScalar E(materialProperties.lookup("E"));
    dimensionedScalar nu(materialProperties.lookup("nu"));

    dimensionedScalar mu = E/(2.0*(1.0 + nu));
    dimensionedScalar lambda = nu*E/((1.0 + nu)*(1.0 - 2.0*nu));

    Switch planeStress(materialProperties.lookup("planeStress"));

    if (planeStress)
    {
        lambda = nu*E/((1.0 + nu)*(1.0 - nu));
    }

    scalar twoMuLambda = (2*mu + lambda).value();

    vectorField n = patch().nf(); //Unit normal

    const fvPatchField<symmTensor>& sigmaD =
        patch().lookupPatchField<volSymmTensorField, symmTensor>("sigmaD");

    const fvPatchField<scalar>& p = 
	patch().lookupPatchField<volScalarField, scalar>("p");

    scalar T = 3.0;
    vectorField trac = traction_;//*sin((2.0*constant::mathematical::pi/T)*(this->db().time().value()));
    scalarField pres = max(pressure_,pressure_*this->db().time().value());

    gradient() =
    (
        (trac + pres*n)
      + twoMuLambda*fvPatchField<vector>::snGrad() - (n & sigmaD) - p*n
    )/twoMuLambda;

    fixedGradientFvPatchVectorField::updateCoeffs();
}
// Return second Lame's coefficient
tmp<volScalarField> constitutiveModel::lambda
(
    const volScalarField& epsilonEq
) const
{
    volScalarField lawE = rheologyLawPtr_->E(epsilonEq);
    volScalarField lawNu = rheologyLawPtr_->nu();

    if (planeStress())
    {
        return tmp<volScalarField>
        (
            new volScalarField
            (
                IOobject
                (
                    "lambda",
                    sigma_.time().timeName(),
                    sigma_.db(),
                    IOobject::NO_READ,
                    IOobject::NO_WRITE
                ),
                lawNu*lawE/((1.0 + lawNu)*(1.0 - lawNu))
            )
        );
    }
    else
    {
        return tmp<volScalarField>
        (
            new volScalarField
            (
                IOobject
                (
                    "lambda",
                    sigma_.time().timeName(),
                    sigma_.db(),
                    IOobject::NO_READ,
                    IOobject::NO_WRITE
                ),
                lawNu*lawE/((1.0 + lawNu)*(1.0 - 2.0*lawNu))
            )
        );
    }
}
// Return threeK
tmp<volScalarField> constitutiveModel::threeK() const
{
    volScalarField lawRho = rheologyLawPtr_->rho();
    volScalarField lawE = rheologyLawPtr_->E();
    volScalarField lawNu = rheologyLawPtr_->nu();

    if (planeStress())
    {
        return tmp<volScalarField>
        (
            new volScalarField
            (
                IOobject
                (
                    "threeK",
                    sigma_.time().timeName(),
                    sigma_.db(),
                    IOobject::NO_READ,
                    IOobject::NO_WRITE
                ),
                lawE/(lawRho*(1 - lawNu))
            )
        );
    }
    else
    {
        return tmp<volScalarField>
        (
            new volScalarField
            (
                IOobject
                (
                    "threeK",
                    sigma_.time().timeName(),
                    sigma_.db(),
                    IOobject::NO_READ,
                    IOobject::NO_WRITE
                ),
                lawE/(lawRho*(1 - 2*lawNu))
            )
        );
    }
}
void Foam::tractionDisplacementFvPatchVectorField::updateCoeffs()
{
    if (updated())
    {
        return;
    }

    const dictionary& mechanicalProperties =
        db().lookupObject<IOdictionary>("mechanicalProperties");

    const dictionary& thermalProperties =
        db().lookupObject<IOdictionary>("thermalProperties");


    const fvPatchField<scalar>& rho =
        patch().lookupPatchField<volScalarField, scalar>("rho");

    const fvPatchField<scalar>& rhoE =
        patch().lookupPatchField<volScalarField, scalar>("E");

    const fvPatchField<scalar>& nu =
        patch().lookupPatchField<volScalarField, scalar>("nu");

    scalarField E(rhoE/rho);
    scalarField mu(E/(2.0*(1.0 + nu)));
    scalarField lambda(nu*E/((1.0 + nu)*(1.0 - 2.0*nu)));
    scalarField threeK(E/(1.0 - 2.0*nu));

    Switch planeStress(mechanicalProperties.lookup("planeStress"));

    if (planeStress)
    {
        lambda = nu*E/((1.0 + nu)*(1.0 - nu));
        threeK = E/(1.0 - nu);
    }

    scalarField twoMuLambda(2*mu + lambda);

    vectorField n(patch().nf());

    const fvPatchField<symmTensor>& sigmaD =
        patch().lookupPatchField<volSymmTensorField, symmTensor>("sigmaD");

    gradient() =
    (
        (traction_ - pressure_*n)/rho
      + twoMuLambda*fvPatchField<vector>::snGrad() - (n & sigmaD)
    )/twoMuLambda;

    Switch thermalStress(thermalProperties.lookup("thermalStress"));

    if (thermalStress)
    {
        const fvPatchField<scalar>&  threeKalpha=
            patch().lookupPatchField<volScalarField, scalar>("threeKalpha");

        const fvPatchField<scalar>& T =
            patch().lookupPatchField<volScalarField, scalar>("T");

        gradient() += n*threeKalpha*T/twoMuLambda;
    }

    fixedGradientFvPatchVectorField::updateCoeffs();
}