Regions creation issue + using regions question

Hi.

I’m starting to use FreeFem and I’ve been trying to model using the freefem mesh generator.

I’ve got two questions/issues:

A.I’m running into issues with the geometry/mesh definitions when having multiple regions/borders

B. how can I use regions, in order to use them in a function in order to differentiate physics/equations between water and polycarbonate in this case (no convection in PC, no SAR heating in PC for example).

A. Intended geometry:

  1. outside sphere/circle (polycarbonate)

  2. inside sphere/circle (water)

  3. several spheres/circles inside (polycarbonate)

  4. inside these spheres, water sphere/circle again

  5. in between these spheres some slabs.

The goal is to perform a simulation for temperature evolution, with outside air (21 °C for example) and the initial sphere at 14 °C; but also combining MR radiofrequent heating later on.

I ran into quite some mesh issues. The current mesh, enclosed (geom_only.edp), does not result in correct region definition when plotting: the outside region is combined with the water region, and not all spheres seem correct regions

When commenting some regions out, I get more correct definition.

However, when adding more regions, it seems the definition no longer seems coherent. In the script I tried to differentiate everything, creating more mesh points, enlarging distances, using or not using labels, but I don’t seem to get it work, no overlap… Seperately, each region seems coherent, but when adding them all in, at a certain point it becomes incoherent.

(I tried to model also using gmsh; however, both the GMSH and INRIA import resulted in border definition problems, which I abandoned currently.)

