def test_pCoordinates(self): NWorld = np.array([5]) xp = util.pCoordinates(NWorld) self.assertTrue(np.allclose(xp.T - np.array([0., 1., 2., 3., 4., 5.])/5, 0)) NWorld = np.array([9, 9, 9, 9]) xp = util.pCoordinates(NWorld) ind = util.convertpCoordinateToIndex(NWorld, [7, 3, 6, 0]) self.assertTrue(np.allclose(xp[ind] - np.array([7., 3., 6., 0.])/9., 0))
def invert_cq1_mapping(N, mapping): """Invert a y = psi(x) CQ1 mapping using the iterative method "A simple fixed-point approach to invert a deformation field", Chen et al 2008. """ coords = util.pCoordinates(N) displace = mapping - coords inv_displace = np.zeros_like(displace) max_iter = 100 iter = 0 tolerance = 1e-7 error = 1 while iter < max_iter and error > tolerance: inv_displace_previous = inv_displace points = np.maximum(0, np.minimum(1.0, coords + inv_displace)) inv_displace = -func.evaluateCQ1(N, displace, points) iter += 1 error = np.max(np.abs(inv_displace - inv_displace_previous)) return inv_displace + coords
def create(self): NFine = self.world.NWorldFine fine = NFine[0] x = util.pCoordinates(NFine) num_dots = self.num_dots epsilon = 0.4 frequency = 2 * np.pi * num_dots displacement_unscaled = 1. / (frequency) * np.column_stack([ 0.5 * (np.sin(0.5 * frequency * x[:, 0]) + 1) * np.sin(frequency * x[:, 0]), 0.5 * (np.sin(0.5 * frequency * x[:, 1]) + 1) * np.sin(frequency * x[:, 1]) ]) point_tile_index = np.array(np.minimum(np.floor(num_dots * x), num_dots - 1), dtype=int) tile_scaling = epsilon * 2 * np.random.rand(num_dots, num_dots)**2 point_scaling = tile_scaling[point_tile_index[:, 0], point_tile_index[:, 1]] displacement = displacement_unscaled * point_scaling[..., None] self.psi = discrete_mapping.MappingCQ1(NFine, x + displacement)
def d3plotter(N, s, String='FinescaleSolution', boundary=None, Blues=None, zmax=None, zmin=None, fig=None, ax=None): if fig is None: fig = plt.figure(String) if ax is None: ax = fig.add_subplot(111, projection='3d') xp = util.pCoordinates(N) X = xp[0:,1:].flatten() Y = xp[0:,:1].flatten() X = np.unique(X) Y = np.unique(Y) X, Y = np.meshgrid(X, Y) uLodFine = s.reshape(N+1) # Plot the surface. if zmin is not None: surf = ax.plot_surface(X, Y, uLodFine, cmap=cm.coolwarm, vmin=zmin, vmax=zmax) if boundary is not None: surf = ax.plot_surface(X, Y, uLodFine, cmap=cm.coolwarm, vmin=boundary[0], vmax=boundary[1]) ax.set_zlim(boundary[0], boundary[1]) ax.zaxis.set_major_locator(LinearLocator(10)) if zmin is not None: ax.set_zlim(zmin,zmax) ax.axis('off') ax.grid(False) fig.subplots_adjust(left=0.00,bottom=0.00,right=1,top=1,wspace=0.2,hspace=0.2)
def d3sol(N, s, String='FinescaleSolution'): ''' 3d solution ''' fig = plt.figure(String) ax = fig.add_subplot(111, projection='3d') xp = util.pCoordinates(N) X = xp[0:,1:].flatten() Y = xp[0:,:1].flatten() X = np.unique(X) Y = np.unique(Y) X, Y = np.meshgrid(X, Y) uLodFine = s.reshape(N+1) # Plot the surface. surf = ax.plot_surface(X, Y, uLodFine, cmap=cm.coolwarm) ymin, ymax = ax.set_zlim() ax.set_zticks((ymin,ymax)) ax.set_zlabel('$z$') ax.set_xlabel('$x$') ax.set_ylabel('$y$') ax.zaxis.set_major_locator(LinearLocator(10)) ax.axis('off')
def d3sol(N, s, String='FinescaleSolution'): ''' 3d solution ''' fig = plt.figure(String) ax = fig.add_subplot(111, projection='3d') xp = util.pCoordinates(N) X = xp[0:, 1:].flatten() Y = xp[0:, :1].flatten() X = np.unique(X) Y = np.unique(Y) X, Y = np.meshgrid(X, Y) uLodFine = s.reshape(N + 1) # Plot the surface. ymin, ymax = ax.set_zlim([0, 0.021]) ax.set_zticks((ymin, ymax)) ax.zaxis.set_major_formatter(FormatStrFormatter('%.3f')) ax.set_zlabel('$z$', size=16) ax.set_xlabel('$x$', size=16) ax.set_ylabel('$y$', size=16) # ax.view_init(50, 35) ax.zaxis.set_major_locator(LinearLocator(4)) ax.tick_params(labelsize=12) #ax.axis('off') # Add a color bar which maps values to colors. surf = ax.plot_surface(X, Y, uLodFine, cmap=cm.hot, vmin=0, vmax=0.021)
def test_stiffnessMatrixForConstantFullA(self): N = np.array([3, 4, 5], dtype='int64') AConstant = np.array([[3.0, 0.2, 0.1], [0.2, 2.0, 0.3], [0.1, 0.3, 1.0]]) aPatch = np.tile(AConstant, [3 * 4 * 5, 1, 1]) ALocTensor = fem.localStiffnessTensorMatrixCoefficient(N) A = fem.assemblePatchMatrix(N, ALocTensor, aPatch) # Create the functions x1, x2 and x3 pc = util.pCoordinates(N) x1 = pc[:, 0] x2 = pc[:, 1] x3 = pc[:, 2] # Check diagonal elements self.assertTrue(np.isclose(np.dot(x1, A * x1), 3.0)) self.assertTrue(np.isclose(np.dot(x2, A * x2), 2.0)) self.assertTrue(np.isclose(np.dot(x3, A * x3), 1.0)) # Check off-diagonal elements self.assertTrue(np.isclose(np.dot(x1, A * x2), 0.2)) self.assertTrue(np.isclose(np.dot(x2, A * x1), 0.2)) self.assertTrue(np.isclose(np.dot(x1, A * x3), 0.1)) self.assertTrue(np.isclose(np.dot(x3, A * x1), 0.1)) self.assertTrue(np.isclose(np.dot(x2, A * x3), 0.3)) self.assertTrue(np.isclose(np.dot(x3, A * x2), 0.3))
def evaluateSolution(self, u): NFine = self.world.NWorldFine xpFine = util.pCoordinates(NFine) xpFine_ref = self.psi.inverse_evaluate(xpFine) return func.evaluateCQ1(NFine, u, xpFine_ref)
def test_boundaryNormalDerivativeMatrixProperties(self): # BoundaryNormalDerivative bilinear form should map constants to 0 NPatch = np.array([3, 4, 5]) CLocGetter = fem.localBoundaryNormalDerivativeMatrixGetter(NPatch) C = fem.assemblePatchBoundaryMatrix(NPatch, CLocGetter) constant = np.ones(np.prod(NPatch + 1)) self.assertTrue(np.isclose(np.linalg.norm(C * constant), 0)) # BoundaryNormalDerivative bilinear form (a=constant) should map planes to 0 NPatch = np.array([3, 4, 5, 6]) CLocGetter = fem.localBoundaryNormalDerivativeMatrixGetter(NPatch) C = fem.assemblePatchBoundaryMatrix(NPatch, CLocGetter) p = util.pCoordinates(NPatch) pSum = np.sum(p, axis=1) ones = np.ones(np.prod(NPatch + 1)) self.assertTrue(np.isclose(np.linalg.norm(np.dot(ones, C * pSum)), 0)) # A function f with df/dx_k = 1 at x_k = 0 and df/dx_k = 0 at # x_k = 1 should give 1'*C*f = -d NPatch = np.array([5, 4, 3, 7]) CLocGetter = fem.localBoundaryNormalDerivativeMatrixGetter(NPatch) C = fem.assemblePatchBoundaryMatrix(NPatch, CLocGetter) p = util.pCoordinates(NPatch) p = np.minimum(p, 0.5) pSum = np.sum(p, axis=1) ones = np.ones(np.prod(NPatch + 1)) self.assertTrue(np.isclose(np.dot(ones, C * pSum), -4)) # Same test as above, but with a coefficient a NPatch = np.array([5, 4, 3, 7]) CLocGetter = fem.localBoundaryNormalDerivativeMatrixGetter(NPatch) p = util.pCoordinates(NPatch) p0 = p[:, 0] pElement = util.pCoordinates(NPatch, NPatch=NPatch - 1) pElement0 = pElement[:, 0] aPatch = 1. * (pElement0 < 0.5) + 10. * (pElement0 >= 0.5) C = fem.assemblePatchBoundaryMatrix(NPatch, CLocGetter, aPatch) ones = np.ones(np.prod(NPatch + 1)) self.assertTrue(np.isclose(np.dot(ones, C * p0), 10 - 1))
def test_computeElementFaceFlux_2d(self): NPatchCoarse = np.array([4, 6]) NCoarseElement = np.array([10, 20]) NPatchFine = NPatchCoarse*NCoarseElement NtFine = np.prod(NPatchFine) NpFine = np.prod(NPatchFine+1) aPatch = np.ones(NtFine) uPatch = np.ones(NpFine) fluxTF = transport.computeElementFaceFlux(NPatchCoarse, NPatchCoarse, NCoarseElement, aPatch, uPatch) self.assertTrue(np.all(fluxTF.shape == (24, 4))) self.assertTrue(np.all(fluxTF == 0)) x = util.pCoordinates(NPatchFine)[:,0] y = util.pCoordinates(NPatchFine)[:,1] uPatch = x xFaceArea = 1./NPatchCoarse[1] fluxTF = transport.computeElementFaceFlux(NPatchCoarse, NPatchCoarse, NCoarseElement, aPatch, uPatch) self.assertTrue(np.allclose(fluxTF[:,0], xFaceArea) and np.allclose(fluxTF[:,1], -xFaceArea)) uPatch = x+y xFaceArea = 1./NPatchCoarse[1] yFaceArea = 1./NPatchCoarse[0] fluxTF = transport.computeElementFaceFlux(NPatchCoarse, NPatchCoarse, NCoarseElement, aPatch, uPatch) self.assertTrue(np.allclose(fluxTF[:,0], xFaceArea) and np.allclose(fluxTF[:,1], -xFaceArea)) self.assertTrue(np.allclose(fluxTF[:,2], yFaceArea) and np.allclose(fluxTF[:,3], -yFaceArea)) aPatch = 10*aPatch fluxTF = transport.computeElementFaceFlux(NPatchCoarse, NPatchCoarse, NCoarseElement, aPatch, uPatch) self.assertTrue(np.allclose(fluxTF[:,0], 10*xFaceArea) and np.allclose(fluxTF[:,1], -10*xFaceArea)) self.assertTrue(np.allclose(fluxTF[:,2], 10*yFaceArea) and np.allclose(fluxTF[:,3], -10*yFaceArea)) aPatch = np.ones(NtFine) NWorldCoarse = np.array(NPatchCoarse) NWorldCoarse[0] = 10*NWorldCoarse[0] fluxTF = transport.computeElementFaceFlux(NWorldCoarse, NPatchCoarse, NCoarseElement, aPatch, uPatch) self.assertTrue(np.allclose(fluxTF[:,0], 10*xFaceArea) and np.allclose(fluxTF[:,1], -10*xFaceArea)) self.assertTrue(np.allclose(fluxTF[:,2], 0.1*yFaceArea) and np.allclose(fluxTF[:,3], -0.1*yFaceArea))
def test_smooth_1d(self): N = np.array([1000]) x = util.pCoordinates(N) e = np.exp(1) mapping = (np.exp(x)-1)/(e-1) inv_mapping = discrete_mapping.invert_cq1_mapping(N, mapping) inv_mapping_should_be = np.log((e-1)*x+1) self.assertTrue(np.allclose(inv_mapping, inv_mapping_should_be, atol=1e-3))
def create(self): NFine = self.world.NWorldFine fine = NFine[0] xpFine = util.pCoordinates(NFine) forward_mapping = np.stack([xpFine[:, 0], xpFine[:, 1]], axis=1) xpFine_shaped = xpFine.reshape(fine + 1, fine + 1, 2) for i in [1, 3]: middle = int((fine + 1) * (i / 4)) intervall = int((fine + 1) / 8) left_2 = middle - int(intervall) right_2 = middle + int(intervall) left, right = left_2, right_2 # print(fine + 1, left, right) part_x = xpFine_shaped[left:right, left_2:right_2, 0] part_y = xpFine_shaped[left:right, left_2:right_2, 1] left_margin_x = np.min(part_x) right_margin_x = np.max(part_x) left_margin_y = np.min(part_y) right_margin_y = np.max(part_y) # print(left_margin_x, right_margin_x, left_margin_y, right_margin_y) epsilon = self.bending_factor / ( right_margin_y - left_margin_y ) # why does this have to be so large??? forward_mapping_partial = np.stack([ xpFine_shaped[left:right, left_2:right_2, 0] + epsilon * (xpFine_shaped[left:right, left_2:right_2, 0] - left_margin_x) * (right_margin_x - xpFine_shaped[left:right, left_2:right_2, 0]) * (xpFine_shaped[left:right, left_2:right_2, 1] - left_margin_y) * (right_margin_y - xpFine_shaped[left:right, left_2:right_2, 1]), xpFine_shaped[left:right, left_2:right_2, 1] ], axis=2) forward_mapping_shaped = forward_mapping.reshape( fine + 1, fine + 1, 2) forward_mapping_shaped[left:right, left_2:right_2, :] = forward_mapping_partial forward_mapping = forward_mapping_shaped.reshape((fine + 1)**2, 2) self.psi = discrete_mapping.MappingCQ1(NFine, forward_mapping)
def test_smooth_2d(self): N = np.array([100, 100]) x = util.pCoordinates(N) e = np.exp(1) mapping = (np.exp([x[:,0] + 0.1*x[:,0]*(1-x[:,0])*x[:,1]*(1-x[:,1]), x[:,1] + 0.1*x[:,1]*(1-x[:,1])*x[:,0]*(1-x[:,0])])-1)/(e-1) mapping = np.transpose(mapping) inv_mapping = discrete_mapping.invert_cq1_mapping(N, mapping) inv_inv_mapping = discrete_mapping.invert_cq1_mapping(N, inv_mapping) self.assertTrue(np.allclose(mapping, inv_inv_mapping, atol=1e-4))
def create(self): NFine = self.world.NWorldFine fine = NFine[0] xpFine = util.pCoordinates(NFine) forward_mapping = np.stack([xpFine[:, 0], xpFine[:, 1]], axis=1) xpFine_shaped = xpFine.reshape(fine + 1, fine + 1, 2) left = int((fine + 1) * self.area[0]) right = int((fine + 1) * self.area[1]) # TODO: enable other left_2 and right_2 left_2, right_2 = left, right print('left_right ', left, right) part_x = xpFine_shaped[left:right, left_2:right_2, 0] part_y = xpFine_shaped[left:right, left_2:right_2, 1] left_margin_x = np.min(part_x) right_margin_x = np.max(part_x) left_margin_y = np.min(part_y) right_margin_y = np.max(part_y) print(left_margin_x, right_margin_x, left_margin_y, right_margin_y) epsilon = self.bending_factor / ( right_margin_y - left_margin_y ) # why does this have to be so large??? forward_mapping_partial = np.stack([ xpFine_shaped[left:right, left_2:right_2, 0] + epsilon * (xpFine_shaped[left:right, left_2:right_2, 0] - left_margin_x) * (right_margin_x - xpFine_shaped[left:right, left_2:right_2, 0]) * (xpFine_shaped[left:right, left_2:right_2, 1] - left_margin_y) * (right_margin_y - xpFine_shaped[left:right, left_2:right_2, 1]), xpFine_shaped[left:right, left_2:right_2, 1] ], axis=2) forward_mapping_shaped = forward_mapping.reshape(fine + 1, fine + 1, 2) forward_mapping_shaped[left:right, left_2:right_2, :] = forward_mapping_partial forward_mapping = forward_mapping_shaped.reshape((fine + 1)**2, 2) self.psi = discrete_mapping.MappingCQ1(NFine, forward_mapping)
def test_boundarypIndexMap(self): N = np.array([3,4,5]) Np = np.prod(N+1) shouldBe = np.setdiff1d(np.arange(Np), util.interiorpIndexMap(N)) self.assertTrue(np.all(util.boundarypIndexMapLarge(N) == shouldBe)) boundaryMap = np.array([[True, False], [True, True], [True, True]]) shouldBe = np.setdiff1d(np.arange(Np), util.interiorpIndexMap(N)) coords = util.pCoordinates(N) shouldBe = np.setdiff1d(shouldBe, np.where(np.logical_and(coords[:,0] == 1, np.logical_and(coords[:,1] != 0, np.logical_and(coords[:,1] != 1, np.logical_and(coords[:,2] != 0, coords[:,2] != 1)))))[0]) self.assertTrue(np.all(util.boundarypIndexMapLarge(N, boundaryMap) == shouldBe)) boundaryMap = np.array([[True, True], [False, True], [True, True]]) shouldBe = np.setdiff1d(np.arange(Np), util.interiorpIndexMap(N)) shouldBe = np.setdiff1d(shouldBe, np.where(np.logical_and(coords[:,0] != 0, np.logical_and(coords[:,0] != 1, np.logical_and(coords[:,1] == 0, np.logical_and(coords[:,2] != 0, coords[:,2] != 1)))))[0]) self.assertTrue(np.all(util.boundarypIndexMapLarge(N, boundaryMap) == shouldBe)) boundaryMap = np.array([[True, True], [False, False], [True, True]]) shouldBe = np.setdiff1d(np.arange(Np), util.interiorpIndexMap(N)) shouldBe = np.setdiff1d(shouldBe, np.where(np.logical_and(coords[:,0] != 0, np.logical_and(coords[:,0] != 1, np.logical_and(coords[:,1] == 0, np.logical_and(coords[:,2] != 0, coords[:,2] != 1)))))[0]) shouldBe = np.setdiff1d(shouldBe, np.where(np.logical_and(coords[:,0] != 0, np.logical_and(coords[:,0] != 1, np.logical_and(coords[:,1] == 1, np.logical_and(coords[:,2] != 0, coords[:,2] != 1)))))[0]) self.assertTrue(np.all(util.boundarypIndexMapLarge(N, boundaryMap) == shouldBe))
def create(self): NFine = self.world.NWorldFine fine = NFine[0] x = util.pCoordinates(NFine) x0 = np.array([0.5, 0.5]) r = np.linalg.norm((x - x0), axis=1) r_min = self.r_min r_bounded = np.maximum(r, r_min) / r_min tapering = np.prod(np.sin(np.pi * x), axis=1) displacement = np.column_stack([ tapering * self.displacement_factor * (r_bounded)**-2, tapering * self.displacement_factor * (r_bounded)**-2 ]) self.psi = discrete_mapping.MappingCQ1(NFine, x + displacement)
def test_stiffnessMatrixForVaryingDiagonalA(self): N = np.array([3, 4, 5], dtype='int64') AConstant1 = np.array([[1.0, 0, 0], [0, 2.0, 0], [0, 0, 1.0]]) AConstant2 = np.array([[1.0, 0, 0], [0, 7.0, 0], [0, 0, 1.0]]) aPatchCube = np.tile(AConstant1, [3, 4, 5, 1, 1]) aPatchCube[:, :2, :, :, :] = AConstant2 aPatch = np.reshape(aPatchCube, [3 * 4 * 5, 3, 3]) ALocTensor = fem.localStiffnessTensorMatrixCoefficient(N) A = fem.assemblePatchMatrix(N, ALocTensor, aPatch) # Create the functions x1, x2 and x3 pc = util.pCoordinates(N) x1 = pc[:, 0] x2 = pc[:, 1] x3 = pc[:, 2] self.assertTrue(np.isclose(np.dot(x1, A * x1), 1.0)) self.assertTrue(np.isclose(np.dot(x2, A * x2), 0.5 * (2. + 7.))) self.assertTrue(np.isclose(np.dot(x3, A * x3), 1.0))
def computeTransformation(self, aFine, f_ref): assert (len(aFine) == np.prod(self.world.NWorldFine)) assert (len(f_ref) == np.prod(self.world.NWorldFine + 1)) assert (self.psi) psi = self.psi NFine = self.world.NWorldFine xtFine = util.tCoordinates(NFine) a_trans = np.einsum('tij, t, tkj, t -> tik', psi.Jinv(xtFine), aFine, psi.Jinv(xtFine), psi.detJ(xtFine)) xpFine = util.pCoordinates(NFine) xpFine_pert = self.psi.evaluate(xpFine) f_trans = func.evaluateCQ1(NFine, f_ref, xpFine_pert) f_trans = np.einsum('t, t -> t', f_trans, psi.detJ(xpFine_pert)) return a_trans, f_trans
def computePerturbation(self, aFine, f_ref): assert (self.psi) assert (len(aFine) == np.prod(self.world.NWorldFine)) NFine = self.world.NWorldFine # Elements xtFine = util.tCoordinates(NFine) xtFine_ref = self.psi.inverse_evaluate(xtFine) xtFine_pert = self.psi.evaluate(xtFine_ref) # Nodes xpFine = util.pCoordinates(NFine) xpFine_ref = self.psi.inverse_evaluate(xpFine) xpFine_pert = self.psi.evaluate(xpFine_ref) self.checkInvertible(xpFine_pert, xpFine) aFine_pert = func.evaluateDQ0(NFine, aFine, xtFine_ref) # f_pert = func.evaluateCQ1(NFine, f_ref, xpFine_ref) return aFine_pert, f_ref
def d3solextra(N, s, fig, ax, ymin, ymax): ''' function for 2d fem example ''' xp = util.pCoordinates(N) X = xp[0:, 1:].flatten() Y = xp[0:, :1].flatten() X = np.unique(X) Y = np.unique(Y) X, Y = np.meshgrid(X, Y) uLodFine = s.reshape(N + 1) # Plot the surface. surf = ax.plot_surface(X, Y, uLodFine, cmap=cm.jet) ymin, ymax = ax.set_zlim() ax.set_zlim(ymin, ymax) ax.set_zlabel('$z$') ax.set_xlabel('$x$') ax.set_ylabel('$y$') ax.zaxis.set_major_locator(LinearLocator(10)) ax.axis('off')
import matplotlib.pyplot as plt from gridlod import util, fem, coef, interp from gridlod.world import World import lod_wave # fine mesh parameters fine = 1024 NFine = np.array([fine]) NpFine = np.prod(NFine + 1) boundaryConditions = np.array([[0, 0]]) world = World(NFine, NFine // NFine, boundaryConditions) NWorldFine = world.NWorldCoarse * world.NCoarseElement # fine grid elements and nodes xt = util.tCoordinates(NFine).flatten() xp = util.pCoordinates(NFine).flatten() # time step parameters tau = 0.1 numTimeSteps = 10 # ms coefficients epsA = 2 ** (-4) epsB = 2 ** (-6) aFine = (2 - np.sin(2 * np.pi * xt / epsA)) ** (-1) bFine = (2 - np.cos(2 * np.pi * xt / epsB)) ** (-1) k_0 = np.inf k_1 = k_0 N = 16
def test_1d(self): # Example from Peterseim, Variational Multiscale Stabilization and the Exponential Decay of correctors, p. 2 # Two modifications: A with minus and u(here) = 1/4*u(paper). NFine = np.array([3200]) NpFine = np.prod(NFine + 1) NList = [10, 20, 40, 80, 160] epsilon = 1024. / NFine epsilon = 1. / 320 k = 2 pi = np.pi xt = util.tCoordinates(NFine).flatten() xp = util.pCoordinates(NFine).flatten() #aFine = (2 + np.cos(2*pi*xt/epsilon))**(-1) aFine = (2 - np.cos(2 * pi * xt / epsilon))**(-1) uSol = 4 * (xp - xp**2) - 4 * epsilon * ( 1 / (4 * pi) * np.sin(2 * pi * xp / epsilon) - 1 / (2 * pi) * xp * np.sin(2 * pi * xp / epsilon) - epsilon / (4 * pi**2) * np.cos(2 * pi * xp / epsilon) + epsilon / (4 * pi**2)) uSol = uSol / 4 previousErrorCoarse = np.inf previousErrorFine = np.inf for N in NList: NWorldCoarse = np.array([N]) NCoarseElement = NFine / NWorldCoarse boundaryConditions = np.array([[0, 0]]) world = World(NWorldCoarse, NCoarseElement, boundaryConditions) xpCoarse = util.pCoordinates(NWorldCoarse).flatten() NpCoarse = np.prod(NWorldCoarse + 1) IPatchGenerator = lambda i, N: interp.L2ProjectionPatchMatrix( i, N, NWorldCoarse, NCoarseElement, boundaryConditions) aCoef = coef.coefficientFine(NWorldCoarse, NCoarseElement, aFine) pglod = pg.PetrovGalerkinLOD(world, k, IPatchGenerator, 0) pglod.updateCorrectors(aCoef, clearFineQuantities=False) KFull = pglod.assembleMsStiffnessMatrix() MFull = fem.assemblePatchMatrix(NWorldCoarse, world.MLocCoarse) free = util.interiorpIndexMap(NWorldCoarse) f = np.ones(NpCoarse) bFull = MFull * f KFree = KFull[free][:, free] bFree = bFull[free] xFree = sparse.linalg.spsolve(KFree, bFree) basis = fem.assembleProlongationMatrix(NWorldCoarse, NCoarseElement) basisCorrectors = pglod.assembleBasisCorrectors() modifiedBasis = basis - basisCorrectors xFull = np.zeros(NpCoarse) xFull[free] = xFree uLodCoarse = basis * xFull uLodFine = modifiedBasis * xFull AFine = fem.assemblePatchMatrix(NFine, world.ALocFine, aFine) MFine = fem.assemblePatchMatrix(NFine, world.MLocFine) newErrorCoarse = np.sqrt( np.dot(uSol - uLodCoarse, MFine * (uSol - uLodCoarse))) newErrorFine = np.sqrt( np.dot(uSol - uLodFine, AFine * (uSol - uLodFine))) self.assertTrue(newErrorCoarse < previousErrorCoarse) self.assertTrue(newErrorFine < previousErrorFine)
def computeFunctions(): pc = util.pCoordinates(NFine) x1 = pc[:,0] x2 = pc[:,1] return [x1, 2*x2]
aFine_ref_shaped = CoefClass.SpecificMove(Number=np.arange(0, 10), steps=4, Right=1) aFine_ref = aFine_ref_shaped.flatten() number_of_channels = len(CoefClass.ShapeRemember) # Discrete mapping Nmapping = np.array([int(fine), int(fine)]) size_of_an_element = 1. / fine walk_with_perturbation = size_of_an_element channels_position_from_zero = space channels_end_from_zero = channels_position_from_zero + thick xpFine = util.pCoordinates(NFine) xtFine = util.tCoordinates(NFine) NWorldCoarse = np.array([N, N]) boundaryConditions = np.array([[0, 0], [0, 0]]) NCoarseElement = NFine // NWorldCoarse world = World(NWorldCoarse, NCoarseElement, boundaryConditions) every_psi_was_valid = [] k = 3 #I want to know the exact places of the channels ref_array = aFine_ref_shaped[0] def create_psi_function():
def computeFunctions(): pc = util.pCoordinates(world.NWorldFine) x1 = pc[:,0] x2 = pc[:,1] return [x1]
def test_pgtransport(self): NWorldCoarse = np.array([16, 16]) NCoarseElement = np.array([8, 8]) NWorldFine = NWorldCoarse * NCoarseElement boundaryConditions = np.array([[1, 1], [0, 0]]) d = 2 world = World(NWorldCoarse, NCoarseElement, boundaryConditions) # Load coefficient aLogBase = np.loadtxt( os.path.dirname(os.path.realpath(__file__)) + '/data/randomfield64x64') #aBase = np.loadtxt(os.path.dirname(os.path.realpath(__file__)) + '/data/upperness_x.txt') #aBase = aBase[:60*220] #aLogBase = np.random.rand(128*128) aBase = np.exp(3 * aLogBase) drawCoefficient(NWorldFine, aBase) plt.title('a') # Compute coordinates coordsFine = util.pCoordinates(NWorldFine) xFine = coordsFine[:, 0] yFine = coordsFine[:, 1] # Compute fixed and free dofs allDofs = np.arange(world.NpFine) fixed = util.boundarypIndexMap(NWorldFine, boundaryConditions == 0) free = np.setdiff1d(allDofs, fixed) # Compute matrices AFull = fem.assemblePatchMatrix(NWorldFine, world.ALocFine, aBase) A = AFull[free][:, free] # Compute rhs gFine = 1 - yFine bFull = -AFull * gFine b = bFull[free] # Solve fine system u0Free = sparse.linalg.spsolve(A, b) u0Full = np.zeros(world.NpFine) u0Full[free] = u0Free uFull = u0Full + gFine ## First, compute flux on fine mesh def computeAvgVelocitiesTF(NFluxElement): fluxWorld = World(NWorldFine / NFluxElement, NFluxElement, boundaryConditions) if True: avgFluxTF = transport.computeHarmonicMeanFaceFlux( fluxWorld.NWorldCoarse, fluxWorld.NWorldCoarse, NFluxElement, aBase, uFull) avgFluxTF = transport.computeAverageFaceFlux( fluxWorld.NWorldCoarse, avgFluxTF) conservativeFluxTF = transport.computeConservativeFlux( fluxWorld, avgFluxTF) if False: avgFluxTF = transport.computeElementFaceFlux( fluxWorld.NWorldCoarse, fluxWorld.NWorldCoarse, NFluxElement, aBase, uFull) avgFluxTF = transport.computeAverageFaceFlux( fluxWorld.NWorldCoarse, avgFluxTF) return avgFluxTF, conservativeFluxTF avgFluxTF, conservativeFluxTF = computeAvgVelocitiesTF(NCoarseElement) avgFluxtf, conservativeFluxtf = computeAvgVelocitiesTF( np.ones_like(NCoarseElement)) def fractionalFlow(s): return s**3 boundarys = np.array([[0, 0], [1, 0]]) sT = np.zeros(world.NtCoarse) st = np.zeros(world.NtFine) nTime = 1e5 endTime = 1 dTime = endTime / float(nTime) volt = np.prod(1. / world.NWorldFine) volT = np.prod(1. / world.NWorldCoarse) plt.figure() h1 = plt.gcf().number plt.figure() h2 = plt.gcf().number plt.figure() h3 = plt.gcf().number for timeStep in np.arange(nTime): def computeElementNetFluxT(NFluxElement, avgFluxTF, sT): fluxWorld = World(NWorldFine / NFluxElement, NFluxElement, boundaryConditions) netFluxT = transport.computeElementNetFlux( fluxWorld, avgFluxTF, sT, boundarys, fractionalFlow) return netFluxT netFluxT = computeElementNetFluxT(NCoarseElement, conservativeFluxTF, sT) netFluxt = computeElementNetFluxT(np.ones_like(NCoarseElement), conservativeFluxtf, st) sT = sT + dTime / volT * netFluxT #sT[sT > 1] = 1. #sT[sT < 0] = 0. st = st + dTime / volt * netFluxt #st[st > 1] = 1. #st[st < 0] = 0. if timeStep % 1000 == 0 or timeStep == nTime - 1: plt.figure(h1) drawSaturation(NWorldCoarse, sT) plt.title('sT') plt.gcf().canvas.draw() plt.figure(h2) drawSaturation(NWorldFine, st) plt.title('st') plt.gcf().canvas.draw() plt.figure(h3) stProjected = projectSaturation(NWorldCoarse, NCoarseElement, st) drawSaturation(NWorldCoarse, stProjected) plt.title('st projected') plt.gcf().canvas.draw() print np.sqrt(np.mean((stProjected - sT)**2)) plt.pause(0.0001) plt.show()
def create(self): NFine = self.world.NWorldFine fine = NFine[0] xpFine = util.pCoordinates(NFine) epsilonT = [] forward_mapping = np.stack([xpFine[:, 0], xpFine[:, 1]], axis=1) xpFine_shaped = xpFine.reshape(fine + 1, fine + 1, 2) left, right = 0, fine + 1 for c in range(self.number_of_channels): count = 0 for i in range(np.size(self.ref_array)): if self.ref_array[i] == 1: count += 1 if count == (c + 1) * self.thick: begin = i + 1 - self.space // 2 end = i + 1 + self.thick + self.space // 2 break print(begin, end) left_2, right_2 = begin, end if c == 3: epsilon = 25 # elif c == 4: # epsilon = -25 # elif c % 2 == 0: # epsilon = 0 else: epsilon = np.random.uniform(-10, 10) part_x = xpFine_shaped[left:right, left_2:right_2, 0] part_y = xpFine_shaped[left:right, left_2:right_2, 1] left_margin_x = np.min(part_x) right_margin_x = np.max(part_x) left_margin_y = np.min(part_y) right_margin_y = np.max(part_y) print(left_margin_x, right_margin_x, left_margin_y, right_margin_y) forward_mapping_partial = np.stack([ xpFine_shaped[left:right, left_2:right_2, 0] + epsilon * (xpFine_shaped[left:right, left_2:right_2, 0] - left_margin_x) * (right_margin_x - xpFine_shaped[left:right, left_2:right_2, 0]) * (xpFine_shaped[left:right, left_2:right_2, 1] - left_margin_y) * (right_margin_y - xpFine_shaped[left:right, left_2:right_2, 1]), xpFine_shaped[left:right, left_2:right_2, 1] ], axis=2) forward_mapping_shaped = forward_mapping.reshape( fine + 1, fine + 1, 2) forward_mapping_shaped[left:right, left_2:right_2, :] = forward_mapping_partial epsilonT.append(epsilon) forward_mapping = forward_mapping_shaped.reshape((fine + 1)**2, 2) print('Those are the results of the shift epsilon', epsilonT) self.psi = discrete_mapping.MappingCQ1(NFine, forward_mapping)
def create(self): NFine = self.world.NWorldFine fine = NFine[0] xpFine = util.pCoordinates(NFine) Nmapping = np.array([int(fine), int(fine)]) size_of_an_element = 1. / fine print('the size of a fine element is {}'.format(size_of_an_element)) walk_with_perturbation = size_of_an_element epsilonT = [] cq1 = np.zeros((int(fine) + 1, int(fine) + 1)) random.seed(20) cs = np.random.randint(0, 2, self.number_of_channels) cs = [c * random.sample([-1, 1], 1)[0] for c in cs] ## or manually cs[2] = 0 cs[3] = -1 cs[4] = 0 cs[5] = 0 print(cs) last_value = 0 for i, c in enumerate(cs): platform = self.space // 2 + 2 * self.thick begin = platform // 2 + i * (self.space + self.thick) end = begin + self.space - platform + self.thick epsilon = c * walk_with_perturbation epsilonT.append(epsilon) walk = epsilon - last_value constant_length = platform + self.thick increasing_length = end - begin for i in range(increasing_length): cq1[:, begin + i] = last_value + (i + 1) / increasing_length * walk for i in range(constant_length): cq1[:, begin + increasing_length + i] = epsilon last_value = epsilon # ending begin += self.space + self.thick end = begin + self.space - platform + self.thick epsilon = 0 walk = epsilon - last_value increasing_length = end - begin for i in range(increasing_length): cq1[:, begin + i] = last_value + (i + 1) / increasing_length * walk if self.plot_mapping: plt.plot(np.arange(0, fine + 1), cq1[self.space, :], label='$id(x) - \psi(x)$') plt.title('Domain mapping') plt.legend() plt.show() print('These are the results of the shift epsilon', epsilonT) cq1 = cq1.flatten() alpha = 1. for_mapping = np.stack( (xpFine[:, 0] + alpha * func.evaluateCQ1(Nmapping, cq1, xpFine), xpFine[:, 1]), axis=1) self.psi = discrete_mapping.MappingCQ1(NFine, for_mapping)
#two examples of the offline coeffs Nepsilon = np.array([64, 64]) NFine = np.array([256, 256]) NCoarse = np.array([32, 32]) k = 2 alpha = 0.1 beta = 1. incl_bl = np.array([0.25, 0.25]) incl_tr = np.array([0.75, 0.75]) NCoarseElement = NFine // NCoarse world = World(NCoarse, NCoarseElement, None) middle = world.NWorldCoarse[1] // 2 * world.NWorldCoarse[ 0] + world.NWorldCoarse[0] // 2 patch = lod_periodic.PatchPeriodic(world, k, middle) xpFine = util.pCoordinates(world.NWorldCoarse, patch.iPatchWorldCoarse, patch.NPatchCoarse) aRefList_rand = build_coefficient.build_checkerboardbasis( patch.NPatchCoarse, Nepsilon // NCoarse, world.NCoarseElement, alpha, beta) fig = plt.figure() for ii in range(4): ax = fig.add_subplot(2, 2, ii + 1) apertGrid = aRefList_rand[-1 + ii].reshape(patch.NPatchFine, order='C') im = ax.imshow(apertGrid, origin='lower_left', extent=(xpFine[:, 0].min(), xpFine[:, 0].max(), xpFine[:, 1].min(), xpFine[:, 1].max()), cmap='Greys') plt.show()
def create(self): NFine = self.world.NWorldFine fine = NFine[0] xpFine = util.pCoordinates(NFine) number_of_perturbed_channels = 4 now = 0 count = 0 for i in range(np.size(self.ref_array)): if self.ref_array[i] == 1: count += 1 if count == 8 * self.thick: # at the 8ths shape (which is the last dot in one line, the cq starts) begin = i + 1 break count = 0 for i in range(np.size(self.ref_array)): if self.ref_array[i] == 1: count += 1 if count == 13 * self.thick - 3: # it ends after the last channel end = i break # Discrete mapping Nmapping = np.array([int(fine), int(fine)]) cq1 = np.zeros((int(fine) + 1, int(fine) + 1)) # I only want to perturb on the fine mesh. size_of_an_element = 1. / fine walk_with_perturbation = size_of_an_element channels_position_from_zero = self.space channels_end_from_zero = channels_position_from_zero + self.thick # The next only have the purpose to make the psi invertible. increasing_length = (end - begin) // (number_of_perturbed_channels + 1) - self.thick - 2 constant_length = (end - begin) - increasing_length * 2 maximum_walk = (increasing_length - 6) * walk_with_perturbation walk_with_perturbation = maximum_walk for i in range(increasing_length): cq1[:, begin + 1 + i] = (i + 1) / increasing_length * walk_with_perturbation cq1[:, begin + increasing_length + i + constant_length] = walk_with_perturbation - ( i + 1) / increasing_length * walk_with_perturbation for i in range(constant_length): cq1[:, begin + increasing_length + i] = walk_with_perturbation # Check what purtubation I have if self.plot_mapping: plt.figure('DomainMapping') plt.plot(np.arange(0, fine + 1), cq1[self.space, :], label='$id(x) - \psi(x)$') plt.title('Domain mapping') plt.legend() cq1 = cq1.flatten() xpFine = util.pCoordinates(NFine) alpha = 1. for_mapping = np.stack( (xpFine[:, 0] + alpha * func.evaluateCQ1(Nmapping, cq1, xpFine), xpFine[:, 1]), axis=1) self.psi = discrete_mapping.MappingCQ1(NFine, for_mapping)