def test_behaviour_data(self): pr = -1.2e5 eps = -pr * 1.e-14 h = mgis_bv.Hypothesis.Tridimensional b = self.__get_behaviour(h) d = mgis_bv.BehaviourData(b) mgis_bv.setExternalStateVariable(d.s0, "Temperature", 293.15) mgis_bv.setExternalStateVariable(d.s1, "Temperature", 293.15) inputs = numpy.asarray([pr], dtype=numpy.float64) v = mgis_bv.make_view(d) mgis_bv.executeInitializeFunction(v, b, "StressFromInitialPressure", inputs) # Due to restrictions of the BehaviourDataView class (the # initial state is assumed immutable), only the state at the # end of the time step is initialized. Calling update is thus # required in most cases mgis_bv.update(d) s0 = d.s0.thermodynamic_forces s1 = d.s1.thermodynamic_forces for i in range(0, 3): self.assertTrue( abs(s0[i] - pr) < eps, "invalid stress value at the beginning of the time step") self.assertTrue( abs(s1[i] - pr) < eps, "invalid stress value at the end of the time step") for i in range(3, 6): self.assertTrue( abs(s0[i]) < eps, "invalid stress value at the beginning of the time step") self.assertTrue( abs(s1[i]) < eps, "invalid stress value at the end of the time step")
def test_behaviour_data2(self): E = 200e9 nu = 0.3 sxx = 150e6 eps = 10 * sxx * 1e-14 h = mgis_bv.Hypothesis.Tridimensional b = self.__get_behaviour(h) d = mgis_bv.BehaviourData(b) d.s0.thermodynamic_forces[:] = [sxx, 0, 0, 0, 0, 0] mgis_bv.setExternalStateVariable(d.s0, "Temperature", 293.15) mgis_bv.setExternalStateVariable(d.s1, "Temperature", 293.15) v = mgis_bv.make_view(d) mgis_bv.executeInitializeFunction(v, b, "ElasticStrainFromInitialStress") # Due to restrictions of the BehaviourDataView class (the # initial state is assumed immutable), only the state at the # end of the time step is initialized. Calling update is thus # required in most cases mgis_bv.update(d) eel_values = [sxx / E, -nu * sxx / E, -nu * sxx / E, 0, 0, 0] eel0 = d.s0.internal_state_variables eel1 = d.s1.internal_state_variables for i in range(0, 6): self.assertTrue( abs(eel0[i] - eel_values[i]) < eps, "invalid elastic strain value at the beginning of the time step" ) self.assertTrue( abs(eel1[i] - eel_values[i]) < eps, "invalid elastic strain value at the end of the time step")
def __updateStrainStress(self, du): # private method (self-explanatory) """ :var du: nodal displacement increment """ dstrain = self.__spfem.calcStrain(VectorX(du)) self.__materData.s1.gradients[:, :] += numpy.array(dstrain) mgis_bv.integrate(self.__materData, intType, self.__dt, 0, self.__materData.n) mgis_bv.update(self.__materData)
def __updateMaterialData(self,res): self.__materData = mgis_bv.MaterialDataManager(behaviour, self.__npts) for s in [self.__materData.s0, self.__materData.s1]: # material initialization mgis_bv.setMaterialProperty(s,"YoungModulus",self.mater['young']) mgis_bv.setMaterialProperty(s,"PoissonRatio",self.mater['poisson']) mgis_bv.setMaterialProperty(s,"InitYieldStress",self.mater['tau0']) mgis_bv.setMaterialProperty(s,"ResidualYieldStress",self.mater['taur']) mgis_bv.setMaterialProperty(s,"SoftenExponent",self.mater['b']) mgis_bv.setExternalStateVariable(s,"Temperature",293.15) s.internal_state_variables[:,:] = res[:,:5] #s.thermodynamic_forces[:,:] = res[:,5:9] s.gradients[:,:] = res[:,5:] mgis_bv.integrate(pool, self.__materData, intType, self.__dt) mgis_bv.update(self.__materData)
def test_pass(self): # path to the test library lib = os.environ['MGIS_TEST_BEHAVIOURS_LIBRARY'] # reference values pref = [ 0, 1.3523277308229e-11, 1.0955374667213e-07, 5.5890770166084e-06, 3.2392193670428e-05, 6.645865307584e-05, 9.9676622883138e-05, 0.00013302758358953, 0.00016635821069889, 0.00019969195920296, 0.00023302522883648, 0.00026635857194317, 0.000299691903777, 0.0003330252373404, 0.00036635857063843, 0.00039969190397718, 0.00043302523730968, 0.00046635857064314, 0.00049969190397646, 0.00053302523730979, 0.00056635857064313 ] # comparison criterion eps = 1.e-12 b = mgis_bv.load(lib, 'Norton', mgis_bv.Hypothesis.Tridimensional) d = mgis_bv.BehaviourData(b) o = mgis_bv.getVariableOffset(b.isvs, 'EquivalentViscoplasticStrain', b.hypothesis) # strain increment per time step de = 5.e-5 # time step d.dt = 180 # setting the temperature mgis_bv.setExternalStateVariable(d.s1, 'Temperature', 293.15) # copy d.s1 in d.s0 mgis_bv.update(d) d.s1.gradients[0] = de # equivalent plastic strain p = [d.s0.internal_state_variables[o]] # integrate the behaviour for i in range(0, 20): mgis_bv.integrate(d, b) mgis_bv.update(d) d.s1.gradients[0] += de p.append(d.s1.internal_state_variables[o]) # check-in results for i in range(0, 20): self.assertTrue(abs(p[i] - pref[i]) < eps) pass
def test_behaviour_data(self): eps = 1.e-14 e = numpy.asarray([1.3e-2, 1.2e-2, 1.4e-2, 0., 0., 0.], dtype=numpy.float64) e2 = numpy.asarray([1.2e-2, 1.3e-2, 1.4e-2, 0., 0., 0.], dtype=numpy.float64) h = mgis_bv.Hypothesis.Tridimensional b = self.__get_behaviour(h) m = mgis_bv.MaterialDataManager(b, 2) mgis_bv.setMaterialProperty(m.s1, "YoungModulus", 150e9) mgis_bv.setMaterialProperty(m.s1, "PoissonRatio", 0.3) mgis_bv.setExternalStateVariable(m.s1, "Temperature", 293.15) mgis_bv.update(m) m.s1.gradients[0:] = e m.s1.gradients[1:] = e outputs = numpy.empty(shape=(2, 3), dtype=numpy.float64) mgis_bv.executePostProcessing(outputs.reshape(6), m, "PrincipalStrain") for i in range(0, 3): self.assertTrue( abs(outputs[0, i] - e2[i]) < eps, "invalid output value") self.assertTrue( abs(outputs[1, i] - e2[i]) < eps, "invalid output value")
def test_pass(self): # path to the test library lib = os.environ['MGIS_TEST_MODELS_LIBRARY'] # modelling hypothesis h = mgis_bv.Hypothesis.Tridimensional # loading the behaviour model = mgis.model.load(lib, 'ode_rk54', h) # default value of parameter A A = model.getParameterDefaultValue('A') # material data manager d = mgis_bv.BehaviourData(model) # index of x in the array of state variable o = mgis_bv.getVariableOffset(model.isvs, 'x', h) # time step increment d.dt = 0.1 # type of storage mgis_bv.setExternalStateVariable(d.s1, 'Temperature', 293.15) # Initial value of x d.s1.internal_state_variables[o] = 1 # copy d.s1 in d.s0 mgis_bv.update(d) # values of x xvalues = [d.s0.internal_state_variables[o]] # integration for i in range(0, 10): mgis_bv.integrate(d, model) mgis_bv.update(d) xvalues.append(d.s1.internal_state_variables[o]) # checks # comparison criterion eps = 1.e-10 t = 0 for i in range(0, 11): x_ref = math.exp(-A * t) self.assertTrue(abs(xvalues[i] - x_ref) < eps) t = t + d.dt pass
def test_data_manager2(self): """ Call an initialize function with non uniform inputs """ pr = [-1.2e5, 0.7e5] eps = -pr[0] * 1.e-14 h = mgis_bv.Hypothesis.Tridimensional b = self.__get_behaviour(h) d = mgis_bv.MaterialDataManager(b, 2) mgis_bv.setExternalStateVariable(d.s0, "Temperature", 293.15) mgis_bv.setExternalStateVariable(d.s1, "Temperature", 293.15) inputs = numpy.asarray(pr, dtype=numpy.float64) mgis_bv.executeInitializeFunction(d, "StressFromInitialPressure", inputs) # Due to restrictions of the BehaviourDataView class (the # initial state is assumed immutable), only the state at the # end of the time step is initialized. Calling update is thus # required in most cases mgis_bv.update(d) s0 = d.s0.thermodynamic_forces s1 = d.s1.thermodynamic_forces for n in range(0, 2): for i in range(0, 3): self.assertTrue( abs(s0[n][i] - pr[n]) < eps, "invalid stress value at the beginning of the time step") self.assertTrue( abs(s1[n][i] - pr[n]) < eps, "invalid stress value at the end of the time step") for i in range(3, 6): self.assertTrue( abs(s0[n][i]) < eps, "invalid stress value at the beginning of the time step") self.assertTrue( abs(s1[n][i]) < eps, "invalid stress value at the end of the time step")
def f(self, x): """Objective function""" self.u.vector()[:] = x self.update_constitutive_law() mgis_bv.update(self.material.data_manager) return self.get_total_energy()
def solve(self, x): if self._init: self.initialize() solv_out = self.solver.solve(self, x) mgis_bv.update(self.material.data_manager) return solv_out
def test_pass(self): print(dir(mgis)) # path to the test library lib = os.environ['MGIS_TEST_BEHAVIOURS_LIBRARY'] # reference values pref = [ 0, 1.3523277308229e-11, 1.0955374667213e-07, 5.5890770166084e-06, 3.2392193670428e-05, 6.645865307584e-05, 9.9676622883138e-05, 0.00013302758358953, 0.00016635821069889, 0.00019969195920296, 0.00023302522883648, 0.00026635857194317, 0.000299691903777, 0.0003330252373404, 0.00036635857063843, 0.00039969190397718, 0.00043302523730968, 0.00046635857064314, 0.00049969190397646, 0.00053302523730979, 0.00056635857064313 ] # modelling hypothesis h = mgis_bv.Hypothesis.Tridimensional # loading the behaviour b = mgis_bv.load(lib, 'Norton', h) # number of integration points nig = 100 # material data manager m = mgis_bv.MaterialDataManager(b, nig) # index of the equivalent viscplastic strain in the array of # state variable o = mgis_bv.getVariableOffset(b.isvs, 'EquivalentViscoplasticStrain', h) # strain increment per time step de = 5.e-5 # time step increment dt = 180 # setting the temperature mgis_bv.setExternalStateVariable(m.s1, 'Temperature', 293.15) # copy d.s1 in d.s0 mgis_bv.update(m) # index of the first integration point ni = 0 # index of the last integration point ne = nig - 1 # values of the equivalent plastic strain # for the first integration point pi = [m.s0.internal_state_variables[ni][o]] # values of the equivalent plastic strain # for the last integration point pe = [m.s0.internal_state_variables[ne][o]] # setting the gradient at the end of the first time step for i in range(0, nig): m.s1.gradients[i][0] = de # creating a thread pool for parallel integration p = mgis.ThreadPool(2) # integration for i in range(0, 20): it = mgis_bv.IntegrationType.IntegrationWithoutTangentOperator mgis_bv.integrate(p, m, it, dt) mgis_bv.update(m) for j in range(0, nig): m.s1.gradients[j][0] += de pi.append(m.s0.internal_state_variables[ni][o]) pe.append(m.s0.internal_state_variables[ne][o]) # checks # comparison criterion eps = 1.e-12 for i in range(0, 21): self.assertTrue(abs(pi[i] - pref[i]) < eps) self.assertTrue(abs(pe[i] - pref[i]) < eps) pass
Dt.vector().apply("insert") print("Coupled Tangent Operator:", tangent_operators[1::2]) # retrieve cumulated plastic strain values p.vector().set_local(m.s1.internal_state_variables[:, -1]) p.vector().apply("insert") # solve Newton system A, Res = assemble_system(a_Newton, res, bc) nRes = Res.norm("l2") print(" Residual at the end:", nRes) niter += 1 # update the displacement for the next increment vt.assign(vt1) (u, theta) = vt.split() # update the material # the update function updates an instance of the MaterialStateManager by copying the state s1 at the end of the time step in the state s0 at the beginning of the time step. mgis_bv.update(m) # postprocessing results file_results.write(u, t) p_avg.assign(project(p, P0)) file_results.write(p_avg, t) results[i+1, :] = (u(0, 0, 0)[0], t) import matplotlib.pyplot as plt plt.plot(results[:, 0], results[:, 1], "-o") plt.xlabel("Displacement of inner boundary") plt.ylabel(r"Applied pressure $q/q_{lim}$") plt.show() # .. note:: # Note that we defined the cumulative plastic strain variable :math:`p` in FEniCS # only for post-processing purposes. In fact, FEniCS deals only with the global equilibrium
def solve_newton_2(problem: Problem, material: Material, verbose: bool = False, debug_mode: DebugMode = DebugMode.NONE): time_step_index_count = 0 clean_res_dir(problem.res_folder_path) problem.create_output(problem.res_folder_path) _dx = problem.field.field_dimension _fk = problem.finite_element.face_basis_k.dimension _cl = problem.finite_element.cell_basis_l.dimension external_forces_coefficient = 1.0 normalization_lagrange_coefficient = material.lagrange_parameter # ---------------------------------------------------------------------------------------------------------- # SET SYSTEM SIZE # ---------------------------------------------------------------------------------------------------------- _constrained_system_size, _system_size = problem.get_total_system_size() faces_unknown_vector = np.zeros((_constrained_system_size), dtype=real) faces_unknown_vector_previous_step = np.zeros((_constrained_system_size), dtype=real) residual_values = [] time_step_temp = problem.time_steps[0] initial_time_steps = [ff for ff in problem.time_steps] for time_step_index, time_step in enumerate(problem.time_steps): local_time_steps = [time_step] for local_time_step_index, local_time_step in enumerate( local_time_steps): print("0K") # --- SET TEMPERATURE material.set_temperature() # --- PRINT DATA print( "----------------------------------------------------------------------------------------------------" ) print("TIME_STEP : {} | LOAD_VALUE : {}".format( time_step_index, time_step)) # --- WRITE RES FILES # if time_step in initial_time_steps: # file_suffix = "{}".format(time_step_index).zfill(6) # problem.create_vertex_res_files(problem.res_folder_path, file_suffix) # problem.create_quadrature_points_res_files(problem.res_folder_path, file_suffix, material) for iteration in range(problem.number_of_iterations): # -------------------------------------------------------------------------------------------------- # SET SYSTEM MATRIX AND VECTOR # -------------------------------------------------------------------------------------------------- tangent_matrix = np.zeros( (_constrained_system_size, _constrained_system_size), dtype=real) residual = np.zeros((_constrained_system_size), dtype=real) # -------------------------------------------------------------------------------------------------- # SET TIME INCREMENT # -------------------------------------------------------------------------------------------------- if time_step_index == 0: _dt = time_step else: _dt = time_step - problem.time_steps[time_step_index - 1] _dt = np.float64(_dt) # _dt = 0.0 # _dt = np.float64(0.0) # -------------------------------------------------------------------------------------------------- # FOR ELEMENT LOOP # -------------------------------------------------------------------------------------------------- _qp = 0 stab_coef = 1.0 iter_face_constraint = 0 for _element_index, element in enumerate(problem.elements): cell_quadrature_size = element.cell.get_quadrature_size( problem.finite_element.construction_integration_order, quadrature_type=problem.quadrature_type) cell_quadrature_points = element.cell.get_quadrature_points( problem.finite_element.construction_integration_order, quadrature_type=problem.quadrature_type) cell_quadrature_weights = element.cell.get_quadrature_weights( problem.finite_element.construction_integration_order, quadrature_type=problem.quadrature_type) x_c = element.cell.get_centroid() h_c = element.cell.get_diameter() _nf = len(element.faces) _c0_c = _dx * _cl # --- INITIALIZE MATRIX AND VECTORS element_stiffness_matrix = np.zeros( (element.element_size, element.element_size), dtype=real) element_internal_forces = np.zeros((element.element_size, ), dtype=real) element_external_forces = np.zeros((element.element_size, ), dtype=real) # --- RUN OVER EACH QUADRATURE POINT for _qc in range(cell_quadrature_size): _w_q_c = cell_quadrature_weights[_qc] # _w_q_c = np.abs(cell_quadrature_weights[_qc]) _x_q_c = cell_quadrature_points[:, _qc] # --- COMPUTE STRAINS AND SET THEM IN THE BEHAVIOUR LAW transformation_gradient = element.get_transformation_gradient( faces_unknown_vector, _qc) material.mat_data.s1.gradients[ _qp] = transformation_gradient # --- INTEGRATE BEHAVIOUR LAW integ_res = mgis_bv.integrate(material.mat_data, material.integration_type, _dt, _qp, (_qp + 1)) # stored_energies', 'dissipated_energies', 'internal_state_variables # print(material.mat_data.s1.internal_state_variables) # --- VOLUMETRIC FORCES v = problem.finite_element.cell_basis_l.evaluate_function( _x_q_c, x_c, h_c) for load in problem.loads: vl = _w_q_c * v * load.function(time_step, _x_q_c) _re0 = load.direction * _cl _re1 = (load.direction + 1) * _cl element_external_forces[_re0:_re1] += vl # --- COMPUTE STIFFNESS MATRIX CONTRIBUTION AT QUADRATURE POINT element_stiffness_matrix += _w_q_c * ( element.gradients_operators[_qc].T @ material.mat_data. K[_qp] @ element.gradients_operators[_qc]) # --- COMPUTE STIFFNESS MATRIX CONTRIBUTION AT QUADRATURE POINT element_internal_forces += _w_q_c * ( element.gradients_operators[_qc].T @ material.mat_data.s1.thermodynamic_forces[_qp]) _qp += 1 if debug_mode == DebugMode.LIGHT: print("ELEM : {} | INTERNAL_FORCES_BEFORE STAB : \n {}". format(_element_index, element_internal_forces)) if verbose: print("ELEM : {} | INTERNAL_FORCES_BEFORE STAB : \n {}". format(_element_index, element_internal_forces)) # --- STAB PARAMETER CHANGE stab_param = stab_coef * material.stabilization_parameter # --- ADDING STABILIZATION CONTRIBUTION AT THE ELEMENT LEVEL element_stiffness_matrix += stab_param * element.stabilization_operator # element_stiffness_matrix -= stab_param * element.stabilization_operator # --- ADDING STABILIZATION CONTRIBUTION AT THE ELEMENT LEVEL element_internal_forces += ( stab_param * element.stabilization_operator @ element.get_element_unknown_vector(faces_unknown_vector)) # element_internal_forces -= ( # stab_param # * element.stabilization_operator # @ element.get_element_unknown_vector(problem.field, problem.finite_element, faces_unknown_vector) # ) # if verbose: # print( # "ELEM : {} | INTERNAL_FORCES_AFTER STAB : \n {}".format(_element_index, element_internal_forces) # ) # _iv0 = _element_index * len(element.cell.quadrature_weights) # _iv1 = (_element_index + 1) * len(element.cell.quadrature_weights) # print( # "ELEM : {} | DISPLACEMENT S0 : \n {}".format( # _element_index, # element.get_element_unknown_vector( # problem.field, problem.finite_element, faces_unknown_vector_previous_step # ), # ) # ) # print( # "ELEM : {} | GRADIENTS S0 : \n {}".format( # _element_index, material.mat_data.s0.gradients[_iv0:_iv1] # ) # ) # print( # "ELEM : {} | DISPLACEMENT S1 : \n {}".format( # _element_index, # element.get_element_unknown_vector( # problem.field, problem.finite_element, faces_unknown_vector # ), # ) # ) # print( # "ELEM : {} | GRADIENTS S1 : \n {}".format( # _element_index, material.mat_data.s1.gradients[_iv0:_iv1] # ) # ) # if not material.behaviour_name == "Elasticity": # print( # "ELEM : {} | INTERNAL_STATE_VARIABLES S0 : \n {}".format( # _element_index, material.mat_data.s0.internal_state_variables[_iv0:_iv1] # ) # ) # print( # "ELEM : {} | INTERNAL_STATE_VARIABLES S1 : \n {}".format( # _element_index, material.mat_data.s1.internal_state_variables[_iv0:_iv1] # ) # ) # --- BOUNDARY CONDITIONS for boundary_condition in problem.boundary_conditions: # --- DISPLACEMENT CONDITIONS if boundary_condition.boundary_type == BoundaryType.DISPLACEMENT: for f_local, f_global in enumerate( element.faces_indices): if f_global in problem.mesh.faces_boundaries_connectivity[ boundary_condition.boundary_name]: _l0 = _system_size + iter_face_constraint * _fk _l1 = _system_size + (iter_face_constraint + 1) * _fk _c0 = _cl * _dx + ( f_local * _dx * _fk) + boundary_condition.direction * _fk _c1 = _cl * _dx + (f_local * _dx * _fk) + ( boundary_condition.direction + 1) * _fk _r0 = f_global * _fk * _dx + _fk * boundary_condition.direction _r1 = f_global * _fk * _dx + _fk * ( boundary_condition.direction + 1) # ------- # face_displacement = element_unknown_increment[_r0:_r1] # face_displacement = np.copy(element_unknown_increment[_c0:_c1]) # face_displacement = element_unknown_increment[_c0:_c1] face_lagrange = faces_unknown_vector[_l0:_l1] face_displacement = faces_unknown_vector[ _r0:_r1] _m_psi_psi_face = np.zeros((_fk, _fk), dtype=real) _v_face_imposed_displacement = np.zeros( (_fk, ), dtype=real) face = element.faces[f_local] x_f = face.get_centroid() h_f = face.get_diameter() face_rot = face.get_rotation_matrix() face_quadrature_size = face.get_quadrature_size( problem.finite_element. construction_integration_order, quadrature_type=problem.quadrature_type, ) face_quadrature_points = face.get_quadrature_points( problem.finite_element. construction_integration_order, quadrature_type=problem.quadrature_type, ) face_quadrature_weights = face.get_quadrature_weights( problem.finite_element. construction_integration_order, quadrature_type=problem.quadrature_type, ) for _qf in range(face_quadrature_size): # _h_f = element.faces[f_local].shape.diameter # _x_f = element.faces[f_local].shape.centroid _x_q_f = face_quadrature_points[:, _qf] _w_q_f = face_quadrature_weights[_qf] _s_q_f = (face_rot @ _x_q_f)[:-1] _s_f = (face_rot @ x_f)[:-1] # v = problem.finite_element.face_basis_k.evaluate_function( # _x_q_f, # element.faces[f_local].shape.centroid, # element.faces[f_local].shape.diameter, # ) v = problem.finite_element.face_basis_k.evaluate_function( _s_q_f, _s_f, h_f) _v_face_imposed_displacement += ( _w_q_f * v * boundary_condition.function( time_step, _x_q_f)) # _m_psi_psi_face += blocks.get_face_mass_matrix_in_face( # element.faces[f_local], # problem.finite_element.face_basis_k, # problem.finite_element.face_basis_k, # _x_q_f, # _w_q_f, # ) _psi_k = problem.finite_element.face_basis_k.evaluate_function( _s_q_f, _s_f, h_f) _m_psi_psi_face += _w_q_f * np.tensordot( _psi_k, _psi_k, axes=0) _m_psi_psi_face_inv = np.linalg.inv( _m_psi_psi_face) if debug_mode == 0: print( "FACE MASS MATRIX IN DIRICHLET BOUND COND :" ) print("{}".format( np.linalg.cond(_m_psi_psi_face))) imposed_face_displacement = _m_psi_psi_face_inv @ _v_face_imposed_displacement face_displacement_difference = face_displacement - imposed_face_displacement # print(face_lagrange) # --- LAGRANGE INTERNAL FORCES PART element_internal_forces[ _c0: _c1] += normalization_lagrange_coefficient * face_lagrange # --- LAGRANGE MULTIPLIERS PART # residual[_l0:_l1] += ( # normalization_lagrange_coefficient * face_displacement_difference # ) residual[ _l0: _l1] -= normalization_lagrange_coefficient * face_displacement_difference # --- LAGRANGE MATRIX PART tangent_matrix[ _l0:_l1, _r0: _r1] += normalization_lagrange_coefficient * np.eye( _fk, dtype=real) tangent_matrix[ _r0:_r1, _l0: _l1] += normalization_lagrange_coefficient * np.eye( _fk, dtype=real) # --- SET EXTERNAL FORCES COEFFICIENT lagrange_external_forces = ( normalization_lagrange_coefficient * imposed_face_displacement) if np.max(np.abs(lagrange_external_forces) ) > external_forces_coefficient: external_forces_coefficient = np.max( np.abs(lagrange_external_forces)) iter_face_constraint += 1 elif boundary_condition.boundary_type == BoundaryType.PRESSURE: for f_local, f_global in enumerate( element.faces_indices): if f_global in problem.mesh.faces_boundaries_connectivity[ boundary_condition.boundary_name]: face = element.faces[f_local] x_f = face.get_centroid() h_f = face.get_diameter() face_rot = face.get_rotation_matrix() face_quadrature_size = face.get_quadrature_size( problem.finite_element. construction_integration_order, quadrature_type=problem.quadrature_type, ) face_quadrature_points = face.get_quadrature_points( problem.finite_element. construction_integration_order, quadrature_type=problem.quadrature_type, ) face_quadrature_weights = face.get_quadrature_weights( problem.finite_element. construction_integration_order, quadrature_type=problem.quadrature_type, ) for _qf in range(face_quadrature_size): # _h_f = element.faces[f_local].shape.diameter # _x_f = element.faces[f_local].shape.centroid _x_q_f = face_quadrature_points[:, _qf] _w_q_f = face_quadrature_weights[_qf] _s_q_f = (face_rot @ _x_q_f)[:-1] _s_f = (face_rot @ x_f)[:-1] # for qf in range(len(element.faces[f_local].quadrature_weights)): # # _h_f = element.faces[f_local].shape.diameter # # _x_f = element.faces[f_local].shape.centroid # _x_q_f = face_quadrature_points[:, _qf] # _w_q_f = face_quadrature_weights[_qf] # _s_q_f = (element.faces[f_local].mapping_matrix @ _x_q_f)[:-1] # _s_f = (element.faces[f_local].mapping_matrix @ _x_f)[:-1] # v = problem.finite_element.face_basis_k.evaluate_function( # _x_q_f, # element.faces[f_local].shape.centroid, # element.faces[f_local].shape.diameter, # ) v = problem.finite_element.face_basis_k.evaluate_function( _s_q_f, _s_f, h_f) # _x_q_f = element.faces[f_local].quadrature_points[:, qf] # _w_q_f = element.faces[f_local].quadrature_weights[qf] # v = problem.finite_element.face_basis_k.evaluate_function( # _x_q_f, # element.faces[f_local].shape.centroid, # element.faces[f_local].shape.diameter, # ) vf = _w_q_f * v * boundary_condition.function( time_step, _x_q_f) _c0 = _dx * _cl + f_local * _dx * _fk + boundary_condition.direction * _fk _c1 = _dx * _cl + f_local * _dx * _fk + ( boundary_condition.direction + 1) * _fk # _r0 = f_global * _fk * _dx + _fk * boundary_condition.direction # _r1 = f_global * _fk * _dx + _fk * (boundary_condition.direction + 1) element_external_forces[_c0:_c1] += vf # --- COMPUTE RESIDUAL AFTER VOLUMETRIC CONTRIBUTION element_residual = element_internal_forces - element_external_forces if verbose: print("ELEM : {} | INTERNAL_FORCES_END : \n {}".format( _element_index, element_internal_forces)) print("ELEM : {} | ELEMENT_RESIDUAL : \n {}".format( _element_index, element_residual)) # -------------------------------------------------------------------------------------------------- # CONDENSATION # -------------------------------------------------------------------------------------------------- m_cell_cell = element_stiffness_matrix[:_c0_c, :_c0_c] m_cell_faces = element_stiffness_matrix[:_c0_c, _c0_c:] m_faces_cell = element_stiffness_matrix[_c0_c:, :_c0_c] m_faces_faces = element_stiffness_matrix[_c0_c:, _c0_c:] # v_cell = element_residual[:_c0_c] # v_faces = element_residual[_c0_c:] v_cell = -element_residual[:_c0_c] v_faces = -element_residual[_c0_c:] _condtest = np.linalg.cond(m_cell_cell) m_cell_cell_inv = np.linalg.inv(m_cell_cell) if debug_mode == 0: print("TANGENT MATRIX IN CONDENSATION COND :") print("{}".format(np.linalg.cond(m_cell_cell))) # ge = m_faces_cell @ m_cell_cell_inv # gd = (m_faces_cell @ m_cell_cell_inv) @ m_cell_faces K_cond = m_faces_faces - ( (m_faces_cell @ m_cell_cell_inv) @ m_cell_faces) R_cond = v_faces - (m_faces_cell @ m_cell_cell_inv) @ v_cell # --- SET CONDENSATION/DECONDENSATION MATRICES element.m_cell_cell_inv = m_cell_cell_inv element.m_cell_faces = m_cell_faces element.v_cell = v_cell # --- ASSEMBLY for _i_local, _i_global in enumerate(element.faces_indices): _rg0 = _i_global * (_fk * _dx) _rg1 = (_i_global + 1) * (_fk * _dx) _re0 = _i_local * (_fk * _dx) _re1 = (_i_local + 1) * (_fk * _dx) residual[_rg0:_rg1] += R_cond[_re0:_re1] for _j_local, _j_global in enumerate( element.faces_indices): _cg0 = _j_global * (_fk * _dx) _cg1 = (_j_global + 1) * (_fk * _dx) _ce0 = _j_local * (_fk * _dx) _ce1 = (_j_local + 1) * (_fk * _dx) tangent_matrix[_rg0:_rg1, _cg0:_cg1] += K_cond[_re0:_re1, _ce0:_ce1] # --- SET EXTERNAL FORCES COEFFICIENT if np.max(np.abs(element_external_forces) ) > external_forces_coefficient: external_forces_coefficient = np.max( np.abs(element_external_forces)) # -------------------------------------------------------------------------------------------------- # RESIDUAL EVALUATION # -------------------------------------------------------------------------------------------------- if external_forces_coefficient == 0.0: external_forces_coefficient = 1.0 residual_evaluation = np.max( np.abs(residual)) / external_forces_coefficient print("ITER : {} | RES_MAX : {}".format( str(iteration).zfill(4), residual_evaluation)) # print("ITER : {} | =====================================================================".format(str(iteration).zfill(4))) # residual_values.append(residual_evaluation) # if residual_evaluation < problem.tolerance: if residual_evaluation < problem.tolerance: # ---------------------------------------------------------------------------------------------- # UPDATE INTERNAL VARIABLES # ---------------------------------------------------------------------------------------------- mgis_bv.update(material.mat_data) print("ITERATIONS : {}".format(iteration + 1)) file_suffix = "{}".format(time_step_index).zfill(6) problem.create_vertex_res_files(problem.res_folder_path, file_suffix) problem.create_quadrature_points_res_files( problem.res_folder_path, file_suffix, material) problem.write_vertex_res_files(problem.res_folder_path, file_suffix, faces_unknown_vector) problem.write_quadrature_points_res_files( problem.res_folder_path, file_suffix, material, faces_unknown_vector) # problem.create_output(problem.res_folder_path) problem.fill_quadrature_stress_output(problem.res_folder_path, "CAUCHY_STRESS", time_step_index_count, time_step, material) problem.fill_quadrature_strain_output(problem.res_folder_path, "STRAIN", time_step_index_count, time_step, material) # problem.close_output(problem.res_folder_path) time_step_index_count += 1 faces_unknown_vector_previous_step = np.copy( faces_unknown_vector) for element in problem.elements: element.cell_unknown_vector_backup = np.copy( element.cell_unknown_vector) residual_values.append(residual_evaluation) time_step_temp = time_step + 0. break elif iteration == problem.number_of_iterations - 1: problem.time_steps.insert(time_step_index + 1, (time_step + time_step_temp) / 2.) faces_unknown_vector = np.copy( faces_unknown_vector_previous_step) for element in problem.elements: # element.cell_unknown_vector = np.zeros((_cl * _dx,)) element.cell_unknown_vector = np.copy( element.cell_unknown_vector_backup) break else: # ---------------------------------------------------------------------------------------------- # SOLVE SYSTEM # ---------------------------------------------------------------------------------------------- if debug_mode == 0: print("K GLOBAL COND") print("{}".format(np.linalg.cond(tangent_matrix))) # sparse_global_matrix = csr_matrix(-tangent_matrix) sparse_global_matrix = csr_matrix(tangent_matrix) correction = spsolve(sparse_global_matrix, residual) # print("CORRECTION :") # print(correction) # correction = np.linalg.solve(-tangent_matrix, residual) faces_unknown_vector += correction if verbose: print( "R_K_RES : \n {}".format(residual - tangent_matrix @ correction)) print("R_K_RES_NORMALIZED : \n {}".format( (residual - tangent_matrix @ correction) / external_forces_coefficient)) # ---------------------------------------------------------------------------------------------- # DECONDENSATION # ---------------------------------------------------------------------------------------------- for element in problem.elements: _nf = len(element.faces) # _c0_c = _dx * _cl # --- DECONDENSATION - GET ELEMENT UNKNOWN CORRECTION face_correction = np.zeros((_nf * _fk * _dx), dtype=real) # element_correction = np.zeros((element.element_size,)) for _i_local, _i_global in enumerate( element.faces_indices): _c0_fg = _i_global * (_fk * _dx) _c1_fg = (_i_global + 1) * (_fk * _dx) # _c0_fl = (_dx * _cl) + _i_local * (_fk * _dx) # _c1_fl = (_dx * _cl) + (_i_local + 1) * (_fk * _dx) _c0_fl = _i_local * (_fk * _dx) _c1_fl = (_i_local + 1) * (_fk * _dx) # element_correction[_c0_fl:_c1_fl] += correction[_c0_fg:_c1_fg] face_correction[_c0_fl:_c1_fl] += correction[ _c0_fg:_c1_fg] # element_correction[:_c0_c] = element.m_cell_cell_inv @ ( # element.v_cell - element.m_cell_faces @ element_correction[_c0_c:] # ) cell_correction = element.m_cell_cell_inv @ ( element.v_cell - element.m_cell_faces @ face_correction) # --- ADDING CORRECTION TO CURRENT DISPLACEMENT element.cell_unknown_vector += cell_correction plt.plot(range(len(residual_values)), residual_values, label="residual") plt.plot(range(len(residual_values)), [problem.tolerance for local_i in range(len(residual_values))], label="tolerance") plt.ylabel("resiudal after convergence") plt.xlabel("time step index") plt.title("evolution of the residual") plt.legend() plt.gcf().subplots_adjust(left=0.15) plt.show() return
def solve_newton_exact(problem: Problem, material: Material, verbose: bool = False, debug_mode: DebugMode = DebugMode.NONE): """ Args: material: Returns: """ clean_res_dir(problem.res_folder_path) _dx = problem.field.field_dimension _fk = problem.finite_element.face_basis_k.dimension _cl = problem.finite_element.cell_basis_l.dimension external_forces_coefficient = 1.0 normalization_lagrange_coefficient = material.lagrange_parameter # ---------------------------------------------------------------------------------------------------------- # SET SYSTEM SIZE # ---------------------------------------------------------------------------------------------------------- _constrained_system_size, _system_size = problem.get_total_system_size() faces_unknown_vector = np.zeros((_constrained_system_size), dtype=real) faces_unknown_vector_previous_step = np.zeros((_constrained_system_size), dtype=real) residual_values = [] correction = np.zeros((_constrained_system_size), dtype=real) for time_step_index, time_step in enumerate(problem.time_steps): # --- SET TEMPERATURE material.set_temperature() # --- PRINT DATA print( "----------------------------------------------------------------------------------------------------" ) print("TIME_STEP : {} | LOAD_VALUE : {}".format( time_step_index, time_step)) # --- WRITE RES FILES file_suffix = "{}".format(time_step_index).zfill(6) problem.create_vertex_res_files(problem.res_folder_path, file_suffix) problem.create_quadrature_points_res_files(problem.res_folder_path, file_suffix, material) # correction = np.zeros((_constrained_system_size),dtype=real) # --- RESET DISPLACEMENT reset_displacement = False if reset_displacement: faces_unknown_vector = np.zeros((_constrained_system_size), dtype=real) for element in problem.elements: element.cell_unknown_vector = np.zeros((_dx * _cl, ), dtype=real) for iteration in range(problem.number_of_iterations): # -------------------------------------------------------------------------------------------------- # SET SYSTEM MATRIX AND VECTOR # -------------------------------------------------------------------------------------------------- tangent_matrix = np.zeros( (_constrained_system_size, _constrained_system_size), dtype=real) residual = np.zeros((_constrained_system_size), dtype=real) # -------------------------------------------------------------------------------------------------- # SET TIME INCREMENT # -------------------------------------------------------------------------------------------------- if time_step_index == 0: _dt = time_step else: _dt = time_step - problem.time_steps[time_step_index - 1] _dt = np.float64(_dt) # -------------------------------------------------------------------------------------------------- # FOR ELEMENT LOOP # -------------------------------------------------------------------------------------------------- _qp = 0 stab_coef = 1.0 stab_inf = np.inf iter_face_constraint = 0 if False: for element in problem.elements: for _qc in range(len(element.cell.quadrature_weights)): _w_q_c = element.cell.quadrature_weights[_qc] _x_q_c = element.cell.quadrature_points[:, _qc] # --- COMPUTE STRAINS AND SET THEM IN THE BEHAVIOUR LAW transformation_gradient = element.get_transformation_gradient( problem.field, problem.finite_element, faces_unknown_vector, _qc) material.mat_data.s1.gradients[ _qp] = transformation_gradient # --- INTEGRATE BEHAVIOUR LAW integ_res = mgis_bv.integrate( material.mat_data, material.integration_type, _dt, _qp, (_qp + 1)) eigen_values = np.linalg.eig( material.mat_data.K[_qp])[0] stab_elem = np.min( eigen_values) / material.stabilization_parameter if stab_elem < stab_inf and stab_elem > 1.0: stab_inf = stab_elem stab_coef = stab_elem _qp += 1 mgis_bv.revert(material.mat_data) _qp = 0 for _element_index, element in enumerate(problem.elements): cell_quadrature_size = element.cell.get_quadrature_size( problem.finite_element.construction_integration_order, quadrature_type=problem.quadrature_type) cell_quadrature_points = element.cell.get_quadrature_points( problem.finite_element.construction_integration_order, quadrature_type=problem.quadrature_type) cell_quadrature_weights = element.cell.get_quadrature_weights( problem.finite_element.construction_integration_order, quadrature_type=problem.quadrature_type) x_c = element.cell.get_centroid() h_c = element.cell.get_diameter() print("ELEMENT : {}".format(_element_index)) # --- GET FACES LOCAL CORRECTION local_faces_correction = np.zeros( (len(element.faces) * _dx * _fk), dtype=real) for _f_local, _f_global in enumerate(element.faces_indices): local_faces_correction[_f_local * _dx * _fk:(_f_local + 1) * _dx * _fk] += ( correction[_f_global * _dx * _fk:(_f_global + 1) * _dx * _fk]) # --- LOCAL NEWTON number_of_local_iterations = 20 # local_tolerance = problem.tolerance local_tolerance = 1.e-4 R_cell_value_previous = np.inf for _local_iteration in range(number_of_local_iterations): _nf = len(element.faces) _c0_c = _dx * _cl # --- INITIALIZE MATRIX AND VECTORS element_stiffness_matrix = np.zeros( (element.element_size, element.element_size), dtype=real) element_internal_forces = np.zeros( (element.element_size, ), dtype=real) element_external_forces = np.zeros( (element.element_size, ), dtype=real) # --- RUN OVER EACH QUADRATURE POINT _local_qp = 0 for _qc in range(cell_quadrature_size): _w_q_c = cell_quadrature_weights[_qc] _x_q_c = cell_quadrature_points[:, _qc] # --- COMPUTE STRAINS AND SET THEM IN THE BEHAVIOUR LAW transformation_gradient = element.get_transformation_gradient( faces_unknown_vector, _qc) material.mat_data.s1.gradients[ _qp] = transformation_gradient # --- INTEGRATE BEHAVIOUR LAW integ_res = mgis_bv.integrate( material.mat_data, material.integration_type, _dt, _qp, (_qp + 1)) # stored_energies', 'dissipated_energies', 'internal_state_variables # print(material.mat_data.s1.internal_state_variables) # --- VOLUMETRIC FORCES v = problem.finite_element.cell_basis_l.evaluate_function( _x_q_c, x_c, h_c) for load in problem.loads: vl = _w_q_c * v * load.function(time_step, _x_q_c) _re0 = load.direction * _cl _re1 = (load.direction + 1) * _cl element_external_forces[_re0:_re1] += vl # --- COMPUTE STIFFNESS MATRIX CONTRIBUTION AT QUADRATURE POINT element_stiffness_matrix += _w_q_c * ( element.gradients_operators[_qc].T @ material. mat_data.K[_qp] @ element.gradients_operators[_qc]) # --- COMPUTE STIFFNESS MATRIX CONTRIBUTION AT QUADRATURE POINT element_internal_forces += _w_q_c * ( element.gradients_operators[_qc].T @ material.mat_data.s1.thermodynamic_forces[_qp]) _qp += 1 _local_qp += 1 if verbose: print( "ELEM : {} | INTERNAL_FORCES_BEFORE STAB : \n {}". format(_element_index, element_internal_forces)) # --- STAB PARAMETER CHANGE stab_param = stab_coef * material.stabilization_parameter # if check and iteration > 0: # numerical_element_stiffness_matrix = ( # numerical_forces_bs_0[_element_index] - # numerical_forces_bs_1[_element_index] # ) / (2.0 * noise) # check_num = np.max( # np.abs(numerical_element_stiffness_matrix - element_stiffness_matrix) # ) / np.max(np.abs(element_stiffness_matrix)) # if check_num > noise_tolerance: # print( # "AT ELEM : {} | CHECK_BEFORE_STAB : {}".format(str(_element_index).zfill(6), check_num) # ) # --- ADDING STABILIZATION CONTRIBUTION AT THE ELEMENT LEVEL element_stiffness_matrix += stab_param * element.stabilization_operator # element_stiffness_matrix -= stab_param * element.stabilization_operator # --- ADDING STABILIZATION CONTRIBUTION AT THE ELEMENT LEVEL element_internal_forces += ( stab_param * element.stabilization_operator @ element. get_element_unknown_vector(faces_unknown_vector)) # --- MATRIX VECTOR DECOMPOSITION K_cc = element_stiffness_matrix[:_c0_c, :_c0_c] K_cf = element_stiffness_matrix[:_c0_c, _c0_c:] # local_external_forces_coefficient = np.max(np.abs(element_external_forces)) element_residual = element_internal_forces - element_external_forces # if local_external_forces_coefficient == 0.: # local_external_forces_coefficient = 1.0 # local_external_forces_coefficient = normalization_lagrange_coefficient # local_external_forces_coefficient = 1./element.cell.shape.volume R_cc = element_residual[:_c0_c] if iteration == 0: local_external_forces_coefficient = 1.0 cell_correction = np.ones((_cl * _dx, ), dtype=real) if _local_iteration == 0 and iteration > 0: cell_correction = np.ones((_cl * _dx, ), dtype=real) local_external_forces_coefficient = np.max( np.abs(R_cc)) # local_external_forces_coefficient = 1. # if local_external_forces_coefficient == 0.0 or local_external_forces_coefficient < local_tolerance: if local_external_forces_coefficient == 0.0: local_external_forces_coefficient = 1.0 # R_cell = R_cc - K_cf @ local_faces_correction # print("LOCAL_EXTERNAL_FORCES_COEF : {}".format(local_external_forces_coefficient)) R_cell = R_cc local_residual_evaluation = np.max( np.abs(R_cell) / local_external_forces_coefficient) # local_residual_evaluation = np.max(np.abs(cell_correction)) # if local_residual_evaluation > R_cell_value_previous: # print("!!!! RESIUDAL INCREASE :\n {}".format(element.cell.quadrature_points)) # R_cell_value_previous = local_residual_evaluation print("LOCAL ITER : {} | RES MAX : {}".format( _local_iteration, local_residual_evaluation)) if local_residual_evaluation < local_tolerance: break else: cell_correction = np.linalg.solve(-K_cc, R_cell) element.cell_unknown_vector += cell_correction if _local_iteration != number_of_local_iterations - 1: _qp -= _local_qp # element_internal_forces -= ( # stab_param # * element.stabilization_operator # @ element.get_element_unknown_vector(problem.field, problem.finite_element, faces_unknown_vector) # ) # -------------------------------------------------------------------------------------------------- # CONDENSATION # -------------------------------------------------------------------------------------------------- m_cell_cell = element_stiffness_matrix[:_c0_c, :_c0_c] m_cell_faces = element_stiffness_matrix[:_c0_c, _c0_c:] m_faces_cell = element_stiffness_matrix[_c0_c:, :_c0_c] m_faces_faces = element_stiffness_matrix[_c0_c:, _c0_c:] # v_cell = element_residual[:_c0_c] # v_faces = element_residual[_c0_c:] v_cell = -element_residual[:_c0_c] v_faces = -element_residual[_c0_c:] m_cell_cell_inv = np.linalg.inv(m_cell_cell) if debug_mode == 0: print("TANGENT MATRIX IN CONDENSATION COND :") print("{}".format(np.linalg.cond(m_cell_cell))) # ge = m_faces_cell @ m_cell_cell_inv # gd = (m_faces_cell @ m_cell_cell_inv) @ m_cell_faces K_cond = m_faces_faces - ( (m_faces_cell @ m_cell_cell_inv) @ m_cell_faces) R_cond = v_faces - (m_faces_cell @ m_cell_cell_inv) @ v_cell # --- SET CONDENSATION/DECONDENSATION MATRICES # element.m_cell_cell_inv = m_cell_cell_inv # element.m_cell_faces = m_cell_faces # element.v_cell = v_cell # --- ASSEMBLY for _i_local, _i_global in enumerate(element.faces_indices): _rg0 = _i_global * (_fk * _dx) _rg1 = (_i_global + 1) * (_fk * _dx) _re0 = _i_local * (_fk * _dx) _re1 = (_i_local + 1) * (_fk * _dx) residual[_rg0:_rg1] += R_cond[_re0:_re1] for _j_local, _j_global in enumerate( element.faces_indices): _cg0 = _j_global * (_fk * _dx) _cg1 = (_j_global + 1) * (_fk * _dx) _ce0 = _j_local * (_fk * _dx) _ce1 = (_j_local + 1) * (_fk * _dx) tangent_matrix[_rg0:_rg1, _cg0:_cg1] += K_cond[_re0:_re1, _ce0:_ce1] # --- SET EXTERNAL FORCES COEFFICIENT if np.max(np.abs(element_external_forces) ) > external_forces_coefficient: external_forces_coefficient = np.max( np.abs(element_external_forces)) # if check and iteration > 0: # numerical_element_stiffness_matrix = ( # numerical_forces_as_0[_element_index] - # numerical_forces_as_1[_element_index] # ) / (2.0 * noise) # check_num = np.max( # np.abs(numerical_element_stiffness_matrix - element_stiffness_matrix) # ) / np.max(np.abs(element_stiffness_matrix)) # if check_num > noise_tolerance: # print( # "AT ELEM : {} | CHECK_BEFORE_STAB : {}".format(str(_element_index).zfill(6), check_num) # ) if verbose: pass # print("ELEM : {} | INTERNAL_FORCES_AFTER STAB : \n {}".format(_element_index, # element_internal_forces)) # _iv0 = _element_index * len(element.cell.quadrature_weights) # _iv1 = (_element_index + 1) * len(element.cell.quadrature_weights) # print("ELEM : {} | DISPLACEMENT S0 : \n {}".format(_element_index, # element.get_element_unknown_vector(problem.field, # problem.finite_element, # faces_unknown_vector_previous_step))) # print("ELEM : {} | GRADIENTS S0 : \n {}".format(_element_index, # material.mat_data.s0.gradients[_iv0:_iv1])) # print("ELEM : {} | DISPLACEMENT S1 : \n {}".format(_element_index, # element.get_element_unknown_vector(problem.field, # problem.finite_element, # faces_unknown_vector))) # print("ELEM : {} | GRADIENTS S1 : \n {}".format(_element_index, # material.mat_data.s1.gradients[_iv0:_iv1])) # if not material.behaviour_name == "Elasticity": # print("ELEM : {} | INTERNAL_STATE_VARIABLES S0 : \n {}".format(_element_index, # material.mat_data.s0.internal_state_variables[ # _iv0:_iv1])) # print("ELEM : {} | INTERNAL_STATE_VARIABLES S1 : \n {}".format(_element_index, # material.mat_data.s1.internal_state_variables[ # _iv0:_iv1])) # --- BOUNDARY CONDITIONS for boundary_condition in problem.boundary_conditions: # --- DISPLACEMENT CONDITIONS if boundary_condition.boundary_type == BoundaryType.DISPLACEMENT: for f_local, f_global in enumerate( element.faces_indices): if (f_global in problem.mesh.faces_boundaries_connectivity[ boundary_condition.boundary_name]): _l0 = _system_size + iter_face_constraint * _fk _l1 = _system_size + (iter_face_constraint + 1) * _fk _c0 = _cl * _dx + ( f_local * _dx * _fk) + boundary_condition.direction * _fk _c1 = _cl * _dx + (f_local * _dx * _fk) + ( boundary_condition.direction + 1) * _fk _r0 = f_global * _fk * _dx + _fk * boundary_condition.direction _r1 = f_global * _fk * _dx + _fk * ( boundary_condition.direction + 1) # ------- # face_displacement = element_unknown_increment[_r0:_r1] # face_displacement = np.copy(element_unknown_increment[_c0:_c1]) # face_displacement = element_unknown_increment[_c0:_c1] face_lagrange = faces_unknown_vector[_l0:_l1] face_displacement = faces_unknown_vector[ _r0:_r1] _m_psi_psi_face = np.zeros((_fk, _fk), dtype=real) _v_face_imposed_displacement = np.zeros( (_fk, ), dtype=real) face = element.faces[f_local] x_f = face.get_centroid() h_f = face.get_diameter() face_rot = face.get_rotation_matrix() face_quadrature_size = face.get_quadrature_size( problem.finite_element. construction_integration_order, quadrature_type=problem.quadrature_type, ) face_quadrature_points = face.get_quadrature_points( problem.finite_element. construction_integration_order, quadrature_type=problem.quadrature_type, ) face_quadrature_weights = face.get_quadrature_weights( problem.finite_element. construction_integration_order, quadrature_type=problem.quadrature_type, ) for _qf in range(face_quadrature_size): _x_q_f = face_quadrature_points[:, _qf] _w_q_f = face_quadrature_weights[_qf] _s_q_f = (face_rot @ _x_q_f)[:-1] _s_f = (face_rot @ x_f)[:-1] v = problem.finite_element.face_basis_k.evaluate_function( _s_q_f, _s_f, h_f) _v_face_imposed_displacement += ( _w_q_f * v * boundary_condition.function( time_step, _x_q_f)) _psi_k = problem.finite_element.face_basis_k.evaluate_function( _s_q_f, _s_f, h_f) _m_psi_psi_face += _w_q_f * np.tensordot( _psi_k, _psi_k, axes=0) _m_psi_psi_face_inv = np.linalg.inv( _m_psi_psi_face) if debug_mode == 0: print( "FACE MASS MATRIX IN DIRICHLET BOUND COND :" ) print("{}".format( np.linalg.cond(_m_psi_psi_face))) imposed_face_displacement = _m_psi_psi_face_inv @ _v_face_imposed_displacement face_displacement_difference = face_displacement - imposed_face_displacement # --- LAGRANGE INTERNAL FORCES PART # element_internal_forces[_c0:_c1] += ( # normalization_lagrange_coefficient * face_lagrange # ) # residual[_r0:_r1] += ( # normalization_lagrange_coefficient * face_lagrange # ) residual[_r0:_r1] -= ( normalization_lagrange_coefficient * face_lagrange) # --- LAGRANGE MULTIPLIERS PART # residual[_l0:_l1] += ( # normalization_lagrange_coefficient * face_displacement_difference # ) residual[_l0:_l1] -= ( normalization_lagrange_coefficient * face_displacement_difference) # --- LAGRANGE MATRIX PART tangent_matrix[ _l0:_l1, _r0: _r1] += normalization_lagrange_coefficient * np.eye( _fk, dtype=real) tangent_matrix[ _r0:_r1, _l0: _l1] += normalization_lagrange_coefficient * np.eye( _fk, dtype=real) # --- SET EXTERNAL FORCES COEFFICIENT lagrange_external_forces = ( normalization_lagrange_coefficient * imposed_face_displacement) if np.max(np.abs(lagrange_external_forces) ) > external_forces_coefficient: external_forces_coefficient = np.max( np.abs(lagrange_external_forces)) iter_face_constraint += 1 elif boundary_condition.boundary_type == BoundaryType.PRESSURE: for f_local, f_global in enumerate( element.faces_indices): if (f_global in problem.mesh.faces_boundaries_connectivity[ boundary_condition.boundary_name]): face = element.faces[f_local] x_f = face.get_centroid() h_f = face.get_diameter() face_rot = face.get_rotation_matrix() face_quadrature_size = face.get_quadrature_size( problem.finite_element. construction_integration_order, quadrature_type=problem.quadrature_type, ) face_quadrature_points = face.get_quadrature_points( problem.finite_element. construction_integration_order, quadrature_type=problem.quadrature_type, ) face_quadrature_weights = face.get_quadrature_weights( problem.finite_element. construction_integration_order, quadrature_type=problem.quadrature_type, ) for _qf in range(face_quadrature_size): # _h_f = element.faces[f_local].shape.diameter # _x_f = element.faces[f_local].shape.centroid _x_q_f = face_quadrature_points[:, _qf] _w_q_f = face_quadrature_weights[_qf] _s_q_f = (face_rot @ _x_q_f)[:-1] _s_f = (face_rot @ x_f)[:-1] v = problem.finite_element.face_basis_k.evaluate_function( _s_q_f, _s_f, h_f) vf = _w_q_f * v * boundary_condition.function( time_step, _x_q_f) # _c0 = _dx * _cl + f_local * _dx * _fk + boundary_condition.direction * _fk # _c1 = _dx * _cl + f_local * _dx * _fk + (boundary_condition.direction + 1) * _fk _r0 = f_global * _fk * _dx + _fk * boundary_condition.direction _r1 = f_global * _fk * _dx + _fk * ( boundary_condition.direction + 1) # element_external_forces[_c0:_c1] += vf # residual[_r0:_r1] -= vf residual[_r0:_r1] += vf if np.max(np.abs( vf)) > external_forces_coefficient: external_forces_coefficient = np.max( np.abs(vf)) # -------------------------------------------------------------------------------------------------- # RESIDUAL EVALUATION # -------------------------------------------------------------------------------------------------- if external_forces_coefficient == 0.0: external_forces_coefficient = 1.0 residual_evaluation = np.max( np.abs(residual)) / external_forces_coefficient print("ITER : {} | RES_MAX : {}".format( str(iteration).zfill(4), residual_evaluation)) # print("ITER : {} | =====================================================================".format(str(iteration).zfill(4))) # residual_values.append(residual_evaluation) # if residual_evaluation < problem.tolerance: if residual_evaluation < problem.tolerance or iteration == problem.number_of_iterations - 1: # ---------------------------------------------------------------------------------------------- # UPDATE INTERNAL VARIABLES # ---------------------------------------------------------------------------------------------- mgis_bv.update(material.mat_data) print("ITERATIONS : {}".format(iteration + 1)) problem.write_vertex_res_files(problem.res_folder_path, file_suffix, faces_unknown_vector) problem.write_quadrature_points_res_files( problem.res_folder_path, file_suffix, material, faces_unknown_vector) faces_unknown_vector_previous_step += faces_unknown_vector residual_values.append(residual_evaluation) break else: # ---------------------------------------------------------------------------------------------- # SOLVE SYSTEM # ---------------------------------------------------------------------------------------------- if debug_mode == 0: print("K GLOBAL COND") print("{}".format(np.linalg.cond(tangent_matrix))) # sparse_global_matrix = csr_matrix(-tangent_matrix) sparse_global_matrix = csr_matrix(tangent_matrix) correction = spsolve(sparse_global_matrix, residual) print("CORRECTION :") # print(correction) # correction = np.linalg.solve(-tangent_matrix, residual) faces_unknown_vector += correction if verbose: print( "R_K_RES : \n {}".format(residual - tangent_matrix @ correction)) print("R_K_RES_NORMALIZED : \n {}".format( (residual - tangent_matrix @ correction) / external_forces_coefficient)) plt.plot(range(len(residual_values)), residual_values, label="residual") plt.plot(range(len(residual_values)), [problem.tolerance for local_i in range(len(residual_values))], label="tolerance") plt.ylabel("resiudal after convergence") plt.xlabel("time step index") plt.title("evolution of the residual") plt.legend() plt.gcf().subplots_adjust(left=0.15) plt.show() return
def __updateStrainStress(self,du): #private method dstrain = self.__spfem.calcStrain(VectorX(du)) self.__materData.s1.gradients[:,:] += numpy.array(dstrain) mgis_bv.integrate(pool, self.__materData, IT, self.__dt) #parallel stress integration mgis_bv.update(self.__materData)