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 update_constitutive_law(self): """Performs the consitutive law update""" for c in self._before_update_constitutive_law_callbacks: c() self.update_gradients() self.material.update_external_state_variables( self.quadrature_degree, self.mesh, self.state_variables["external"]) # integrate the behaviour mgis_bv.integrate( self.material.data_manager, self.integration_type, self.dt, 0, self.material.data_manager.n, ) # getting the stress and consistent tangent operator back to # the FEniCS world. self.update_fluxes() self.update_tangent_blocks() self.update_internal_state_variables()
def test_behaviour_data(self): eps = 1.e-14 h = mgis_bv.Hypothesis.Tridimensional b = self.__get_behaviour(h) d = mgis_bv.BehaviourData(b) self.assertTrue(len(d.s0.external_state_variables) == 55, "invalid array size for the external state variables") self.assertTrue(len(d.s1.external_state_variables) == 55, "invalid array size for the external state variables") v_esv_values = numpy.asarray([1, 2, 3], dtype=numpy.float64) print(v_esv_values) mgis_bv.setExternalStateVariable(d.s1, "v_esv", v_esv_values) mgis_bv.integrate(d, b) for i in range(0, 3): self.assertTrue(abs(d.s1.external_state_variables[i + 1] - v_esv_values[i]) < eps, "invalid external state variable value") self.assertTrue(abs(d.s1.internal_state_variables[i] - v_esv_values[i]) < eps, "invalid internal state variable value") pass
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_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
# FunctionSpace (here piecewise constant) and Function for output of the equivalent # plastic strain since XDMF output does not handle Quadrature elements:: file_results = XDMFFile("plasticity_results.xdmf") file_results.parameters["flush_output"] = True file_results.parameters["functions_share_mesh"] = True P0 = FunctionSpace(mesh, "DG", 0) p_avg = Function(P0, name="Plastic strain") # The tangent stiffness is also initialized with the elasticity matrix: # one integrates the behaviour over the time step and computes an elastic stiffness it = mgis_bv.IntegrationType.PredictionWithElasticOperator #print("m.n: ", m.n) #m.n numer of intergation points mgis_bv.integrate(m, it, 0, 0, m.n); tangent_operators = m.K.flatten() #print("m.K_stride:",m.K_stride) Ct.vector().set_local(tangent_operators[0::2]) Ct.vector().apply("insert") print("Tangent Operator:",tangent_operators[0::2]) # getting the coupled tangent operator Dt.vector().set_local(tangent_operators[1::2]) Dt.vector().apply("insert") print("Coupled Tangent Operator:",tangent_operators[1::2]) # The main difference with respect to the pure FEniCS implementation of the previous # tutorial is that `MFront` computes the current stress state and stiffness matrix # (``integrate`` method) based on the value of the total strain which is computed # from the total displacement estimate ``u1``. The associated strain is projected
def test_material_data_manager(self): eps = 1.e-14 dt = 0.1 h = mgis_bv.Hypothesis.Tridimensional b = self.__get_behaviour(h) d = mgis_bv.MaterialDataManager(b, 2) mgis_bv.setMaterialProperty(d.s0, "YoungModulus", 150e9) mgis_bv.setMaterialProperty(d.s0, "PoissonRatio", 0.3) mgis_bv.setMaterialProperty(d.s1, "YoungModulus", 150e9) mgis_bv.setMaterialProperty(d.s1, "PoissonRatio", 0.3) # zeros = numpy.zeros(9) # v_esv is uniform v_esv_values = numpy.asarray([1, 2, 3], dtype=numpy.float64) mgis_bv.setExternalStateVariable(d.s0, "v_esv", zeros[0:3], mgis_bv.MaterialStateManagerStorageMode.EXTERNAL_STORAGE) mgis_bv.setExternalStateVariable(d.s1, "v_esv", v_esv_values, mgis_bv.MaterialStateManagerStorageMode.LOCAL_STORAGE) # v2_esv[0] is not uniform v2_esv0_values = numpy.asarray([1, 2, 3, 7, 6, 5], dtype=numpy.float64) mgis_bv.setExternalStateVariable(d.s0, "v2_esv[0]",zeros[0:3], mgis_bv.MaterialStateManagerStorageMode.EXTERNAL_STORAGE) mgis_bv.setExternalStateVariable(d.s1, "v2_esv[0]", v2_esv0_values, mgis_bv.MaterialStateManagerStorageMode.EXTERNAL_STORAGE) v2_esv1_values = numpy.asarray([9, 8, 2, 3, 6, 4], dtype=numpy.float64) mgis_bv.setExternalStateVariable(d.s0, "v2_esv[1]", zeros[0:3], mgis_bv.MaterialStateManagerStorageMode.EXTERNAL_STORAGE) mgis_bv.setExternalStateVariable(d.s1, "v2_esv[1]", v2_esv1_values, mgis_bv.MaterialStateManagerStorageMode.EXTERNAL_STORAGE) for s in [d.s0, d.s1]: mgis_bv.setExternalStateVariable(s, "Temperature", zeros[0:1], mgis_bv.MaterialStateManagerStorageMode.EXTERNAL_STORAGE) mgis_bv.setExternalStateVariable(s, "s_esv", zeros[0:6], mgis_bv.MaterialStateManagerStorageMode.EXTERNAL_STORAGE) mgis_bv.setExternalStateVariable(s, "s2_esv[0]", zeros[0:6], mgis_bv.MaterialStateManagerStorageMode.EXTERNAL_STORAGE) mgis_bv.setExternalStateVariable(s, "s2_esv[1]", zeros[0:6], mgis_bv.MaterialStateManagerStorageMode.EXTERNAL_STORAGE) mgis_bv.setExternalStateVariable(s, "t_esv", zeros[0:9], mgis_bv.MaterialStateManagerStorageMode.EXTERNAL_STORAGE) mgis_bv.setExternalStateVariable(s, "t2_esv[0]", zeros[0:9], mgis_bv.MaterialStateManagerStorageMode.EXTERNAL_STORAGE) mgis_bv.setExternalStateVariable(s, "t2_esv[1]", zeros[0:9], mgis_bv.MaterialStateManagerStorageMode.EXTERNAL_STORAGE) # checking if the external storage do work as expected v2_esv1_values[3] = -1 mgis_bv.integrate(d, mgis_bv.IntegrationType.INTEGRATION_NO_TANGENT_OPERATOR, dt, 0, 2) for i in range (0, 3): self.assertTrue(abs(d.s1.internal_state_variables[0, i] - v_esv_values[i]) < eps, "invalid internal state variable value") self.assertTrue(abs(d.s1.internal_state_variables[1, i] - v_esv_values[i]) < eps, "invalid internal state variable value") self.assertTrue(abs(d.s1.internal_state_variables[0, i + 3] - v2_esv0_values[i]) < eps, "invalid internal state variable value") self.assertTrue(abs(d.s1.internal_state_variables[1, i + 3] - v2_esv0_values[i + 3]) < eps, "invalid internal state variable value") self.assertTrue(abs(d.s1.internal_state_variables[0, i + 6] - v2_esv1_values[i]) < eps, "invalid internal state variable value") self.assertTrue(abs(d.s1.internal_state_variables[1, i + 6] - v2_esv1_values[i + 3]) < eps, "invalid internal state variable value")
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)