def test_failsafe_sweep(): interpolate_expression = Expression('x[0]', degree=1) mesh = UnitSquareMesh(5, 5) V = FunctionSpace(mesh, "DG", 1) v = Function(V) v.assign(interpolate_expression) np_min, np_max = 1, 2 np_failsafe = 4 # Initialize particles x = RandomRectangle(Point(0.0, 0.0), Point(1., 1.)).generate([100, 100]) s = assign_particle_values(x, interpolate_expression) # Broadcast to other procs x = comm.bcast(x, root=0) s = comm.bcast(s, root=0) property_idx = 1 p = particles(x, [s], mesh) AD = AddDelete(p, np_min, np_max, [v]) AD.do_sweep_failsafe(np_failsafe) # Must recover linear lstsq_rho = l2projection(p, V, property_idx) lstsq_rho.project(v.cpp_object()) error = sqrt( assemble( (v - interpolate_expression) * (v - interpolate_expression) * dx)) assert len(p.positions() == mesh.num_cells() * np_failsafe) assert error < 1e-12
def test_l2projection_bounded_3D(polynomial_order, lb, ub): xmin, ymin, zmin = 0., 0., 0. xmax, ymax, zmax = 1., 1., 1. nx = 10 interpolate_expression = Ball(0.15, [0.5, 0.5, 0.5], degree=3, lb=lb, ub=ub) property_idx = 1 mesh = BoxMesh(Point(xmin, ymin, zmin), Point(xmax, ymax, zmax), nx, nx, nx) V = FunctionSpace(mesh, "DG", polynomial_order) x = RegularBox(Point(0., 0., 0.), Point(1., 1., 1.)).generate([100, 100, 100]) s = assign_particle_values(x, interpolate_expression) # Just make a complicated particle, possibly with scalars and vectors mixed p = particles(x, [s], mesh) vh = Function(V) lstsq_rho = l2projection(p, V, property_idx) lstsq_rho.project(vh.cpp_object(), lb, ub) # Assert if it stays within bounds assert np.any(vh.vector().get_local() < ub + 1e-12) assert np.any(vh.vector().get_local() > lb - 1e-12)
def test_l2projection_bounded(polynomial_order, lb, ub): # Test l2 projection if it stays within bounds given by lb and ub interpolate_expression = SlottedDisk(radius=0.15, center=[0.5, 0.5], width=0.05, depth=0., degree=3, lb=lb, ub=ub) xmin, xmax = 0., 1. ymin, ymax = 0., 1. property_idx = 5 mesh = RectangleMesh(Point(xmin, ymin), Point(xmax, ymax), 40, 40) V = FunctionSpace(mesh, "DG", polynomial_order) x = RandomRectangle(Point(xmin, ymin), Point(xmax, ymax)).generate([500, 500]) s = assign_particle_values(x, interpolate_expression) # Just make a complicated particle, possibly with scalars and vectors mixed p = particles(x, [x, s, x, x, s], mesh) vh = Function(V) lstsq_rho = l2projection(p, V, property_idx) lstsq_rho.project(vh, lb, ub) # Assert if it stays within bounds assert np.all(vh.vector().get_local() < ub + 1e-12) assert np.all(vh.vector().get_local() > lb - 1e-12)
def test_l2projection(polynomial_order, in_expression): # Test l2 projection for scalar and vector valued expression interpolate_expression = Expression(in_expression, degree=3) xmin, xmax = 0., 1. ymin, ymax = 0., 1. property_idx = 5 mesh = RectangleMesh(Point(xmin, ymin), Point(xmax, ymax), 40, 40) if len(interpolate_expression.ufl_shape) == 0: V = FunctionSpace(mesh, "DG", polynomial_order) elif len(interpolate_expression.ufl_shape) == 1: V = VectorFunctionSpace(mesh, "DG", polynomial_order) v_exact = Function(V) v_exact.interpolate(interpolate_expression) x = RandomRectangle(Point(xmin, ymin), Point(xmax, ymax)).generate([500, 500]) s = assign_particle_values(x, interpolate_expression) # Just make a complicated particle, possibly with scalars and vectors mixed p = particles(x, [x, s, x, x, s], mesh) vh = Function(V) lstsq_rho = l2projection(p, V, property_idx) lstsq_rho.project(vh) error_sq = abs(assemble(dot(v_exact - vh, v_exact - vh) * dx)) assert error_sq < 1e-15
def test_l2_projection_3D(polynomial_order, in_expression): xmin, ymin, zmin = 0.0, 0.0, 0.0 xmax, ymax, zmax = 1.0, 1.0, 1.0 nx = 25 property_idx = 1 mesh = BoxMesh(Point(xmin, ymin, zmin), Point(xmax, ymax, zmax), nx, nx, nx) interpolate_expression = Expression(in_expression, degree=3) if len(interpolate_expression.ufl_shape) == 0: V = FunctionSpace(mesh, "DG", polynomial_order) elif len(interpolate_expression.ufl_shape) == 1: V = VectorFunctionSpace(mesh, "DG", polynomial_order) v_exact = Function(V) v_exact.assign(interpolate_expression) x = RandomBox(Point(0.0, 0.0, 0.0), Point(1.0, 1.0, 1.0)).generate([4, 4, 4]) s = assign_particle_values(x, interpolate_expression) # Just make a complicated particle, possibly with scalars and vectors mixed p = particles(x, [s], mesh) # Do AddDelete sweep AD = AddDelete(p, 13, 15, [v_exact]) AD.do_sweep() vh = Function(V) lstsq_vh = l2projection(p, V, property_idx) lstsq_vh.project(vh.cpp_object()) error_sq = abs(assemble(dot(v_exact - vh, v_exact - vh) * dx)) if comm.Get_rank() == 0: assert error_sq < 1e-13
def update(self,u,dt,p,remesh=True,remesh_elastic=False): """ Update positions and properties of traces using 1st order Euler forward The RK 4 scheme is fourth order in space, but first order in time because we interpolate the velocities instead of solving for new velocities at each step """ # Step 1, establish our function spaces for projections Q = self.mesh.Q # Linear elements Q0 = FunctionSpace(self.mesh.mesh, "DG", 0) # Discontinuous elements epsII=self.epsII eta = self.eta eta_visc = self.eta_visc eta_plas = self.eta_plas Vdg = FunctionSpace(self.mesh.mesh, 'DG',1) # Variables to store strain and temp strain, temp = Function(Vdg), Function(Vdg) #lstsq_strain = l2projection(p, Vdg, 1) # First variable??? #lstsq_strain.project_mpm(strain) # Projection is stored in phih0 lstsq_temp = l2projection(p, Vdg, 2) # First variable??? lstsq_temp.project(temp,253.15,273.15) # Projection is stored in phih0 dt_min = 0.5*project(CellDiameter(self.mesh.mesh)/sqrt(dot(u, u)),Q0).compute_vertex_values() dt_m = np.minimum(dt,np.min(dt_min)) #epsII = project(epsII,Vdg) p.interpolate(epsII,3) self.epsII = epsII (xp , pstrain , ptemp, pepsII) = (p. return_property(mesh , 0) , p. return_property(mesh , 1) , p. return_property(mesh , 2), p. return_property(mesh , 3)) pepsII = np.maximum(pepsII,0.0) self.pepsII = pepsII self.ptemp = ptemp self.pstrain = pstrain #""" if self.method==1: deps_dt = Function(Vdg) deps_dt.vector()[:] = self.visc_func.strain_update(epsII.vector().get_local(),temp.vector().get_local(),strain.vector().get_local(),dt_m) deps_dt_eff = Function(Vdg) #if self.deps_dt == None: p.interpolate(deps_dt,1) pstrain_new = np.maximum(p. return_property(mesh , 1) + pstrain,0.0) #self.deps_dt = deps_dt # else: # if self.deps_dt_old == None: # deps_dt_old = interpolate(self.deps_dt,Vdg) # deps_dt_eff.vector()[:]=1.5*deps_dt.vector().get_local()-0.5*deps_dt_old.vector().get_local() # p.interpolate(deps_dt_eff,1) # self.deps_dt = deps_dt # # self.deps_dt_old = deps_dt_old # else: # if self.deps_dt_older==None: # deps_dt_older = interpolate(self.deps_dt_old,Vdg) # deps_dt_old = interpolate(self.deps_dt,Vdg) # deps_dt_eff.vector()[:]=23./12*deps_dt.vector().get_local()-16./12*deps_dt_old.vector().get_local()+5./12*deps_dt_older.vector().get_local() # p.interpolate(deps_dt_eff,1) # self.deps_dt = deps_dt # self.deps_dt_old = deps_dt_old # self.deps_dt_older = deps_dt_older # else: # deps_dt_old = interpolate(self.deps_dt,Vdg) # deps_dt_older = interpolate(self.deps_dt_old,Vdg) # deps_dt_oldist = interpolate(self.deps_dt_older,Vdg) # deps_dt_eff.vector()[:]=(55./24*deps_dt.vector().get_local()-59./24*deps_dt_old.vector().get_local()+37./24*deps_dt_older.vector().get_local() -9./24*deps_dt_oldist.vector().get_local()) # p.interpolate(deps_dt_eff,1) # self.deps_dt = deps_dt # self.deps_dt_old = deps_dt_old # self.deps_dt_older = deps_dt_older else: pstrain_new = self.visc_func.update(pepsII,ptemp,pstrain,dt_m) pstrain_new = np.maximum(pstrain_new,0.0) #pstrain_new[xp[:,0]<1e3]=0.0 p.change_property(pstrain_new,1) strain = Function(Vdg) lstsq_strain = l2projection(p, Vdg, 1) # First variable??? lstsq_strain.project_mpm(strain) # Projection is stored in phih0 #self.strain = strain print('Starting to remesh') if remesh == True: if remesh_elastic==False: #Temp = self.temp_model.advect_diffuse(T0,u,dt,self.scalar,self.boundary_parts,self.mesh.mesh) #self.Temp = Temp if self.calving_front == False: # Update model mesh with new mesh new_mesh=self.remesh(u,dt_m) u_eff = u print('Finished remeshing') else: # Update mesh coordinates to new coordinates u_elastic=self.remesh_elastic(u,dt_m) #u_eff = u-u_elastic #u_eff = project(u-u_elastic,self.vector2) #Temp = self.temp_model.advect_diffuse(T0,u-u_elastic,dt,self.scalar,self.boundary_parts,self.mesh.mesh) #self.Temp = Temp ux,uz=u_elastic.split() # Update mesh coordinates coords = self.mesh.mesh.coordinates() coords[:,0]=coords[:,0]+ux.compute_vertex_values()*dt_m coords[:,1]=coords[:,1]+uz.compute_vertex_values()*dt_m # And update bounding box tree self.mesh.mesh.bounding_box_tree().build(self.mesh.mesh) self.markBoundaries() # Now remesh new_mesh=self.mesh.remesh(max_length=self.mesh.length) print('Finished remeshing') Qnew=FunctionSpace(new_mesh.mesh, "CG", 1) Tnew = Function(Qnew) self.set_mesh(new_mesh) length = self.mesh.length else: #xm,zm = self.tracers.get_coords() x,z = self.mesh.get_coords() xmax = np.max(x) u_elastic=self.remesh_elastic(u,dt_m) u_eff = u-u_elastic u_eff = project(u-u_elastic,self.vector2) ux,uz=u_elastic.split() # Update mesh coordinates coords = self.mesh.mesh.coordinates() coords[:,0]=coords[:,0]+ux.compute_vertex_values()*dt_m coords[:,1]=coords[:,1]+uz.compute_vertex_values()*dt_m # And update bounding box tree self.mesh.mesh.bounding_box_tree().build(self.mesh.mesh) self.markBoundaries() length = xmax*2.0 #self.tracers.set_mesh(self.mesh) else: length = self.mesh.length self.tempModel.set_mesh(self.mesh.mesh) self.markBoundaries() #Temp = self.tempModel.update(u_eff,dt_m,self.boundary_parts) if self.u_k!=None: self.u_k = interpolate(self.u_k,self.vector2) self.strain = strain self.temp = temp self.epsII = epsII self.u_k = interpolate(self.u_k,self.vector2) #ap = advect_rk3(p, self.vector2, u, "open") #ap.do_step(dt_m) return dt_m
def solve(self,p,dt=3600,tolerance=1e-6,relax_param=1.0): """ Picard iteration to solve system of equations p is particles """ # Normal vector z_vector = interpolate(Constant((0.0, 1.0)), self.vector2) # Vertical vector pointing upwards # Normal and tangent unit vectors N = FacetNormal(self.mesh.mesh) normE = as_vector([N[0], N[1]]) tanE = as_vector([-N[1], N[0]]) # Mark boundaries and subdomains self.markBoundaries() #Define functio space for viscosity coefficients??? Q = self.mesh.Q # Extract strain and temperature as mesh functions # Function spaces -- should be defined once?? Vdg = FunctionSpace(self.mesh.mesh, 'DG',1) Vcg = FunctionSpace(self.mesh.mesh, 'DG',1) # Variables to store strain and temp strain, temp = Function(Vdg), Function(Vcg) lstsq_temp = l2projection(p, Vcg, 2) lstsq_temp.project(temp) lstsq_strain = l2projection(p, Vdg, 1) # First variable??? lstsq_strain.project_mpm(strain) # Projection is stored in phih0 temp = self.tempModel.Temp u_old = Function(self.vector2) if self.u_k != None: u_k = self.u_k u_old.assign(u_k) else: u_k = interpolate(Constant((1E-15, 1E-15)), self.vector2) (q,v) = TestFunctions(self.system) (p, u) = TrialFunctions(self.system) err_rel = 1.0 # error measure ||u-u_k|| and ||p-p_k|| count = 0 # iteration counter maxit = self.maxit # number of iterations allowed visc=self.visc_func #Q=FunctionSpace(self.mesh.mesh, "CG", 2) temp=interpolate(temp,Q) epsII=self.effective_strain_rate_squared(u_k,Q) eta = visc(epsII ,temp,strain,Q) eta_visc = self.visc_func.ductile_visc(epsII ,temp,Q) # Time step needs to be a Constant to avoid recompiling every time step water_drag = Constant(self.water_drag*self.rho_w/material.time_factor**2)*sqrt(dot(u_k,u_k)) # Set friction coefficient m = self.m u_b = dot(tanE,u_k) u_b_norm = sqrt(u_b**2) Neff = Constant(1.0) # Don't use effective pressure in sliding law . . . for now tau_y = self.visc_func.cohes(strain,Q) friction = Neff*Constant(self.friction/material.time_factor**m)*(sqrt(u_b_norm**2 + 1e-16**2))**(m-1) friction = (1./friction + u_b_norm/tau_y)**(-1.0) lateral_drag = Constant(self.lateral_drag/material.time_factor**m)*(sqrt(u_k**2 + 1e-16**2))**(m-1) lateral_drag = (1./lateral_drag + sqrt(dot(u_k,u_k))/self.visc_func.yield_strength)**(-1.0) bcs = self.BCS dt_step = Constant(dt) elastic = Constant(self.elastic_coeff_rock) stokes = inner(Constant(self.rho_i/material.time_factor)*(u-u_old)/dt_step,v)*dx \ + inner(2*eta*epsilon(u), epsilon(v))*dx \ - inner(nabla_div(v), p)*dx \ + inner(nabla_div(u), q)*dx \ + inner(self.below_sea_level*self.rho_w*self.g*dot((dt_step*u)*np.abs(N[1]), z_vector)*z_vector, v)*self.DS(5) \ + inner(elastic*dot((dt_step*u), normE), dot(v,normE))*self.DS(1) \ + inner(self.water_pressure*normE, v)*self.DS(5) \ + inner((self.GROUND_PRESSURE_SCALAR+self.water_pressure)*normE, v)*self.DS(1) \ + inner(dot(v, tanE), friction*dot(u, tanE))*self.DS(1) \ + inner(self.below_sea_level*water_drag*u, v)*self.DS(5) \ + inner(self.water_pressure*normE, v)*self.DS(6) \ + inner(self.below_sea_level*self.rho_w*self.g*dot((dt_step*u)*np.abs(N[1]), z_vector)*z_vector, v)*self.DS(6) \ + inner(self.below_sea_level*water_drag*u, v)*self.DS(6) \ + inner(v,lateral_drag*u)*dx \ + inner(self.buttressing, v[0])*self.DS(6) \ - inner(self.f, v)*dx \ # Solves problem . . . . w = Function(self.system) problem = LinearVariationalProblem(lhs(stokes), rhs(stokes), w, bcs) solver = LinearVariationalSolver(problem) prm = solver.parameters info(prm, False) prm['linear_solver'] = 'mumps' #prm['linear_solver'] = 'lu' while ((float(err_rel) > tolerance) and (count < maxit)): solver.solve() self.u_p = w p, u = w.split(deepcopy=True) du = u.vector().get_local()-u_k.vector().get_local() err = np.linalg.norm(du) err_rel = err/norm(u) print("count = %d, relative error = %G, absolute error = %G" % (count, err_rel,err)) alpha = self.alpha u.vector()[:]=alpha*u.vector()[:]+(1-alpha)*u_k.vector()[:] # Assign new variables to old guess assign(u_k, u) count += 1 # Kick out if the absolute error in the velocity is less than 0.1 m/a if err<1e-3/material.secpera: break ux,uz = u.split() speed = np.sqrt(ux.compute_vertex_values()**2+uz.compute_vertex_values()**2) print('Max viscous speed',np.max(speed)) epsII=self.effective_strain_rate_squared(u,Q) self.eta=self.visc_func(epsII ,temp,strain,Q) self.eta_visc=self.visc_func.ductile_visc(epsII ,temp,Q) self.eta_plas=self.visc_func.plastic_visc(epsII ,strain,Q) #self.epsII = epsII Q = Vdg epsII = Function(Q) # Plastic viscosity eps1 = Function(Q) # Plastic viscosity eps2 = Function(Q) # Plastic viscosity eps = epsilon(u) local_project(eps[0,0],Q,eps1) local_project(eps[0,1],Q,eps2) epsII.vector()[:] = np.sqrt(eps1.vector().get_local()**2+eps2.vector().get_local()**2) #local_project(sqrt(eps1**2 + eps2**2),Q,epsII) self.epsII = epsII if count>=maxit: print("WARNING: MAXIMUM NUMBER OF ITERATIONS EXCEEDED") self.u_k = u_k self.u=u self.u_p = w self.u = u self.p = p self.eta = eta return u,p
def read_files(fname_base): L = [] t = [] for step in range(0, 1000000, 10): fname_ext = str(step).zfill(3) + '.npz' fname = fname_base + fname_ext print(fname) # Load particle data if path.exists(fname): tracer_data = np.load(fname) else: print('Cannot read file') break t.append(tracer_data['t'].item()) # Load mesh mesh_file = fname_base + str(step).zfill(3) + '.xml' mesh = Mesh(mesh_file) # Make particle class n = len(tracer_data['xm']) xp = np.vstack( (tracer_data['xm'], tracer_data['zm'])).transpose().reshape(n, 2) pstrain = tracer_data['strain'] pepsII = tracer_data['epsII'] ptemp = tracer_data['temp'] p = particles(xp, [pstrain, ptemp, pepsII], mesh) # Interpolate particles to mesh Vdg = FunctionSpace(mesh, 'DG', 1) strain = Function(Vdg) lstsq_strain = l2projection(p, Vdg, 1) # First variable??? lstsq_strain.project_mpm(strain) # Projection is stored in phih0 # Boundary mesh with portion above sea level marked bmesh = BoundaryMesh(mesh, 'exterior', order=True) x = bmesh.coordinates() #ymax = np.max(x[x[:,0]==0,1]) filter = (x[:, 0] > 1e-4) & (x[:, 1] > 0) xm = np.min(x[filter, 0]) id = np.argwhere(x[:, 0] == xm).item() # Check if nodes increasing or decreasing if (x[id - 1, 0] > x[id, 0]): # Decrease nodes inc = -1 stop = 0 else: # Increase nodes inc = 1 stop = len(x) iold = id for i in range(id, stop, inc): if x[i, 1] > 0.0: slope = (x[i, 1] - x[iold, 1]) / (x[i, 0] - x[iold, 0]) #print(x[i,0],strain(x[i]),strain(x[i])>0.99,slope,slope<-pi/3) #print(-slope*180/pi) if strain(x[i]) > 0.99: L.append(x[iold, 0]) break elif np.abs(slope) > pi / 6: L.append(x[iold, 0]) break iold = i print('Terminus position', L[-1]) if i == stop - inc: print('No terminus identified') L.append(np.Nan) fname = fname_base + 'term_pos.npz' print(fname) # Least squares fit to data #if len(t)>len(L): # print('Not equal') # t =t[0:-1] print(len(t), len(L)) t = np.array(t) L = np.array(L) filter = (t > 2 / 12) # t, L = np.array(t), np.array(L) dLdt, b, rvalue, pvalue1, err = linregress(t[filter], L[filter]) print('Rate of terminus advance', dLdt, 'Errror', err) np.savez(fname, t=t, L=L, dLdt=dLdt, err=err, pvalue=pvalue1, rvalue=rvalue) return None
mesh, p, forms_pde["N_a"], forms_pde["G_a"], forms_pde["L_a"], forms_pde["H_a"], forms_pde["B_a"], forms_pde["Q_a"], forms_pde["R_a"], forms_pde["S_a"], [bc], property_idx, ) # Initialize the l2 projection lstsq_psi = l2projection(p, W, property_idx) # Set initial condition at mesh and particles psi0_h.interpolate(psi0_expression) p.interpolate(psi0_h.cpp_object(), property_idx) # Initialize add/delete particle AD = AddDelete(p, 15, 25, [psi0_h]) step = 0 t = 0.0 area_0 = assemble(psi0_h * dx) timer = Timer() timer.start() while step < num_steps:
# Define projections problem FuncSpace_adv = {'FuncSpace_local': Q_Rho, 'FuncSpace_lambda': T_1, 'FuncSpace_bar': Qbar} FormsPDE = FormsPDEMap(mesh, FuncSpace_adv, beta_map=Constant(1e-8)) forms_pde = FormsPDE.forms_theta_linear(phih0, uadvect, dt, Constant(1.0), zeta=Constant(0.), h=Constant(0.)) pde_projection = PDEStaticCondensation(mesh, p, forms_pde['N_a'], forms_pde['G_a'], forms_pde['L_a'], forms_pde['H_a'], forms_pde['B_a'], forms_pde['Q_a'], forms_pde['R_a'], forms_pde['S_a'], [], 1) ap = advect_rk3(p, V, uh, 'open') # Initialize the initial condition at mesh by an l2 projection lstsq_rho = l2projection(p, Q_Rho, 1) lstsq_rho.project(phih0) outfile << phih0 for step in range(num_steps): u_expr.t = step * float(dt) u_expre_neg.t = step * float(dt) uh.assign(u_expr) # Compute area at old configuration old_area = assemble(phih0*dx) # Pre-assemble rhs pde_projection.assemble_state_rhs()
initial_density = BinaryBlock(geometry, float(rho1), float(rho2), degree=1) zero_expression = Expression(("0.", "0."), degree=1) # Initialize particles x = RandomRectangle(Point(xmin, ymin), Point(xmax, ymax)).generate( [pres, int(pres * (ymax - ymin) / (xmax - xmin))]) up = assign_particle_values(x, zero_expression) rhop = assign_particle_values(x, initial_density) # Increment requires dup to be stored, init zero dup = up p = particles(x, [rhop, up, dup], mesh) # Init rho0 field lstsq_rho = l2projection(p, Q_Rho, 1) lstsq_rho.project(rho0, float(rho2), float(rho1)) # Initialize l2 projection for specific momentum lstsq_u = l2projection(p, W_2, 2) # Initialize advection class ap = advect_rk3(p, W_2, Udiv, 'closed') # Set-up boundary conditions (free slip) boundaries = MeshFunction("size_t", mesh, mesh.topology().dim() - 1) boundaries.set_all(0) all_bounds = Boundaries() all_bounds.mark(boundaries, 98) ds = Measure('ds', domain=mesh, subdomain_data=boundaries)
W = FunctionSpace(mesh, 'DG', k) psi_h = Function(W) V = VectorFunctionSpace(mesh, 'DG', 3) uh = Function(V) uh.assign(Expression(('-Uh*x[1]', 'Uh*x[0]'), Uh=Uh, degree=3)) # Generate particles x = RandomCircle(Point(x0, y0), r).generate([pres, pres]) s = assign_particle_values(x, psi0_expr) p = particles(x, [s], mesh) # Initialize advection class, use RK3 scheme ap = advect_rk3(p, V, uh, 'closed') # Init projection lstsq_psi = l2projection(p, W, 1) # Do projection to get initial field lstsq_psi.project(psi_h.cpp_object(), lb, ub) AD = AddDelete(p, 10, 20, [psi_h], [1], [lb, ub]) step = 0 t = 0. area_0 = assemble(psi_h * dx) timer = Timer() timer.start() outfile.write(psi_h, t) while step < num_steps: step += 1 t += float(dt)
def read_calving_front_sim(fname_base): fname_ext = '.npz' fname = fname_base + fname_ext print(fname) # Load particle data if path.exists(fname): tracer_data = np.load(fname) else: print('Cannot read file') t = tracer_data['t'].item() # Load mesh mesh_file = fname_base + '.xml' mesh = Mesh(mesh_file) # Make particle class n = len(tracer_data['xm']) xp = np.vstack( (tracer_data['xm'], tracer_data['zm'])).transpose().reshape(n, 2) pstrain = tracer_data['strain'] pepsII = tracer_data['epsII'] ptemp = tracer_data['temp'] p = particles(xp, [pstrain, ptemp, pepsII], mesh) # Interpolate particles to mesh Vdg = FunctionSpace(mesh, 'DG', 1) strain = Function(Vdg) lstsq_strain = l2projection(p, Vdg, 1) # First variable??? lstsq_strain.project_mpm(strain) # Projection is stored in phih0 # Boundary mesh with portion above sea level marked bmesh = BoundaryMesh(mesh, 'exterior', order=True) x = bmesh.coordinates() #ymax = np.max(x[x[:,0]==0,1]) filter = (x[:, 0] > 1e-4) & (x[:, 1] > 0) xm = np.min(x[filter, 0]) id = np.argwhere(x[:, 0] == xm).item() # Check if nodes increasing or decreasing if (x[id - 1, 0] > x[id, 0]): # Decrease nodes inc = -1 stop = 0 else: # Increase nodes inc = 1 stop = len(x) iold = id for i in range(id, stop, inc): if x[i, 1] > 0.0: slope = (x[i, 1] - x[iold, 1]) / (x[i, 0] - x[iold, 0]) #print(x[i,0],strain(x[i]),strain(x[i])>0.99,slope,slope<-pi/3) #print(-slope*180/pi) if strain(x[i]) > 0.1: L = x[iold, 0] break elif np.abs(slope) > pi / 6: L = x[iold, 0] break iold = i print('Terminus position', L) # Extract profile centered on terminus filter = (x[:, 1] > 0.0) & (x[:, 0] > 10) & (x[:, 0] < L + 5 * 800) xp = x[filter, 0] - L zp = x[filter, 1] idx = np.argsort(xp) xp = xp[idx] zp = zp[idx] zp = gaussian_filter(zp, 1.5) #fname = fname_base + 'term_pos.npz' #print(fname) return xp, zp
def test_moving_mesh(): t = 0. dt = 0.025 num_steps = 20 xmin, ymin = 0., 0. xmax, ymax = 2., 2. xc, yc = 1., 1. nx, ny = 20, 20 pres = 150 k = 1 mesh = RectangleMesh(Point(xmin, ymin), Point(xmax, ymax), nx, ny) n = FacetNormal(mesh) # Class for mesh motion dU = PeriodicVelocity(xmin, xmax, dt, t, degree=1) Qcg = VectorFunctionSpace(mesh, 'CG', 1) boundaries = MeshFunction("size_t", mesh, mesh.topology().dim()-1) boundaries.set_all(0) leftbound = Left(xmin) leftbound.mark(boundaries, 99) ds = Measure('ds', domain=mesh, subdomain_data=boundaries) # Create function spaces Q_E_Rho = FiniteElement("DG", mesh.ufl_cell(), k) T_1 = FunctionSpace(mesh, 'DG', 0) Qbar_E = FiniteElement("DGT", mesh.ufl_cell(), k) Q_Rho = FunctionSpace(mesh, Q_E_Rho) Qbar = FunctionSpace(mesh, Qbar_E) phih, phih0 = Function(Q_Rho), Function(Q_Rho) phibar = Function(Qbar) # Advective velocity uh = Function(Qcg) uh.assign(Constant((0., 0.))) # Mesh velocity umesh = Function(Qcg) # Total velocity uadvect = uh-umesh # Now throw in the particles x = RandomRectangle(Point(xmin, ymin), Point(xmax, ymax)).generate([pres, pres]) s = assign_particle_values(x, GaussianPulse(center=(xc, yc), sigma=float(0.25), U=[0, 0], time=0., height=1., degree=3)) x = comm.bcast(x, root=0) s = comm.bcast(s, root=0) p = particles(x, [s], mesh) # Define projections problem FuncSpace_adv = {'FuncSpace_local': Q_Rho, 'FuncSpace_lambda': T_1, 'FuncSpace_bar': Qbar} FormsPDE = FormsPDEMap(mesh, FuncSpace_adv, ds=ds) forms_pde = FormsPDE.forms_theta_linear(phih0, uadvect, dt, Constant(1.0), zeta=Constant(0.)) pde_projection = PDEStaticCondensation(mesh, p, forms_pde['N_a'], forms_pde['G_a'], forms_pde['L_a'], forms_pde['H_a'], forms_pde['B_a'], forms_pde['Q_a'], forms_pde['R_a'], forms_pde['S_a'], [], 1) # Initialize the initial condition at mesh by an l2 projection lstsq_rho = l2projection(p, Q_Rho, 1) lstsq_rho.project(phih0.cpp_object()) for step in range(num_steps): # Compute old area at old configuration old_area = assemble(phih0*dx) # Pre-assemble rhs pde_projection.assemble_state_rhs() # Move mesh dU.compute_ubc() umesh.assign(project(dU, Qcg)) ALE.move(mesh, project(dU * dt, Qcg)) dU.update() # Relocate particles as a result of mesh motion # NOTE: if particles were advected themselve, # we had to run update_facets_info() here as well p.relocate() # Assemble left-hand side on new config, but not the right-hand side pde_projection.assemble(True, False) pde_projection.solve_problem(phibar.cpp_object(), phih.cpp_object(), 'mumps', 'none') # Needed to compute conservation, note that there # is an outgoing flux at left boundary new_area = assemble(phih*dx) gamma = conditional(ge(dot(uadvect, n), 0), 0, 1) bflux = assemble((1-gamma) * dot(uadvect, n) * phih * ds) # Update solution assign(phih0, phih) # Put assertion on (global) mass balance, local mass balance is # too time consuming but should pass also assert new_area - old_area + bflux * dt < 1e-12 # Assert that max value of phih stays close to 2 and # min value close to 0. This typically will fail if # we do not do a correct relocate of particles assert np.amin(phih.vector().get_local()) > -0.015 assert np.amax(phih.vector().get_local()) < 1.04