[docs]defsetUp(self):self.w=0.1self.L=1.0N=3M=2xRange=[0.0,self.L]yRange=[0.0,self.w]mesh,_=self.create_mesh_and_disp(N,M,xRange,yRange,lambdaX:0*X)self.mesh=Mesh.create_higher_order_mesh_from_simplex_mesh(mesh,order=2,createNodeSetsFromSideSets=True)quadPrecision=2*(self.mesh.parentElement.degree-1)quadRule=QuadratureRule.create_quadrature_rule_on_triangle(degree=quadPrecision)self.fs=FunctionSpace.construct_function_space(self.mesh,quadRule)self.fieldShape=self.mesh.coords.shapeebcs=[FunctionSpace.EssentialBC(nodeSet='bottom',component=1)]self.dofManager=FunctionSpace.DofManager(self.fs,self.fieldShape[1],ebcs)props={'elastic modulus':E,'poisson ratio':nu,'density':rho}materialModel=LinearElastic.create_material_model_functions(props)self.props=LinearElastic.create_material_properties(props)newmarkParams=Mechanics.NewmarkParameters(gamma=0.5,beta=0.25)self.dynamicsFunctions=Mechanics.create_dynamics_functions(self.fs,'plane strain',materialModel,newmarkParams)self.staticsFunctions=Mechanics.create_mechanics_functions(self.fs,'plane strain',materialModel)# using an elastic model, so we can neglect internal var updatingself.internalVariables=self.dynamicsFunctions.compute_initial_state()
[docs]deftest_integration_of_constant_acceleration_is_exact(self):Uu,Vu,_=self.set_initial_conditions()dt=0.75t=0.0tOld=-dtp=Objective.Params(None,self.internalVariables,None,None,np.array([t,tOld]),Uu,self.props)defobjective_function(Uu,p):U=self.create_field(Uu,p)UuPre=p.dynamic_dataUPre=self.create_field(UuPre,p)internalVariables=p[1]props=p.prop_datareturnself.dynamicsFunctions.compute_algorithmic_energy(U,UPre,internalVariables,props,dt) \
+self.constant_body_force_potential(Uu,p)objective=Objective.Objective(objective_function,Uu,p)# set constant acceleration of 1.0 in x directionA=np.zeros_like(self.mesh.coords).at[:,0].set(1.0)Au=self.dofManager.get_unknown_values(A)foriinrange(1,15):Uu,Vu,Au=self.time_step(Uu,Vu,Au,objective,dt)U=self.dofManager.create_field(Uu,self.get_ubcs())t=objective.p.time[0]UExact=np.zeros(U.shape).at[:,0].set(t+0.5*t**2)self.assertArrayNear(U,UExact,10)
[docs]defsetUp(self):self.Nx=7self.Ny=7xRange=[0.,1.]yRange=[0.,1.]self.targetDispGradRate=np.array([[0.1,-0.2],[0.4,-0.1]])self.mesh,self.V=self.create_mesh_and_disp(self.Nx,self.Ny,xRange,yRange,lambdax:self.targetDispGradRate.dot(x))quadRule=QuadratureRule.create_quadrature_rule_on_triangle(degree=1)self.fs=FunctionSpace.construct_function_space(self.mesh,quadRule)self.qr1d=QuadratureRule.create_padded_quadrature_rule_1D(degree=1)props={'elastic modulus':E,'poisson ratio':nu,'strain measure':'linear','density':20.0}# density chosen to make kinetic energy and strain energy comparable# Want bugs in either to show up appreciably in errormaterialModel=Neohookean.create_material_model_functions(props)self.props=Neohookean.create_material_properties(props)newmarkParams=Mechanics.NewmarkParameters()self.dynamics=Mechanics.create_dynamics_functions(self.fs,'plane strain',materialModel,newmarkParams)self.compute_stress=jax.jacfwd(materialModel.compute_energy_density)
[docs]deftest_patch_test(self):dt=1.0ebcs=[FunctionSpace.EssentialBC(nodeSet='all_boundary',component=0),FunctionSpace.EssentialBC(nodeSet='all_boundary',component=1)]dofManager=FunctionSpace.DofManager(self.fs,dim=2,EssentialBCs=ebcs)defenergy(Uu,p):t=p.time[0]dt=t-p.time[1]Ubc=dofManager.get_bc_values(self.V*t)U=dofManager.create_field(Uu,Ubc)UPre=p.dynamic_datainternalVariables=p[1]props=p.prop_datareturnself.dynamics.compute_algorithmic_energy(U,UPre,internalVariables,props,dt)# initial conditionsV=self.V.copy()A=np.zeros_like(V)U=np.zeros_like(V)Uu=dofManager.get_unknown_values(U)internals=self.dynamics.compute_initial_state()p=Objective.Params(None,internals,None,None,np.array([0.0,-dt]),U,self.props)objective=Objective.Objective(energy,Uu,p)foriinrange(1,4):print('--------------------')print('LOAD STEP ',i)tOld=objective.p.time[0]t=tOld+dtprint('\ttime = ',t,'\tdt = ',dt)objective.p=Objective.param_index_update(objective.p,4,np.array([t,tOld]))UPrediction,V=self.dynamics.predict(U,V,A,dt)objective.p=Objective.param_index_update(objective.p,5,UPrediction)# The predictor value is exact.# Choose a bad initial guess (zero) to force an actual solve.Uu,solverSuccess=EquationSolver.nonlinear_equation_solve(objective,dofManager.get_unknown_values(UPrediction),objective.p,trSettings,useWarmStart=False)U=dofManager.create_field(Uu,dofManager.get_bc_values(V*t))UCorrection=U-UPredictionV,A=self.dynamics.correct(UCorrection,V,A,dt)internals=self.dynamics.compute_updated_internal_variables(U,internals,self.props,dt)objective.p=Objective.param_index_update(objective.p,1,internals)UExact=np.dot(self.mesh.coords,t*self.targetDispGradRate.T)error=np.linalg.norm((U-UExact).ravel())/np.linalg.norm(UExact.ravel())self.assertLess(error,1e-14)
[docs]deftest_traction_patch_test(self):ebcs=[]dofManager=FunctionSpace.DofManager(self.fs,dim=2,EssentialBCs=ebcs)defenergy(Uu,p):t=p.time[0]deftraction(X,N):dispGrad=self.targetDispGradRate*tdispGrad3D=np.zeros((3,3)).at[:2,:2].set(dispGrad)q=np.array([0.0])dt=0.0P=self.compute_stress(dispGrad3D,q,p.prop_data,dt)[:2,:2]returnnp.dot(P,N)dt=t-p.time[1]U=dofManager.create_field(Uu)UPre=p.dynamic_datainternalVariables=p[1]loadPotential=Mechanics.compute_traction_potential_energy(self.fs,U,self.qr1d,self.fs.mesh.sideSets["all_boundary"],traction)returnself.dynamics.compute_algorithmic_energy(U,UPre,internalVariables,self.props,dt)+loadPotentialdt=1.0# initial conditionsU=np.zeros_like(self.V)V=self.V.copy()A=np.zeros_like(self.V)internals=self.dynamics.compute_initial_state()Uu=dofManager.get_unknown_values(U)p=Objective.Params(None,internals,None,None,np.array([0.0,-dt]),U,self.props)objective=Objective.Objective(energy,Uu,p)foriinrange(1,4):print('--------------------')print('LOAD STEP ',i)tOld=objective.p.time[0]t=tOld+dtprint('\ttime = ',t,'\tdt = ',dt)objective.p=Objective.param_index_update(objective.p,4,np.array([t,tOld]))UPrediction,V=self.dynamics.predict(U,V,A,dt)objective.p=Objective.param_index_update(objective.p,5,UPrediction)# The predictor value is exact.# Choose a bad initial guess (zero) to force an actual solve.Uu,solverSuccess=EquationSolver.nonlinear_equation_solve(objective,dofManager.get_unknown_values(UPrediction),objective.p,trSettings,useWarmStart=False)U=dofManager.create_field(Uu)UCorrection=U-UPredictionV,A=self.dynamics.correct(UCorrection,V,A,dt)internals=self.dynamics.compute_updated_internal_variables(U,internals,self.props,dt)objective.p=Objective.param_index_update(objective.p,1,internals)UExact=np.dot(self.mesh.coords,t*self.targetDispGradRate.T)error=np.linalg.norm((U-UExact).ravel())/np.linalg.norm(UExact.ravel())self.assertLess(error,1e-13)