B) My second question is using regions in a created mesh to differentiate between materials during equation solving (see second file, “sphere_only_with_physics.edp”:slight_smile:

I’m using currently a form like:

func isWater = (Th(x, y).region == 0) || (Th(x, y).region == 2) ;

(I would like to use for example, but using “region” did not seem to work)

func isWater = (region == 0) || (region == 2);

To know if it is a Water or PC region, to be able to use later on:

func kappa = isWater * kWater + isPC * kPC;
func rhoCp = isWater * (rhoWater * cpWater) + isPC * (rhoPC * cpPC);

func nuEff = isWater * nu + isPC * 1e6*nu;

In order to be able to use in a stokes and heat equation

problem heat(T, vT) =
// Transient term
int2d(Th)(rhoCp/dt * T * vT)

-int2d(Th)(rhoCp/dt * Told * vT)
// Diffusion

+int2d(Th)(kappa * (dx(T)*dx(vT) + dy(T)*dy(vT)) )

// Advection (only in water)

-int2d(Th)( isWater * rhoWater * cpWater * (uxdx(T) + uydy(T)) * vT )

// + int2d(Th)( Qrf * vT )
Convective boundary condition at outer surface

+int1d(Th, 1)(h * T * vT)

-int1d(Th, 1)(h * Tair * vT);

Is this a logic way to differentiate? My current idea was to define the borders well in order to have correct boundary conditions and using the region numbers to differentiate materials. Or should I rather use geometrical functions to define what is water/PC and just have a large mesh? (such as:

func isWater = (x^2 + y^2 <= Rw^2 );

func isPMMA = (x^2 + y^2 > Rw^2);

(I cannot upload files currently to the forum, but they are in the following drive link, the first file is the full geometry, the second one a solver with only the outer spheres)

I’m only starting to use FreeFem, so still learning a lot, thanks in advance for helping me further :).

Please have a look at, e.g., Initialisation in different regions (you should use an fespace function, not a func).

Thanks! I’ll try that approach.

Considering my first question: I think it is just a visualization issue lacking colors. The mesh also has this issue with overlapping or the same color and I was probably assuming a real issue. When checking the region in detail, I get different numbers, so I think it is ok:

(I think the issue is that there are only 12 color levels representing the last regions, and all others are using red).

plot(Th, value=region, fill=true, wait=1);

plot(Th, wait=true, cmm=“Mesh with boundaries”);

Right, don’t use ffglut to check for correctness of your results…

Hi again,

I tried to use the region distinctions using Vhs to distinguish between two materials (water & polycarbonate). It seems that Vhs are initialised statically, but when using it dynamically for buoyancy for example, a function is rather better used?

When using Vh in the below stokes equation for buoyancy, it remained the static 0 point, but when replacing it with a function directly it seemed to work (or is it due to using a function to initialise the Vh?).

I tried to initialise a Vh as:

Vh kappaVh;
Vh rhoCpVh;
Vh nuEffVh;
Vh buoyVh;

kappaVh = kWaterisInListWater(region) + kPCisInListPC(region);
rhoCpVh = isInListWater(region) * (rhoWater * cpWater) + isInListPC(region) * (rhoPC * cpPC);

nuEffVh = isInListWater(region)nu + isInListPC(region)1e6nu; //high viscosity in solid
buoyVh = isInListWater(region) beta * g * (T - T0);

However, still using a function, as many regions:

func int isInListWater(int r)
{
for (int i = 0; i < waterRegs.n; i++)
if (r == waterRegs[i]) return 1;
return 0;
}

func int isInListPC(int r)
{
for (int i = 0; i < PCRegs.n; i++)
if (r == PCRegs[i]) return 1;
return 0;
}

When then using in stokes and heat problems:

problem stokes([ux, uy, p], [vx, vy, q]) =

// (1) Viscous diffusion: ν ∫Ω ∇u : ∇v

int2d(Th)(
(nuEffVh + eps) * (
dx(ux)*dx(vx) + dy(ux)*dy(vx)
+ dx(uy)*dx(vy) + dy(uy)*dy(vy))

)

// (2) Pressure—velocity coupling

- int2d(Th)(p * (dx(vx) + dy(vy)))

// (3) Incompressibility constraint

- int2d(Th)(q * (dx(ux) + dy(uy)))

// (4) Buoyancy force

- int2d(Th)(buoyVh * vy)

// (5) Mean pressure = 0 constraint (LM approach)

+ int2d(Th)(1e-8 * p * q)

// (6) No-slip boundary conditions

+ on(borderLabels, ux=0,uy=0);

and heat:

problem heat(T, vT) =

// Transient term
int2d(Th)(rhoCpVh/dt * T * vT)

- int2d(Th)(rhoCpVh/dt * Told * vT)

// Diffusion

+ int2d(Th)( kappaVh * (dx(T)*dx(vT) + dy(T)*dy(vT)) )

// Advection (only in water) TODO CHECK SIGN

+ int2d(Th)( isInListWater(region) * (rhoWater * cpWater)* (uxdx(T) + uydy(T)) * vT)

// RF heating: - = heating?

- int2d(Th)( QrfVh * vT )

// Convective boundary condition at outer surface

+ int1d(Th, 2)( h * T * vT )

- int1d(Th, 2)( h * Tair * vT)

In the heat equation it seems to work correctly as it is static, however, when comparing with my former test with functions, the stokes equation did no longer work out: no velocities at all. When replacing with func, it seemed to work again.

// (4) Buoyancy force

  • int2d(Th)(isInListWater(region)* beta * g * (T - T0) * vy

Or would my syntax not be correct/optimal when using Vh? It is also possible that I made mistakes in the stokes/heat equation that render this incorrect?

Full file below. Geometry: 2D sphere/circle at 14.5 °C, in air 21°C + gaussian RF heating (in file exagerated at 100 W/kg). (can’t upload files as “new member”)

Thanks in advance again!

Hi. I’ve been working to update my freefem script. Modelling the transient heat equation, combined with incompressible Stokes flow/thermal buoyancy for water in an (MRI) phantom, sphere simplified to 2D circle of radius 10 cm. (low temperature differences)

First two equations in water, third heat equation everywhere:

([Edit] or simplified equations:

With kinematic viscosity /nu (m²/s), velocity u (m/s), pressure p (N/m²), thermal expansion beta (1/K), density ρ (kg/m3), gravity constant g (m²/s), heat capacity Cp (J/kgK), thermal conductivity k (W/mK), air convection heat transfer coefficient h (W/m²K), normal vector n and heat deposition Q (W/m3) modelled as a gaussian distribution in water only.

When comparing to measurements, the results seem to be consistent. (however, quite high h value (of air-phantom convection) and SAR is not directly linked to machine listed wattage)

I tried to perform all factors as good as possible, basing on online information and some meteorology courses from the past (physicist here, no mathematician). I’m a new user, and also used in a critical thinking way, often correcting, LLMs to iterate and correct parts of my script. My questions:

  1. Would this implementation seem consistent? (or would it be better to restart from scratch? :slight_smile: )

  2. Would mesh adaptation using adaptmesh be recommended?

  3. I’m not totally happy with the viscosity approach I’ve used, which uses very high values in solid materials instead of only solving in water. Would there be a better way? I guess using two fespaces, but I did not get it working… I also did not find a way to use Vh dynamically, thereofore using a function for buoyancy.

If someone could give some critical return, we would be eternally grateful!

(Caveat, only valid for low temperature differences, if temperature differences of the outside are very high (6°C inside, outside 20 °C), at some point I think the viscosity approach of having high viscosity in solid creates issues, and/or combined with too large velocities/inappropriate mesh and also no longer physical true, requiring possibly Navier).

Enclosed an example of the freefem script.

NIST std V5.edp (22.0 KB)

[Edit] Version without SUPG (SUPG = outside of my comprehension, and seems to result in less stable: no SUPG seems more consistent with measurements also):

NIST std V5_noSUPG.edp (22.0 KB)

[Edit2: changed some comments (SAR value) + correct sign when no SUPG]