PBC in multi-direction

Hello,

I’m wondering that is it possible to apply the periodic boundary condition in more that one direction using DOLFINX_MPC, for example, if I have f(x,y) in [0,1]*[0,1] and I want f(0,y) = f(1,y) and f(x,0)=f(x,1).

In this case, it seems like some master point will the master for more than 1 slave points, can we difine one MPC directly, or we have to define the boundary condition in different direction speratly and apply them one by one.

Is there any demos or instruction about that? Thanks very much!

See Periodic BC in dolfinx - #10 by welahi
(More or less the whole set of posts discussed this aspect )

Thanks for quick reply!

But I’m still confused about one point that you mentioned in that post. Why do we have to constraint some DOFs twice?

For example, consider an unit square, if we know that one dof is on the right-upp corner, can we just connect it to the left-down dof directly instead of using a nest (I think this is what we did in the old DOLFIN). In this case, all the dofs will only be slaves for up to once, and some dofs will be the master for mutiple times. It there any reason preventing doing this?

You should not constrain dofs twice in dolfinx_mpc. The goal of that referenced post is to only constrain any dof once.

Note that dolfinx_mpc does more general constraints than legacy dolfin, where u_i=u_j where the only possible constraint.

You could consider this official demo.
In 2D, the mapping is done as follows: (1) from right to left, (2) from top to bottom, in each case without mapping the corner of master-master surfaces (top right corner) and (3) mapping the top right corner to the bottom left corner.

2 Likes

OK, I see, so I gusee the main problem is that the dofs at the corner should only be constrainted once?

But can we do just:

pbc = dolfinx_mpc::create_periodic_condition_geometrical(V, periodic_condition, periodic_relation, {}, 1, false);

where

std::vector<std::int8_t> periodic_condition(std::experimental::mdspan<const double, std::experimental::extents<std::size_t, 3, std::experimental::dynamic_extent>> x)
{
  std::vector<std::int8_t> f;
  for(std::size_t p = 0;p < x.extent(1);++p)
  {
    f.push_back((std::abs(x(0,p)-1.0)<1e-6) || (std::abs(x(1,p)-1.0)<1e-6));
  }
  return f;
}

std::vector<double> periodic_relation(std::span<const double> x)
{
  std::vector<double> y(x.size(), 0.0);
  std::size_t len = x.size() / 3;

  for(std::size_t i = 0; i < len; i++)
  {
    if((std::abs(x[i]-1.0) < 1e-6)&&(std::abs(x[i+len]-1.0) < 1e-6))
    {
      y[i] = x[i] - 1.0;
      y[i+len] = x[i+len]-1.0;
      y[i+2*len] = x[i+2*len];
    }
    else if(std::abs(x[i]-1.0) < 1e-6)
    {
      y[i] = x[i] - 1.0;
      y[i+len] = x[i+len];
      y[i+2*len] = x[i+2*len];
    }
    else
    {
      y[i] = x[i];
      y[i+len] = x[i+len] - 1.0;
      y[i+2*len] = (zmax+zmin)-x[i+2*len];
    }
  }
  return y;
}

In this case, the right-upp dof will only be constrainted once, is that true? Of course, my mesh is not complicated, it is just grid.

As you are in C++ I guess you could do it like this. This would be rather expensive to do in Python.

1 Like