Hello Dumux,

I tried to calculate the fluxes over a certain part of the boundary of the 
model domain. For this purpose I used an ElementIterator to iterate over the 
elements of the grid. In each element I iterate over the intersections and in 
each intersection over the vertices. With information from the 
IntersectionIterator and the vertex index I can get the boundary face index and 
the boundary face position. I test whether I am at the desired location on the 
grid and then calculate the local residual of the corresponding element. This 
works just fine.
The idea was to use the computeFlux-function of the local residual afterwards 
with the corresponding boundary face index and onBoundary=true to get the flux 
over the boundary. However, this will not work because the fluidState is not 
defined when the local fluxVariables are constructed and this will cause 
Valgrind to complain.
To me it came as a surprise that it is not possible to use the 
computeFlux-function outside the localresidual since this is quite an important 
quantity to access when traversing the grid. I see that several people have 
tried just the same approach but commented the code afterwards, probably for 
the reasons mentioned above. The workaround which was used instead is to 
locally construct the fluxVariables of the element and then do just the same 
flux calculation as in the localresidual. This way, one is forced to copy code 
and have code which does exactly the same in two different locations. I think 
this should be improved and the fluxes over the interfaces should be readily 
available when iterating over the grid.
The solution to this problem would be to add a second computeFlux-function to 
the local residual. This function would get all the parameters needed for the 
flux calculation without the need to touch the private functions of the local 
residual. This would be a public version of computeFlux (the current 
computeFlux function is private in nature since it can't be called outside the 
local residual without causing problems and maybe should be set private for 
consistency).
I believe the problem is the same for all (implicit) models. I attached my code 
which is specific to my multidomain/fuel cell model. The first function is 
called in the multidomain problem. The computeFlux-Function is part of the 
localresidual.
These are just some ideas. Please let me know what you think.

Best regards

Georg Futter

--------------------------
German Aerospace Center (DLR)
Institute of Engineering Thermodynamics | Computational Electrochemistry | 
Pfaffenwaldring 38-40 | 70569 Stuttgart

Dipl.-Ing. Georg Futter | Ph.D. student
Telefon 0711/6862-8135 | [email protected]<mailto:[email protected]>
www.DLR.de<http://www.dlr.de/>


    /*!
     * \brief Calculates the electrical current density per cell area
     *        from the fluxes at the anode current collector [A/m^2].
     */
    void calculateAnodeCurrentDensityFromFlux()
    {
        anodeCurrentDensityFromFlux_ = 0.0;

        FVElementGeometry1 fvGeometry1;
        ElementVolumeVariables1 elemVolVars1;
        PrimaryVariables1 flux(0.0);

        ElementIterator1 eIt1 = this->sdGridView1().template begin<0>();
        ElementIterator1 eEndIt1 = this->sdGridView1().template end<0>();
        for (; eIt1 != eEndIt1; ++eIt1)
        {
            fvGeometry1.update(this->sdGridView1(), *eIt1);

            elemVolVars1.update(this->sdProblem1(),
                                *eIt1,
                                fvGeometry1,
                                /*oldSol=*/false);

            typedef Dune::ReferenceElements<Scalar, dim> ReferenceElements;
            typedef Dune::ReferenceElement<Scalar, dim> ReferenceElement;
            const ReferenceElement &refElement = 
ReferenceElements::general(eIt1->geometry().type());

            IntersectionIterator1 isIt1 = this->sdGridView1().ibegin(*eIt1);
            const IntersectionIterator1 &endIt1 = 
this->sdGridView1().iend(*eIt1);
            for (; isIt1 != endIt1; ++isIt1)
            {
                // handle only intersections on the boundary
                if (!isIt1->boundary())
                    continue;

                // assemble the boundary for all vertices of the current face
                const int fIdx = isIt1->indexInInside();
                const int numFaceVertices = refElement.size(fIdx, 1, dim);

                // loop over the single vertices on the current face
                for (int faceVertexIdx = 0; faceVertexIdx < numFaceVertices; 
++faceVertexIdx)
                {
                    const int boundaryFaceIdx = 
fvGeometry1.boundaryFaceIndex(fIdx, faceVertexIdx);
                    GlobalPosition globalPos = 
fvGeometry1.boundaryFace[boundaryFaceIdx].ipGlobal;

                    if(fcGeometry_.atAnodeCurrentCollectorTest(globalPos))
                    {
                        this->localResidual1().computeFlux(flux,
                                                           this->sdProblem1(),
                                                           *eIt1,
                                                           fvGeometry1,
                                                           boundaryFaceIdx,
                                                           elemVolVars1,
                                                           /*onBoundary=*/ 
true);

                        anodeCurrentDensityFromFlux_ += flux[elecChargeEqIdx1]; 
// A
                    }
                } // loop over vertices
            } // loop over intersections
        } // loop over elements

        anodeCurrentDensityFromFlux_ /= fcGeometry_.cellArea(); // --> A/m^2
    }



    /*!
     * \brief Evaluates the total flux of all conservation quantities
     *        over a face of a subcontrol volume.
     *
     * \param flux The flux over the SCV (sub-control-volume) face for each 
component
     * \param problem The problem
     * \param element The element
     * \param fvGeometry The geometry of the element
     * \param fIdx The index of the SCV face
     * \param elemVolVarsCur The current element volume variables
     * \param onBoundary A boolean variable to specify whether the flux 
variables
     *        are calculated for interior SCV faces or boundary faces, 
default=false
     */
    void computeFlux(PrimaryVariables &flux,
                     const Problem &problem,
                     const Element &element,
                     const FVElementGeometry &fvGeometry,
                     const unsigned int fIdx,
                     const ElementVolumeVariables &elemVolVarsCur,
                     const bool onBoundary=false) const
    {
        FluxVariables fluxVars(problem,
                               element,
                               fvGeometry,
                               fIdx,
                               elemVolVarsCur,
                               onBoundary);

        flux = 0.0;
        MassResid::computeFlux(flux, fluxVars, elemVolVarsCur);
        Valgrind::CheckDefined(flux);
/*
 *      EnergyResid also called in the MassResid
 *      1) Makes some sense because energy is also carried by mass
 *      2) The component-wise mass flux in each phase is needed.
 */
        const GlobalPosition globalPos = 
fvGeometry.subContVolFace[fIdx].ipGlobal;

        ChargeResid::computeFlux(flux, fluxVars, elemVolVarsCur, globalPos);
        Valgrind::CheckDefined(flux);
    }
_______________________________________________
Dumux mailing list
[email protected]
https://listserv.uni-stuttgart.de/mailman/listinfo/dumux

Reply via email to