def test_change_resolution(self): """ Check that we can change mpol and ntor. """ for mpol in [1, 2]: for ntor in [0, 1]: s = SurfaceRZFourier(mpol=mpol, ntor=ntor) n = len(s.get_dofs()) s.set_dofs((np.random.rand(n) - 0.5) * 0.01) s.set_rc(0, 0, 1.0) s.set_rc(1, 0, 0.1) s.set_zs(1, 0, 0.13) v1 = s.volume() a1 = s.area() s.change_resolution(mpol + 1, ntor) s.recalculate = True v2 = s.volume() a2 = s.area() self.assertAlmostEqual(v1, v2) self.assertAlmostEqual(a1, a2) s.change_resolution(mpol, ntor + 1) s.recalculate = True v2 = s.volume() a2 = s.area() self.assertAlmostEqual(v1, v2) self.assertAlmostEqual(a1, a2) s.change_resolution(mpol + 1, ntor + 1) s.recalculate = True v2 = s.volume() a2 = s.area() self.assertAlmostEqual(v1, v2) self.assertAlmostEqual(a1, a2)
def test_surface_sampling(self): np.random.seed(1) nquadpoints = int(4e2) surface = SurfaceRZFourier(nfp=1, stellsym=True, mpol=1, ntor=0, quadpoints_phi=nquadpoints, quadpoints_theta=nquadpoints) dofs = surface.get_dofs() dofs[0] = 1 dofs[1] = 0.8 surface.set_dofs(dofs) n = np.linalg.norm(surface.normal(), axis=2) print(np.min(n), np.max(n)) start = int(0.2*nquadpoints) stop = int(0.5*nquadpoints) from scipy.integrate import simpson quadpoints_phi = surface.quadpoints_phi quadpoints_theta = surface.quadpoints_theta lineintegrals = [simpson(y=n[i, start:stop], x=quadpoints_theta[start:stop]) for i in range(start, stop)] area_of_subset = simpson(y=lineintegrals, x=quadpoints_phi[start:stop]) total_area = surface.area() print("area_of_subset/total_area", area_of_subset/total_area) nsamples = int(1e6) xyz, idxs = draw_uniform_on_surface(surface, nsamples, safetyfactor=10) samples_in_range = np.sum((idxs[0] >= start) * (idxs[0] < stop)*(idxs[1] >= start) * (idxs[1] < stop)) print("samples_in_range/nsamples", samples_in_range/nsamples) print("fraction of samples if uniform", (stop-start)**2/(nquadpoints**2)) assert abs(samples_in_range/nsamples - area_of_subset/total_area) < 1e-2
def test_2dof_surface_opt(self): """ Optimize the minor radius and elongation of an axisymmetric torus to obtain a desired volume and area. """ for solver in solvers: desired_volume = 0.6 desired_area = 8.0 # Start with a default surface, which is axisymmetric with major # radius 1 and minor radius 0.1. surf = SurfaceRZFourier(quadpoints_phi=62, quadpoints_theta=63) # Set initial surface shape. It helps to make zs(1,0) larger # than rc(1,0) since there are two solutions to this # optimization problem, and for testing we want to find one # rather than the other. surf.set_zs(1, 0, 0.2) # Parameters are all non-fixed by default, meaning they will be # optimized. You can choose to exclude any subset of the variables # from the space of independent variables by setting their 'fixed' # property to True. surf.set_fixed('rc(0,0)') # Each function you want in the objective function 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. prob = LeastSquaresProblem([(surf.volume, desired_volume, 1), (surf.area, desired_area, 1)]) # Verify the state vector and names are what we expect np.testing.assert_allclose(prob.x, [0.1, 0.2]) self.assertEqual(prob.dofs.names[0][:28], 'rc(1,0) of SurfaceRZFourier ') self.assertEqual(prob.dofs.names[1][:28], 'zs(1,0) of SurfaceRZFourier ') # Solve the minimization problem: solver(prob) # Check results self.assertAlmostEqual(surf.get_rc(0, 0), 1.0, places=13) self.assertAlmostEqual(surf.get_rc(1, 0), 0.10962565115956417, places=13) self.assertAlmostEqual(surf.get_zs(0, 0), 0.0, places=13) self.assertAlmostEqual(surf.get_zs(1, 0), 0.27727411213693337, places=13) self.assertAlmostEqual(surf.volume(), desired_volume, places=8) self.assertAlmostEqual(surf.area(), desired_area, places=8) self.assertLess(np.abs(prob.objective()), 1.0e-15)
def test_area_volume(self): """ Test the calculation of area and volume for an axisymmetric surface """ s = SurfaceRZFourier() s.rc[0, 0] = 1.3 s.rc[1, 0] = 0.4 s.zs[1, 0] = 0.2 true_area = 15.827322032265993 true_volume = 2.0528777154265874 self.assertAlmostEqual(s.area(), true_area, places=4) self.assertAlmostEqual(s.volume(), true_volume, places=3)
desired_area = 8.0 # Start with a default surface, which is axisymmetric with major # radius 1 and minor radius 0.1. surf = SurfaceRZFourier() # Parameters are all non-fixed by default, meaning they will be # optimized. You can choose to exclude any subset of the variables # from the space of independent variables by setting their 'fixed' # property to True. surf.set_fixed('rc(0,0)') # Each target function is then equipped with a shift and weight, to # become a term in a least-squares objective function term1 = (surf.volume, desired_volume, 1) term2 = (surf.area, desired_area, 1) # A list of terms are combined to form a nonlinear-least-squares # problem. prob = LeastSquaresProblem([term1, term2]) # Solve the minimization problem: least_squares_serial_solve(prob) print("At the optimum,") print(" rc(m=1,n=0) = ", surf.get_rc(1, 0)) print(" zs(m=1,n=0) = ", surf.get_zs(1, 0)) print(" volume = ", surf.volume()) print(" area = ", surf.area()) print(" objective function = ", prob.objective())