//==============
        // Heat equation
        //==============

        public static void AddSpeciesHeatEq(XSpatialOperatorMk2 XOp, IHeat_Configuration config, int D,
                                            string spcName, SpeciesId spcId, ThermalMultiphaseBoundaryCondMap BcMap, LevelSetTracker LsTrk)
        {
            // check input
            if (XOp.IsCommited)
            {
                throw new InvalidOperationException("Spatial Operator is already comitted. Adding of new components is not allowed");
            }

            string CodName = EquationNames.HeatEquation;

            if (!XOp.CodomainVar.Contains(CodName))
            {
                throw new ArgumentException("CoDomain variable \"" + CodName + "\" is not defined in Spatial Operator");
            }

            if (config.getConductMode != ConductivityInSpeciesBulk.ConductivityMode.SIP)
            {
                foreach (string cn in EquationNames.AuxHeatFlux(D))
                {
                    if (!XOp.CodomainVar.Contains(cn))
                    {
                        throw new ArgumentException("CoDomain variable \"" + cn + "\" is not defined in Spatial Operator");
                    }
                }
            }

            ThermalParameters    thermParams = config.getThermParams;
            DoNotTouchParameters dntParams   = config.getDntParams;

            // set species arguments
            double capSpc, LFFSpc, kSpc;

            switch (spcName)
            {
            case "A": { capSpc = thermParams.rho_A * thermParams.c_A; LFFSpc = dntParams.LFFA; kSpc = thermParams.k_A; break; }

            case "B": { capSpc = thermParams.rho_B * thermParams.c_B; LFFSpc = dntParams.LFFB; kSpc = thermParams.k_B; break; }

            default: throw new ArgumentException("Unknown species.");
            }

            // set components
            var comps = XOp.EquationComponents[CodName];


            // convective part
            // ================
            if (thermParams.IncludeConvection)
            {
                IEquationComponent conv;
                if (config.useUpwind)
                {
                    conv = new HeatConvectionInSpeciesBulk_Upwind(D, BcMap, spcName, spcId, capSpc);
                }
                else
                {
                    conv = new HeatConvectionInSpeciesBulk_LLF(D, BcMap, spcName, spcId, capSpc, LFFSpc, LsTrk);
                }

                comps.Add(conv);
            }


            // viscous operator (laplace)
            // ==========================
            if (config.getConductMode == ConductivityInSpeciesBulk.ConductivityMode.SIP)
            {
                double penalty = dntParams.PenaltySafety;

                var Visc = new ConductivityInSpeciesBulk(
                    dntParams.UseGhostPenalties ? 0.0 : penalty, 1.0,
                    BcMap, D, spcName, spcId, thermParams.k_A, thermParams.k_B);

                comps.Add(Visc);

                if (dntParams.UseGhostPenalties)
                {
                    var ViscPenalty = new ConductivityInSpeciesBulk(penalty * 1.0, 0.0, BcMap, D,
                                                                    spcName, spcId, thermParams.k_A, thermParams.k_B);
                    XOp.GhostEdgesOperator.EquationComponents[CodName].Add(ViscPenalty);
                }
            }
            else
            {
                comps.Add(new HeatFluxDivergenceInSpeciesBulk(D, BcMap, spcName, spcId));
                //if (config.getConductMode == ConductivityInSpeciesBulk.ConductivityMode.LDGstabi)
                //    comps.Add(new AuxiliaryStabilizationForm(D, BcMap, spcName, spcId));

                for (int d = 0; d < D; d++)
                {
                    comps = XOp.EquationComponents[EquationNames.AuxHeatFluxComponent(d)];

                    comps.Add(new AuxiliaryHeatFlux_Identity(d, spcName, spcId));   // cell local
                    comps.Add(new TemperatureGradientInSpeciesBulk(D, d, BcMap, spcName, spcId, kSpc));
                    //if (config.getConductMode == ConductivityInSpeciesBulk.ConductivityMode.LDGstabi)
                    //    comps.Add(new TemperatureStabilizationForm(d, BcMap, spcName, spcId));
                }
            }
        }
        public static void AddInterfaceHeatEq(XSpatialOperatorMk2 XOp, IXHeat_Configuration config, int D,
                                              ThermalMultiphaseBoundaryCondMap BcMap, LevelSetTracker LsTrk)
        {
            // check input
            if (XOp.IsCommited)
            {
                throw new InvalidOperationException("Spatial Operator is already comitted. Adding of new components is not allowed");
            }

            string CodName = EquationNames.HeatEquation;

            if (!XOp.CodomainVar.Contains(CodName))
            {
                throw new ArgumentException("CoDomain variable \"" + CodName + "\" is not defined in Spatial Operator");
            }

            if (config.getConductMode != ConductivityInSpeciesBulk.ConductivityMode.SIP)
            {
                foreach (string cn in EquationNames.AuxHeatFlux(D))
                {
                    if (!XOp.CodomainVar.Contains(cn))
                    {
                        throw new ArgumentException("CoDomain variable \"" + cn + "\" is not defined in Spatial Operator");
                    }
                }
            }

            ThermalParameters    thermParams = config.getThermParams;
            DoNotTouchParameters dntParams   = config.getDntParams;

            // set species arguments
            double capA = thermParams.rho_A * thermParams.c_A;
            double LFFA = dntParams.LFFA;
            double kA   = thermParams.k_A;

            double capB = thermParams.rho_B * thermParams.c_B;
            double LFFB = dntParams.LFFB;
            double kB   = thermParams.k_B;

            double Tsat = thermParams.T_sat;

            // set components
            var comps = XOp.EquationComponents[CodName];


            // convective part
            // ================
            if (thermParams.IncludeConvection)
            {
                ILevelSetForm conv;
                conv = new HeatConvectionAtLevelSet_LLF(D, LsTrk, capA, capB, LFFA, LFFB, BcMap, config.isMovingMesh, Tsat);
                //conv = new HeatConvectionAtLevelSet_WithEvaporation(D, LsTrk, LFFA, LFFB, thermParams, config.getPhysParams.Sigma);
                //conv = new HeatConvectionAtLevelSet_Upwind(D, LsTrk, capA, capB, thermParams, config.isMovingMesh, config.isEvaporation, Tsat);

                comps.Add(conv);
            }


            // viscous operator (laplace)
            // ==========================
            if (config.getConductMode == ConductivityInSpeciesBulk.ConductivityMode.SIP)
            {
                double penalty = dntParams.PenaltySafety;

                var Visc = new ConductivityAtLevelSet(LsTrk, kA, kB, penalty * 1.0, Tsat);
                comps.Add(Visc);

                var qJump = new HeatFluxAtLevelSet(D, LsTrk, thermParams, config.getPhysParams.Sigma);
                comps.Add(qJump);
            }
            else
            {
                comps.Add(new HeatFluxDivergencetAtLevelSet(LsTrk));
                //if(config.getConductMode == ConductivityInSpeciesBulk.ConductivityMode.LDGstabi)
                //    comps.Add(new AuxiliaryStabilizationFormAtLevelSet(LsTrk, config.isEvaporation));

                for (int d = 0; d < D; d++)
                {
                    comps = XOp.EquationComponents[EquationNames.AuxHeatFluxComponent(d)];

                    comps.Add(new TemperatureGradientAtLevelSet(d, LsTrk, kA, kB, Tsat));
                    //if (config.getConductMode == ConductivityInSpeciesBulk.ConductivityMode.LDGstabi)
                    //    comps.Add(new TemperatureStabilizationFormAtLevelSet(d, LsTrk, kA, kB, config.isEvaporation, Tsat));
                }
            }
        }