mass = den.totalMass() data0 = numpy.ones((len(initcond), 1)) # discretized density profile to be used as the density constraint rhs1 = target1(den) # data2 is kinematic data: for each orbit (row) it contains # Ngrid values of rho sigma_r^2, then the same number of values of rho sigma_t^2; # we combine them into a single array of Ngrid values that enforce isotropy (sigma_t^2 - 2 sigma_r^2 = 0) Ngrid = len(target2) // 2 datak = 2 * data2[:, :Ngrid] - data2[:, Ngrid:] rhs2 = numpy.zeros(Ngrid) # solve the matrix equation for orbit weights weights = agama.solveOpt(matrix=(data0.T, data1.T, datak.T), rhs=([mass], rhs1, rhs2), \ rpenl=([numpy.inf], numpy.ones_like(rhs1), numpy.ones_like(rhs2)), \ xpenq=numpy.ones(len(initcond))*0.1 ) # check if all constraints were satisfied delta1 = data1.T.dot(weights) - rhs1 for i, d in enumerate(delta1): if abs(d) > 1e-8: print("DensityConstraint %i not satisfied: %s, val=%.4g, rel.err=%.4g" % \ (i, target1[i], rhs1[i], d / rhs1[i])) delta2 = datak.T.dot(weights) for i, d in enumerate(delta2): if abs(d) > 1e-8: print("KinemConstraint %i not satisfied: %.4g" % (i, d)) # export an N-body model nbody = 100000 status, result = agama.sampleOrbitLibrary(nbody, trajs, weights)
def runComponent(comp, pot): """ run the orbit integration, optimization, and construction of an N-body model for a given component of the Schwarzschild model """ if hasattr(comp, 'trajsize'): result = agama.orbit(potential=pot, ic=comp.ic, time=comp.inttime, Omega=comp.Omega, targets=comp.targets, trajsize=comp.trajsize) traj = result[-1] else: result = agama.orbit(potential=pot, ic=comp.ic, time=comp.inttime, Omega=comp.Omega, targets=comp.targets) traj = None if type(result) == numpy.array: result = (result, ) # targets[0] is density, targets[1], if provided, is kinematics matrix = list() rhs = list() rpenl = list() mass = comp.density.totalMass() # density constraints matrix.append(result[0].T) rhs.append(comp.targets[0](comp.density)) avgrhs = mass / len(rhs[0]) # typical magnitude of density constraints rpenl.append(numpy.ones_like(rhs[0]) / avgrhs) # kinematic constraints if len(comp.targets) == 2 and hasattr(comp, 'beta'): numrow = len(comp.targets[1]) // 2 matrix.append(result[1].T[0:numrow] * 2 * (1 - comp.beta) - result[1].T[numrow:2 * numrow]) rhs.append(numpy.zeros(numrow)) rpenl.append(numpy.ones(numrow)) # total mass constraint matrix.append(numpy.ones((len(comp.ic), 1)).T) rhs.append(numpy.array([mass])) rpenl.append(numpy.array([numpy.inf])) # regularization (penalty for unequal weights) avgweight = mass / len(comp.ic) xpenq = numpy.ones(len(comp.ic)) / avgweight**2 / len(comp.ic) * 0.1 # solve the linear equation for weights weights = agama.solveOpt(matrix=matrix, rhs=rhs, rpenl=rpenl, xpenq=xpenq) # check for any outstanding constraints for t in range(len(matrix)): delta = matrix[t].dot(weights) - rhs[t] norm = 1e-4 * abs(rhs[t]) + 1e-8 for c, d in enumerate(delta): if abs(d) > norm[c]: print("Constraint %i:%i not satisfied: %s, val=%.4g, dif=%.4g" % \ (t, c, comp.targets[t][c], rhs[t][c], d)) print("Entropy: %f, # of useful orbits: %i / %i" %\ ( -sum(weights * numpy.log(weights+1e-100)) / mass + numpy.log(avgweight), \ len(numpy.where(weights >= avgweight)[0]), len(comp.ic))) # create an N-body model if needed if hasattr(comp, 'nbody'): status, particles = agama.sampleOrbitLibrary(comp.nbody, traj, weights) if not status: indices, trajsizes = particles print("reintegrating %i orbits; max # of sampling points is %i" % (len(indices), max(trajsizes))) traj[indices] = agama.orbit(potential=pot, ic=comp.ic[indices], \ time=comp.inttime[indices], trajsize=trajsizes) status, particles = agama.sampleOrbitLibrary( comp.nbody, traj, weights) if not status: print("Failed to produce output N-body model") comp.nbodymodel = particles # output comp.weights = weights comp.densitydata = result[0] if len(comp.targets) >= 2: comp.kinemdata = result[1] if not traj is None: comp.traj = traj
data, trajs = agama.orbit(potential=pot, ic=initcond, time=inttimes, trajsize=100, targets=target) # assemble the matrix equation which contains two blocks: # total mass, discretized density # a single value for the total mass constraint, each orbit contributes 1 to it mass = potstars.totalMass() data0 = numpy.ones((len(initcond), 1)) # solve the matrix equation for orbit weights weights = agama.solveOpt(matrix=(data0.T, data.T), rhs=([mass], rhs), rpenl=([numpy.inf], numpy.ones(len(rhs)) * numpy.inf), xpenq=numpy.ones(len(initcond))) #numpy.savetxt('orbits', numpy.column_stack((initcond, weights, inttimes))[numpy.argsort(inttimes)], '%g') # export an N-body model nbody = 100000 status, result = agama.sampleOrbitLibrary(nbody, trajs, weights) if not status: # this may occur if there was not enough recorded trajectory points for some high-weight orbits: # in this case their indices and the required numbers of points are returned in the result tuple indices, trajsizes = result print("reintegrating %i orbits; max # of sampling points is %i" % (len(indices), max(trajsizes))) trajs[indices] = agama.orbit(potential=pot, ic=initcond[indices], time=inttimes[indices], \ trajsize=trajsizes)