Dear Timo,


addRobinFluxDerivatives() is only needed if you want to implement an exact / analytical Jacobian matrix for your problem. In the default setting DuMux computes the Jacobian using numerical differentiation and doesn’t need any user-implemented derivatives.

I am having trouble now with Newton method not converging sometimes. The convergence depends on the grid size and on the influx input parameter, and I am suspecting the numerical differentiation may be the cause. I played with Assembly.NumericDifference.BaseEpsilon parameter, to no avail.

So I decided to check out the analytical addRobinFluxDerivatives(). I created a MyLocalResidual class, inherited from TwoPIncompressibleLocalResidual, and implemented addRobinFluxDerivatives() method in it. I also use Assembler = FVAssembler<TypeTag, DiffMethod::analytic> instead of DiffMethod::numeric, of course.

The program compiles, and does call my method, but the solution diverges dramatically. I checked the derivatives against ones that I calculated numerically, and they are fine, to my understanding anyway. I suspect that maybe I miss something about the units of the derivatives that addRobinFluxDerivatives is supposed to add.

I supposed that I should calculate the derivatives of the fluxes (in kg / m^2 * s, as they are calculated by neumann()) w. r. t. the wetting phase pressure (Pa) and nonwetting phase saturation. Am I correct?

The code snippet is given below for convenience.


    template<class PartialDerivativeMatrices>

    void addRobinFluxDerivatives(PartialDerivativeMatrices& derivativeMatrices,
                                 const Problem& problem,
                                 const Element& element,
                                 const FVElementGeometry& fvGeometry,
                                 const ElementVolumeVariables& curElemVolVars,                                  const ElementFluxVariablesCache& elemFluxVarsCache,
                                 const SubControlVolumeFace& scvf) const
    {
      const auto insideScvIdx = scvf.insideScvIdx();
      const auto& globalPos = scvf.ipGlobal();
      auto ccGlobalPos = element.geometry().center();
      auto& dI_dI = derivativeMatrices[insideScvIdx];

      if (globalPos[0] > problem.bBoxMax()[0] - Problem::eps_) {
        const MaterialLawParams& mlp = problem.spatialParams().materialLawParamsAtPos(ccGlobalPos);
        const auto& volVars = curElemVolVars[scvf.insideScvIdx()];
        Scalar pw = volVars.pressure(0);
        Scalar sw = volVars.saturation(0);
        Scalar krw = MaterialLaw::krw(mlp, sw);
        Scalar krn = MaterialLaw::krn(mlp, sw);
        const auto& insideScv = fvGeometry.scv(insideScvIdx);
        auto dKrw_dSn = -1.0*MaterialLaw::dkrw_dsw(mlp, sw);
        auto dKrn_dSn = -1.0*MaterialLaw::dkrn_dsw(mlp, sw);
        Scalar gradp = (problem.pwAtBoundary_ - pw) / (globalPos[0] - ccGlobalPos[0]);
        Scalar dgradp_dpw = - 1.0 / (globalPos[0] - ccGlobalPos[0]);
        FieldMatrix K = problem.spatialParams().permeabilityAtPos(ccGlobalPos);

        dI_dI[0][Indices::pressureIdx]   += - volVars.density(0) * volVars.mobility(0) * K[0][0] * dgradp_dpw;         dI_dI[0][Indices::saturationIdx] += - volVars.density(0) * dKrw_dSn / volVars.fluidState().viscosity(0) * K[0][0] * gradp;         dI_dI[1][Indices::pressureIdx]   += - volVars.density(1) * volVars.mobility(1) * K[0][0] * dgradp_dpw;         dI_dI[1][Indices::saturationIdx] += - volVars.density(1) * dKrn_dSn / volVars.fluidState().viscosity(1) * K[0][0] * gradp;

      }
    }


The corresponding code snippet from neumann () is:

        const auto& volVars = elemVolVars[scvf.insideScvIdx()];
        auto ccGlobalPos = element.geometry().center();

        FieldMatrix K = this->spatialParams().permeabilityAtPos(ccGlobalPos);
        Scalar pw = volVars.pressure(0);

        Scalar dp_dn = (pwAtBoundary_ - pw) / (globalPos[0] - ccGlobalPos[0]);

        values[0] = - volVars.density(0) * volVars.mobility(0) * K[0][0] * dp_dn;         values[1] = - volVars.density(1) * volVars.mobility(1) * K[0][0] * dp_dn;


Best regards,

Dmitry


_______________________________________________
Dumux mailing list
Dumux@listserv.uni-stuttgart.de
https://listserv.uni-stuttgart.de/mailman/listinfo/dumux

Reply via email to