FEM: Solving the heat conduction with 2D periodic condition

We have to use either NeumannValue[] or save the linear function in the pde as follows

(*Mesh*)Needs["NDSolve`FEM`"]
(*Periodic region with periods P*)

P = {10, 5};
Omega = Rectangle[{0, 0}, P];
centers = {{1.2, 2}, {6, 3}, {8.5, 1.5}};
Omegainc = RegionUnion[Disk[#, 1] & /@ centers];
Omegaemb = RegionDifference[Omega, Omegainc];
mesh = ToElementMesh[Omegaemb, "RegionHoles" -> None, 
   "RegionMarker" -> 
    Join[{#, 1, 0.05} & /@ centers, {{{0.1, 0.1}, 2, 0.5}}]];
{RegionPlot[{Omegainc, Omegaemb}, AspectRatio -> Automatic, 
  PlotLegends -> {"\[CapitalOmega]inc", "\[CapitalOmega]emb"}], 
 mesh["Wireframe"["MeshElementStyle" -> FaceForm /@ {Blue, Orange}]]}

(*Region dependent coefficient A(x)*)
Ainc = DiagonalMatrix@{100, 50};
Aemb = DiagonalMatrix@{1, 2};
A[x1_, x2_] := Boole[Element[{x1, x2}, Omegainc]] (Ainc - Aemb) + Aemb;

(*Boundary conditions*)eps = 10^-3;
bcD = DirichletCondition[v[x1, x2] == RandomReal[{-eps, eps}], 
   x1 == 0 && x2 == 0];
gt1 = FindGeometricTransform[{{0, 0}, {0, P[[2]]}}, {{P[[1]], 0}, 
     P}][[2]];
gt2 = FindGeometricTransform[{{0, 0}, {P[[1]], 0}}, {{0, P[[2]]}, 
     P}][[2]];
bcP = {PeriodicBoundaryCondition[v[x1, x2], 
    x1 == P[[1]] && 0 <= x2 <= P[[2]], gt1], 
   PeriodicBoundaryCondition[v[x1, x2], 
    x2 == P[[2]] && 0 <= x1 <= P[[1]], gt2]};

(*PDE with prescribed g*)
g = 3 x1 + x2;
pde = Inactive[Div][
     A[x1, x2].Inactive[Grad][v[x1, x2], {x1, x2}], {x1, x2}] + 
    Inactive[Div][A[x1, x2].Inactive[Grad][g, {x1, x2}], {x1, x2}] == 
   0;

(*Solve on mesh*)
vsol = NDSolveValue[{pde, bcP, bcD}, v, Element[{x1, x2}, mesh]]
(*Check periodictiy along edges and visualize solution*)
{Plot[vsol[x1, 0] - vsol[x1, P[[2]]], {x1, 0, P[[1]]}, 
  PlotRange -> {-eps, eps}, PlotLegends -> {"v[x1,0]-v[x1,P2]"}],
 Plot[vsol[0, x2] - vsol[P[[1]], x2], {x2, 0, P[[2]]}, 
  PlotRange -> {-eps, eps}, PlotLegends -> {"v[0,x2]-v[P1,x2]"}],
 Show[ContourPlot[vsol[x1, x2], Element[{x1, x2}, Omega], 
   AspectRatio -> Automatic, Contours -> 20, 
   ColorFunction -> "TemperatureMap", PlotLegends -> Automatic], 
  RegionPlot@Omegainc]}

Figure 1


This is similar to this question and this answer also applies here.

When you use

(*PDE with prescribed g*)
g = {{3}, {1}};

Things then work as expected. The Inactive Div then does the differentiation. It's worthwhile noting that the numerical differentiation is probably less accurate then if you have a symbolic derivative.

Note the other improvements in that post also apply here.

For completeness the plot:

enter image description here