## Problem Description
I am working on a coupled simulation where:
-
A rotating object (workpiece) is heated by a stationary heat source
-
The heat source distribution
Qis computed from a previous FEM analysis and stored as aGridFunction -
The mesh rotates using
mesh.SetDeformation()to simulate the rotating workpiece -
I want the heat source
Qto remain fixed in space (not rotate with the mesh)
## Current Issue
When I use a GridFunction-based CoefficientFunction for the heat source, it rotates with the mesh deformation, which is not the desired behavior.
Expression-based CF (works correctly - does NOT rotate):
theta = atan2(y, x)
Q = mesh.MaterialCF({“work”: 1e8*IfPos(theta, 1, 0) * IfPos(pi/8 - theta, 1, 0)}, default=0)
GridFunction-based CF (problem - DOES rotate):
gfQ = GridFunction(fes)
gfQ.Set(Q_expression)
Q = 1.0 * gfQ # Convert to CoefficientFunction
## Minimal Example
from ngsolve import *
from netgen.occ import *
# Simple 2D rotating disk geometry
circle = Circle((0,0), 0.1).Face()
geo = OCCGeometry(circle, dim=2)
mesh = Mesh(geo.GenerateMesh(maxh=0.02))
# Define heat source: fixed sector (0 < theta < pi/4)
theta = atan2(y, x)
Q_expr = IfPos(theta, 1, 0) * IfPos(pi/4 - theta, 1, 0)
# Convert to GridFunction
fes_Q = H1(mesh, order=2)
gfQ_fixed = GridFunction(fes_Q)
gfQ_fixed.Set(Q_expr)
# Temperature field on rotating mesh
fes_T = H1(mesh, order=2)
gfT = GridFunction(fes_T)
# Setup deformation
fesdef = VectorH1(mesh, order=3)
deformation = GridFunction(fesdef)
center = CF((0, 0))
pos = CF((x, y))
# Rotate mesh by 45 degrees
angle = pi/4
rotmat = CF((cos(angle), -sin(angle), sin(angle), cos(angle))).Reshape((2,2))
deformation.Set((rotmat - Id(2))*(pos-center))
mesh.SetDeformation(deformation)
# Problem: How to use gfQ_fixed in a way that it does NOT rotate?
# When using gfQ_fixed directly, it rotates with the mesh
# Example: weak form for heat equation
u, v = fes_T.TnT()
a = BilinearForm(fes_T)
a += grad(u) \* grad(v) \* dx
a.Assemble()
f = LinearForm(fes_T)
f += gfQ_fixed * v * dx # ← This rotates with mesh (NOT desired)
f.Assemble()
## What I Need
I need a way to create a GridFunction-based CoefficientFunction that:
-
Is evaluated in the global (fixed) coordinate system
-
Does NOT follow the mesh deformation
-
Can be used in weak forms like
f += Q_fixed * v * dx
In the future, gfQ_fixed will come from a separate FEM analysis, so I cannot use the analytical expression Q_expr directly.
## Attempted Solutions
- Copy GridFunction vector before deformation:
mesh.UnsetDeformation()
gfQ_current.vec.data = gfQ_fixed.vec
mesh.SetDeformation(deformation)
This doesn’t work because GridFunction DOFs are defined in reference coordinates.
- Apply inverse transformation:
I want to evaluate gfQ_fixed at the inverse-transformed coordinates, but I cannot use:
rotmat_inv = CF((cos(-angle), -sin(-angle), sin(-angle), cos(-angle))).Reshape((2,2))
pos_original = rotmat_inv * pos
Q_at_original = gfQ_fixed(mesh(pos_original\[0\], pos_original\[1\])) # ← pos_original is CF, not numbers
because gfQ(mesh(x,y,z)) requires real numbers, not CoefficientFunction.
- Using Set() or Interpolate():
I need a way to use Set() or .Interpolate() with coordinate transformation, but I’m not sure how.
## Question
What is the correct way to implement a fixed-space heat source using a GridFunction on a deforming mesh in NGSolve?
Any suggestions or examples would be greatly appreciated!
## System Information
- NGSolve version: [6.2.2506]
- Operating System: Windows Python 3.12.10