Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix logical errors and typos in Spec equilibrium object #457

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

missing-user
Copy link
Contributor

There were a few bugs in the Spec equilibrium object that I spotted:

  • Many error checks were written, but the raise clause was omitted, so they didn't take effect
  • The RHS of the assignments to si.iota[0:self.nvol+1] and si.oita[0:self.nvol+1] had the wrong shape
  • array shape check in as_spec compared tuple to list and always raised

@missing-user missing-user marked this pull request as draft November 14, 2024 15:40

if self.oita_profile is not None:
si.oita[0:self.nvol+1] = self.oita_profile.get(np.arange(0, self.nvol))
si.oita[0:self.nvol+1] = self.oita_profile.get(np.arange(0, self.nvol+1))
Copy link
Contributor Author

@missing-user missing-user Nov 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nvol+1 is the correct size here, compare to:

https://github.com/missing-user/SPEC/blob/6a231606a626968fc1b83eed7dfa01c234842905/InputFiles/Verification/forcefree/solovev/generate_spec_nl_from_vmec.m#L167

I think the other iota sizes in spec wrapper must be adjusted.

@missing-user missing-user marked this pull request as ready for review November 18, 2024 02:55
@missing-user missing-user marked this pull request as draft November 18, 2024 15:12
@missing-user
Copy link
Contributor Author

missing-user commented Nov 18, 2024

I noticed, that parts of the codebase assume all profiles to be the same size (mvol), in this example according to the error message local_full_x = self.mvol

# Check that volume index is within bounds
if (lvol < 0).any():
raise ValueError('lvol should be larger or equal than zero')
if (lvol >= self.local_full_x.size).any():
raise ValueError('lvol should be smaller than Mvol')

or here, where volume_current_profile is simply overwritten in the vacuum region for freeboundary runs, so although nvol elements are used, the profile has to be at least mvol in size:
if self.volume_current_profile is not None:
# Volume current is a cumulative profile; special care is required
# when a dofs is changed in order to keep fixed dofs fixed!
old_ivolume = copy.copy(si.ivolume)
for lvol in range(0, self.mvol):
if self.volume_current_profile.is_fixed(lvol):
if lvol != 0:
si.ivolume[lvol] = si.ivolume[lvol] - \
old_ivolume[lvol - 1] + si.ivolume[lvol - 1]
self.set_profile(
'volume_current', lvol=lvol, value=si.ivolume[lvol])
else:
si.ivolume[lvol] = self.get_profile('volume_current', lvol)
if si.lfreebound:
si.ivolume[self.nvol] = si.ivolume[self.nvol - 1]
self.volume_current_profile.set(
key=self.mvol - 1, new_val=si.ivolume[self.nvol - 1])

while other parts create different sizes for different profiles.

profile_dict = {
'pressure': {'specname': 'pressure', 'cumulative': False, 'length': self.nvol},
'volume_current': {'specname': 'ivolume', 'cumulative': True, 'length': self.nvol},
'interface_current': {'specname': 'isurf', 'cumulative': False, 'length': self.nvol-1},
'helicity': {'specname': 'helicity', 'cumulative': False, 'length': self.mvol},
'iota': {'specname': 'iota', 'cumulative': False, 'length': self.mvol},
'oita': {'specname': 'oita', 'cumulative': False, 'length': self.mvol},
'mu': {'specname': 'mu', 'cumulative': False, 'length': self.mvol},
'pflux': {'specname': 'pflux', 'cumulative': True, 'length': self.mvol},
'tflux': {'specname': 'tflux', 'cumulative': True, 'length': self.mvol}
}
profile_data = self.inputlist.__getattribute__(profile_dict[longname]['specname'])[0:profile_dict[longname]['length']]
profile = ProfileSpec(profile_data, cumulative=profile_dict[longname]['cumulative'], psi_edge=self.inputlist.phiedge)
profile.unfix_all()
self.__setattr__(longname + '_profile', profile)

What is the intended design @smiet ? I think variable size will result in stricter error handling, whereas having all profiles the same size makes them easier to switch out, iterate over, etc. On the other hand, having the same size might confuse users about which elements actually affect the result.

@missing-user
Copy link
Contributor Author

missing-user commented Nov 18, 2024

Also @smiet , shouldn't iota profiles be nvol+1 elements and not mvol? How can the vacuum computational boundary have a prescribed iota?
#457 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant