dofs of surface not inherited by SquaredFlux objective
Closed this issue · 4 comments
Hello, I am playing with simsopt to learn how to make some simple coil+surface vacuum optimization.
I don't understand the following:
Following the tutorials,
- I create an object 'coils' and an object 's' of the class SurfaceRZFourier (which has dofs unfixed),
- I create the object
bs = BiotSavart(coils)
and types.set_points(s.gamma().reshape((-1, 3)))
- I create the optimizable object
Jf = SquaredFlux(s, bs)
But, when checking the dofs of Jf
, only the dofs from coils are inherited. Why not the surface dofs as well? Indeed the surface s does not seem to be a parent of Jf. How to include then these dofs into Jf?
Thanks for the help.
OK so with some help from Antoine I realized that indeed the object SquareFlux
does not, by construction, inherit dofs from surface. Changing this line in the source file fluxobjective.py:
Optimizable.__init__(self, x0=np.asarray([]), depends_on=[field,**surface**])
does allow then to consider changes in the surface geometry as dofs. Is this something we should add as a possibility? Or is there another way of doing this without any changes to the source?
Thanks for the help.
@jloizu Can you say more about your use case? When the surface is varying but the magnetic field is not, i.e. you are computing a QFM surface, this is presently done using simsopt.geo.QFMSurface
, documented here and in examples/1_Simple/qfm.py
. Also NormalField is closely related. It's true that QFM surface computation and stage-2 optimization have the same cost function, and the group discussed whether there should be a single class or several. Presently there are these 3 separate classes (SquaredFlux
, QFMSurface
, and NormalField
), which simplifies some aspects of implementation and means users do not need to fix the dofs which will not be varied. But it could be reasonable to try to do things with 2 or 1 class instead of 3.
My use case is as follows: I want to fix a small number of planar coils (e.g. 4) and let them move in space so that they generate a maximal volume of magnetic surfaces in vacuum. For this, I started constructing an objective based on the normal field on a surface and the idea was to allow both the surface and the coils to vary (then I might add constraints/penalties such as iota, or volume). As I understand now, SquaredFlux is thought of only depending on the coils but not on the surface, sot that is not a good choice, unless something is changed. Looking at the QFM documentation, looks like maybe the QfmResidual
object might be well suited, since it seems to depend on both the field and the surface?
OK I think I can close this issue, indeed working with QfmResidual
allows having an optimizable that depends on both the surface and the field (although I cannot use jacobian information anymore, since dJ() is not available for this object, I think).