# Calculating Average of Variable at Periodic Boundary

**URL:** <https://pyfr.discourse.group/t/calculating-average-of-variable-at-periodic-boundary/1343>\
**Category:** Development\
**Created:** [23 February 2026 09:59 UTC](https://pyfr.discourse.group/t/calculating-average-of-variable-at-periodic-boundary/1343 "2026-02-23T09:59:19Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![fredmorin18](https://yyz2.discourse-cdn.com/free1/user_avatar/pyfr.discourse.group/fredmorin18/32/755_2.png) [@fredmorin18](https://pyfr.discourse.group/u/fredmorin18)\
**Post date:** [23 February 2026 09:59 UTC](https://pyfr.discourse.group/t/calculating-average-of-variable-at-periodic-boundary/1343/1 "2026-02-23T09:59:20Z")

</div>

Hello,

I’ve been able to split the periodic faces from the rest of the internal faces, and I use a class similar to the internal interfaces class to handle the periodic interfaces and some mako kernels to decouple the fluxes for select scalars. I’d now like to calculate the average on the LHS and RHS of the periodic boundary in order to make some control loops, but I can’t seem to figure out how to do this from the internal interface classes.

Is there a way to access the solution from the internal interface classes so I can take an integral, similar to in the plugins or BC interfaces? My first thought was to create a class similar to `MassFlowBCMixin` to do this, but the implementation has proven quite cumbersome.

I’d appreciate any help 🙂

Fred

---

<div class="post-metadata">

**Author:** ![fdw](https://avatars.discourse-cdn.com/v4/letter/f/a587f6/32.png) [@fdw](https://pyfr.discourse.group/u/fdw)\
**Post date:** [23 February 2026 12:36 UTC](https://pyfr.discourse.group/t/calculating-average-of-variable-at-periodic-boundary/1343/2 "2026-02-23T12:36:41Z")

</div>

You will need to do what the mass flow controller boundary condition does. Only difference is what you’ll pass in as the surface list.

Regards, Freddie.

---

<div class="post-metadata">

**Author:** ![fredmorin18](https://yyz2.discourse-cdn.com/free1/user_avatar/pyfr.discourse.group/fredmorin18/32/755_2.png) [@fredmorin18](https://pyfr.discourse.group/u/fredmorin18)\
**Post date:** [24 February 2026 17:28 UTC](https://pyfr.discourse.group/t/calculating-average-of-variable-at-periodic-boundary/1343/3 "2026-02-24T17:28:07Z")

</div>

The averaging over the periodic surface is working now 🙂

My next issue is that I can’t seem to be able to pass an external value to the kernels.

I attempted to replicate what was done here (and something similar worked for a plugin I made a while ago), but it throws “invalid argument specification”

> [@Expressions for boundary condition as a function of neural-network outputs](https://pyfr.discourse.group/t/expressions-for-boundary-condition-as-a-function-of-neural-network-outputs/1189):
>
> Hi, I am trying to reproduce [a study](https://www.cambridge.org/core/journals/journal-of-fluid-mechanics/article/artificial-neural-networks-trained-through-deep-reinforcement-learning-discover-control-strategies-for-active-flow-control/D5B80D809DFFD73760989A07F5E11039) of active flow control of the flow over a 2D cylinder with 2 jets positioned at ±90 degrees. I am solving the compressible NS equations for now. As a start, I set the boundary conditions for the jet as, for example, [soln-bcs-jet\_top] type = sub-in-frv theta = atan2(y,x) ; theta, not used for now omega = 10\*pi/180 ; jet width in radians theta0\_top = 90\*pi/180 ; center of jet R = 0.5 ; radius of cylinder rho = rhoc u = 0.09 / (%(omega)s\*%(R)s\*%(R)s) \* x v = …

My class is similar to the MassFlowBC one, and is structured as follows (I only want to use the external value in the `comm_flux` kernel):

```auto
class ACNavierStokesPintInters(ScalarPeriodic, BaseAdvectionDiffusionIntInters):
    def __init__ (self, be, lhs, rhs, elemap, cfg):
        super(). __init__ (be, lhs, rhs, elemap, cfg)

        # Pointwise template arguments
        rsolver = self.cfg.get('solver-interfaces', 'riemann-solver')
        tplargs = dict(ndims=self.ndims, nvars=self.nvars, rsolver=rsolver,
                       c=self.c)
                       
        kprefix = 'pyfr.solvers.acnavstokes.kernels'
        self._be.pointwise.register(f'{kprefix}.pintconu')
        self._be.pointwise.register(f'{kprefix}.pintcflux')
        
        self.kernels['con_u'] = lambda: self._be.kernel(
            'pintconu', tplargs=tplargs, dims=[self.ninterfpts],
            ulin=self._scal_lhs, urin=self._scal_rhs,
            ulout=self._comm_lhs, urout=self._comm_rhs
        )
        self.kernels['comm_flux'] = lambda: self._be.kernel(
            'pintcflux', tplargs=tplargs, dims=[self.ninterfpts],
            extrns=self._external_args, ul=self._scal_lhs, 
            ur=self._scal_rhs, gradul=self._vect_lhs, 
            gradur=self._vect_rhs, nl=self._pnorm_lhs
        )

```

and the relevant parts from the `ScalarPeriodic` class:

```auto
class ScalarPeriodic:
    def __init__ (self, be, lhs, rhs, elemap, cfg):
        super(). __init__ (be, lhs, rhs, elemap, cfg)
        
        self.cfgsect = f'scalar-periodic'
        self.name = f'periodic'
        
        # Setting the desired average value of scalar T
        self.T_sp = self.cfg.getfloat(self.cfgsect, 'T_avg', 1.0)
        
        # Controlling inlet (LHS) scalar avg
        self.cf = be.matrix((1, 1), tags={'align'})
        self.cf.set(np.full((1, 1), 1.0))
        self._set_external('cf', f'in broadcast fpdtype_t[1][1]', value=self.cf)
...

    @classmethod
    def preparefn(cls, pciface, mesh, elemap):
        if pciface:
            return pciface.prepare
        else:
            return None

    def prepare(self, system, ubank, t, kerns): 
        solns = dict(zip(system.ele_types, system.ele_scal_upts(ubank)))
        self.mT = self.calculate_scalar_avg(solns)
        self.cf.set(np.full((1, 1), self.T_sp / self.mT))

```

Finally, the mako kernel:

```auto
...
<%pyfr:kernel name='pintcflux' ndim='1' params='ul, ur, gradul, nl' externs='cf'>
...

```

When I had tried to use the bind method on a scalar like in the MassFlowBC class, it threw ‘PointwiseKernel’ object has no attribute ‘bind’ so I’m wondering if I did something wrong in my solvers/base/system.py file…

Can you see what I’m doing wrong at a glance?

Thank you,

Fred

---

<div class="post-metadata">

**Author:** ![fdw](https://avatars.discourse-cdn.com/v4/letter/f/a587f6/32.png) [@fdw](https://pyfr.discourse.group/u/fdw)\
**Post date:** [24 February 2026 17:34 UTC](https://pyfr.discourse.group/t/calculating-average-of-variable-at-periodic-boundary/1343/4 "2026-02-24T17:34:05Z")

</div>

Only scalar arguments require binding. In your case you’re using an array, so it doesn’t need to be rebound (the pointer remains constant). See the turbulent inflow plugin for an example of this—it never calls bind.

Regards, Freddie.

---

<div class="post-metadata">

**Author:** ![fredmorin18](https://yyz2.discourse-cdn.com/free1/user_avatar/pyfr.discourse.group/fredmorin18/32/755_2.png) [@fredmorin18](https://pyfr.discourse.group/u/fredmorin18)\
**Post date:** [25 February 2026 00:58 UTC](https://pyfr.discourse.group/t/calculating-average-of-variable-at-periodic-boundary/1343/5 "2026-02-25T00:58:26Z")

</div>

I got it working. The mako kernel compiler didn’t like missing the parameter definitions in the header when I tried adding the externs keyword. I figured out you can access external values without the using the externs keyword as long as you pass `extrns=self._external_args` to the kernel. I also forgot `gradur`, but that wasn’t the issue. For reference, the mako file header in the working version looks like this (i.e., no params or externs keywords):

```auto
<%pyfr:kernel name='pintcflux' ndim='1'
              ur='inout view fpdtype_t[${str(nvars)}]'
              ul='inout view fpdtype_t[${str(nvars)}]'
              gradul='in view fpdtype_t[${str(ndims)}][${str(nvars)}]'
              gradur='in view fpdtype_t[${str(ndims)}][${str(nvars)}]'
              nl='in fpdtype_t[${str(ndims)}]'>

```

I’m off to go run some cases now 🤠

Thank you for your help.

Fred
