volume of element

Unknown
edited June 7 in Community Q&A

I have been able to get the volume of single element (both in serial and parallel mode with 8 cores.) I used the code as mentioned in the above link. The following code works very well both in series and parallel. I found that wDetJ is 1/8 th of volume of single element. To find the volume of an element, I needed to multiply by 8 (most probably there are 8 gauss points).

Real* wghtDetJac ; Real wDetJ ; Integer elem ; ... wghtDetJac = udfGetElmWDetJ( udfHd ) ; for ( elem = 0 ; elem < nItems ; elem++ ) {   wDetJ = wghtDetJac[elem] ;  ... }

I have a simple geometry as below. It is 1m x 1m x 1m with (10 x 10 x 1) elements:- 

image

Now, the issue I am having is that I have marker (0-fluid; 1-solid) for each element in the domain above. I want to run a code to calculate the volume of only fluid (i.e marker with 0). I wrote a code that does this. It works very well in series (only 1 core). But, I found when I try to run the same code in parallel (multi cores with 8 cores), wDetJ is correct. But, the total volume (vol) corresponding to 0 marker is not correct in parallel mode--it is correct only in series mode. Would you please help me figure out how to evaluate the volume for the 0 marker only in parallel mode? I figured out that UDF is called several times even in each timestep due to parallelization. The code I ran is:

Integer timeStep ;
Integer firstCall ;
static Integer mytimestep ;
firstCall = udfFirstCall( udfHd ) ;
Real dens ;

/* volume of an element */
Real* wghtDetJac ;
Real wDetJ ;
wghtDetJac = udfGetElmWDetJ( udfHd ) ;

static Real vol ;
if (firstCall ==1)
{
vol = 0.0 ;
 
for ( elem =0 ; elem < nItems ; elem++ ) {
 
outVec[elem] =0 ;

if (dens ==0) // fluid region
{
wDetJ = wghtDetJac[elem] ;
udfPrintMessPrim( udfHd, "wDetJ=%0.12f\t nItems=%d\n", wDetJ, nItems) ;
vol += wDetJ*8;
}

FILE* fpv = fopen("volume.txt", "w");
fprintf(fpv, "%0.12f\n%0.12f\n%d\n%d\n", vol, wDetJ*8, nItems);
fclose(fpv);
}
}

Answers

  • Michel Tanguay_22100
    Michel Tanguay_22100
    Altair Employee
    edited June 7

    Hi,

    If you are mainly interested in integrating an indicator function over a volume, the simplest approach would be to an ELEMENT_OUTPUT command. This will automatically integrate a bunch of things for you (both in parallel and single processing). If the indicator is a species or field then you don’t have to do anything else.

    image

    To visualize the output, you can use acuProbe or depending on the GUI tool you are using, whatever you are currently using to visualize the residuals. If you want to directly get a table of data, then you can use “acuTrans -oei -to table” which will dump everything in files. You can limit the output with “-oeis name” to select which volume to output and “-oeiv species” just to get the indicator scalar.

     

    If you are looking for something a bit more complicated such as having a UDF calculating the quantity of interest, you can set the ELEMENT_OUTPUT to run the UDF.

    Input file:
    #==============================================================
    # Element Output
    #==============================================================
    ELEMENT_OUTPUT( "ElementOutput_3" ) {
        element_set                         = "Box1"
        type                                = all
        integrated_output_frequency         = 1.0
        num_user_output                     = 1
        user_function               = "usrOutput"
    }

     

    UDF:

    #include "acusim.h"
    #include "udf.h"
    UDF_PROTOTYPE(usrOutput) ;
    Void usrOutput (
            UdfHd   udfHd, /* Opaque handle for accessing data  */
            Real*   outVec, /* Output vector                     */
            Integer nItems, /* Number of items in outVec         */
            Integer vecDim /* Vector dimension of outVec        */
    ) {
    Integer i;
    Real *crd;
      Real *spec;

      crd = udfGetElmCrd(udfHd);
    spec = udfGetElmData(udfHd, UDF_ELM_SPECIES);

    for(i=0;i<nItems;i++) {

       if( spec[i] >0 )
         outVec[i] = 1.0;
       else
         outVec[i] = 0.0;
    }
    } /* end of usrOutput() */


    Note that for ELEMENT_OUTPUT, the integration over the different sub-domains is handled directly by AcuSolve and you don’t need to worry about the quadrature weight.

    If you need to access the result from inside the solver (like a source term dependent on it), then you can the values you need via the udfGetOeiData function.

    I hope this helps.

    Cheers.