def test_run(self): """ Try running SPEC and reading in the output. """ filename = os.path.join(TEST_DIR, '1DOF_Garabedian.sp') for new_mpol in [2, 3]: for new_ntor in [2, 3]: s = Spec(filename) print('new_mpol: {}, new_ntor: {}'.format(new_mpol, new_ntor)) s.inputlist.mpol = new_mpol s.inputlist.ntor = new_ntor s.run() self.assertAlmostEqual(s.volume(), 0.001973920880217874, places=4) self.assertAlmostEqual(s.results.output.helicity, 0.435225, places=3) self.assertAlmostEqual(s.iota(), 0.544176, places=3)
def test_integrated_stellopt_scenarios_1dof(self): """ This script implements the "1DOF_circularCrossSection_varyR0_targetVolume" example from https://github.com/landreman/stellopt_scenarios This optimization problem has one independent variable, representing the mean major radius. The problem also has one objective: the plasma volume. There is not actually any need to run an equilibrium code like SPEC since the objective function can be computed directly from the boundary shape. But this problem is a fast way to test the optimization infrastructure with SPEC. Details of the optimum and a plot of the objective function landscape can be found here: https://github.com/landreman/stellopt_scenarios/tree/master/1DOF_circularCrossSection_varyR0_targetVolume """ for grad in [True, False]: # Start with a default surface. equil = Spec() surf = equil.boundary # Set the initial boundary shape. Here is one way to do it: surf.set('rc(0,0)', 1.0) # Here is another syntax that works: surf.set_rc(0, 1, 0.1) surf.set_zs(0, 1, 0.1) surf.set_rc(1, 0, 0.1) surf.set_zs(1, 0, 0.1) surf.set_rc(1, 1, 0) surf.set_zs(1, 1, 0) # SPEC parameters are all fixed by default, while surface # parameters are all non-fixed by default. You can choose # which parameters are optimized by setting their 'fixed' # attributes. surf.all_fixed() surf.set_fixed('rc(0,0)', False) # Turn off Poincare plots and use low resolution, for speed: equil.inputlist.nptrj[0] = 0 equil.inputlist.lrad[0] = 2 # Each Target is then equipped with a shift and weight, to become a # term in a least-squares objective function desired_volume = 0.15 term1 = (equil.volume, desired_volume, 1) # A list of terms are combined to form a nonlinear-least-squares # problem. prob = LeastSquaresProblem([term1]) # Check that the problem was set up correctly: self.assertEqual(len(prob.dofs.names), 1) self.assertEqual(prob.dofs.names[0][:7], 'rc(0,0)') np.testing.assert_allclose(prob.x, [1.0]) self.assertEqual(prob.dofs.all_owners, [equil, surf]) self.assertEqual(prob.dofs.dof_owners, [surf]) # Solve the minimization problem: least_squares_serial_solve(prob, grad=grad) self.assertAlmostEqual(surf.get_rc(0, 0), 0.7599088773175, places=5) self.assertAlmostEqual(equil.volume(), 0.15, places=6) self.assertAlmostEqual(surf.volume(), 0.15, places=6) self.assertLess(np.abs(prob.objective()), 1.0e-15)
def test_integrated_stellopt_scenarios_2dof(self): """ This script implements the "2DOF_vmecOnly_targetIotaAndVolume" example from https://github.com/landreman/stellopt_scenarios This optimization problem has two independent variables, representing the helical shape of the magnetic axis. The problem also has two objectives: the plasma volume and the rotational transform on the magnetic axis. The resolution in this example (i.e. ns, mpol, and ntor) is somewhat lower than in the stellopt_scenarios version of the example, just so this example runs fast. Details of the optimum and a plot of the objective function landscape can be found here: https://github.com/landreman/stellopt_scenarios/tree/master/2DOF_vmecOnly_targetIotaAndVolume """ filename = os.path.join(TEST_DIR, '2DOF_targetIotaAndVolume.sp') # Initialize SPEC from an input file equil = Spec(filename) surf = equil.boundary # VMEC parameters are all fixed by default, while surface parameters are all non-fixed by default. # You can choose which parameters are optimized by setting their 'fixed' attributes. surf.all_fixed() surf.set_fixed('rc(1,1)', False) surf.set_fixed('zs(1,1)', False) # Each Target is then equipped with a shift and weight, to become a # term in a least-squares objective function. A list of terms are # combined to form a nonlinear-least-squares problem. desired_volume = 0.15 volume_weight = 1 term1 = (equil.volume, desired_volume, volume_weight) desired_iota = -0.41 iota_weight = 1 term2 = (equil.iota, desired_iota, iota_weight) prob = LeastSquaresProblem([term1, term2]) # Solve the minimization problem: least_squares_serial_solve(prob) # The tests here are based on values from the VMEC version in # https://github.com/landreman/stellopt_scenarios/tree/master/2DOF_vmecOnly_targetIotaAndVolume # Due to this and the fact that we don't yet have iota on axis from SPEC, the tolerances are wide. """ assert np.abs(surf.get_rc(1, 1) - 0.0313066948) < 0.001 assert np.abs(surf.get_zs(1, 1) - (-0.031232391)) < 0.001 assert np.abs(equil.volume() - 0.178091) < 0.001 assert np.abs(surf.volume() - 0.178091) < 0.001 assert np.abs(equil.iota() - (-0.4114567)) < 0.001 assert (prob.objective() - 7.912501330E-04) < 0.2e-4 """ self.assertAlmostEqual(surf.get_rc(1, 1), 0.0313066948, places=3) self.assertAlmostEqual(surf.get_zs(1, 1), -0.031232391, places=3) self.assertAlmostEqual(equil.volume(), 0.178091, places=3) self.assertAlmostEqual(surf.volume(), 0.178091, places=3) self.assertAlmostEqual(equil.iota(), -0.4114567, places=3) self.assertAlmostEqual(prob.objective(), 7.912501330E-04, places=3)