详解ValueError: Cannot specify ‘,‘ with ‘s‘.

报错的原因:

input函数读取输入的数据类型是字符串,不能直接用于数值格式化。

'{0:=>25,}'中的','是用于千位分隔符的格式规范,但字符串中没有数字,所以无法识别千位分隔符。

所以,解决此问题我们只要把字符串类型转化为整数类型即可:

1.把input定义为整数类型

2.在format中把s定义为整数类型

Warning (from warnings module): File "C:\Users\ASUS\AppData\Local\Programs\Python\Python313\Lib\site-packages\xarray\conventions.py", line 204 var = coder.decode(var, name=name) SerializationWarning: variable 'cSoil' has multiple fill values {np.float32(1e+20), np.float64(1e+20)} defined, decoding all values to NaN. Warning (from warnings module): File "C:\Users\ASUS\AppData\Local\Programs\Python\Python313\Lib\site-packages\xarray\conventions.py", line 204 var = coder.decode(var, name=name) SerializationWarning: variable 'cSoil' has multiple fill values {np.float32(1e+20), np.float64(1e+20)} defined, decoding all values to NaN. Traceback (most recent call last): File "C:\Users\ASUS\AppData\Local\Programs\Python\Python313\DC-run\试运行包.py", line 21, in <module> ds = xr.open_mfdataset( File "C:\Users\ASUS\AppData\Local\Programs\Python\Python313\Lib\site-packages\xarray\backends\api.py", line 1719, in open_mfdataset combined = combine_by_coords( File "C:\Users\ASUS\AppData\Local\Programs\Python\Python313\Lib\site-packages\xarray\structure\combine.py", line 983, in combine_by_coords concatenated_grouped_by_data_vars = tuple( File "C:\Users\ASUS\AppData\Local\Programs\Python\Python313\Lib\site-packages\xarray\structure\combine.py", line 984, in <genexpr> _combine_single_variable_hypercube( File "C:\Users\ASUS\AppData\Local\Programs\Python\Python313\Lib\site-packages\xarray\structure\combine.py", line 656, in _combine_single_variable_hypercube concatenated = _combine_nd( File "C:\Users\ASUS\AppData\Local\Programs\Python\Python313\Lib\site-packages\xarray\structure\combine.py", line 246, in _combine_nd combined_ids = _combine_all_along_first_dim( File "C:\Users\ASUS\AppData\Local\Programs\Python\Python313\Lib\site-packages\xarray\structure\combine.py", line 278, in _combine_all_along_first_dim new_combined_ids[new_id] = _combine_1d( File "C:\Users\ASUS\AppData\Local\Programs\Python\Python313\Lib\site-packages\xarray\structure\combine.py", line 301, in _combine_1d combined = concat( File "C:\Users\ASUS\AppData\Local\Programs\Python\Python313\Lib\site-packages\xarray\structure\concat.py", line 277, in concat return _dataset_concat( File "C:\Users\ASUS\AppData\Local\Programs\Python\Python313\Lib\site-packages\xarray\structure\concat.py", line 552, in _dataset_concat concat_over, equals, concat_dim_lengths, skip_merge = _calc_concat_over( File "C:\Users\ASUS\AppData\Local\Programs\Python\Python313\Lib\site-packages\xarray\structure\concat.py", line 447, in _calc_concat_over process_subset_opt(coords, "coords") File "C:\Users\ASUS\AppData\Local\Programs\Python\Python313\Lib\site-packages\xarray\structure\concat.py", line 357, in process_subset_opt raise ValueError( ValueError: Cannot specify both coords='different' and compat='override'.
08-26
# -*- coding: utf-8 -*- from abaqus import * from abaqusConstants import * from caeModules import * from odbAccess import openOdb import regionToolset import os import sys import math import time import uuid import traceback class GeostaticAnalysis: """主类,处理地应力分析的所有功能""" def __init__(self): self.model = None self.analysis_completed = False self.start_time = time.time() self.displacement_history = [] # 存储位移历史记录 self.convergence_data = [] # 存储收敛性数据 def print_msg(self, text, *args): """打印带时间戳的格式化消息""" if args: text = text % args # 确保使用正确的编码输出中文 if isinstance(text, unicode): text = text.encode('utf-8') elif isinstance(text, str): try: text = text.decode('utf-8').encode('gbk') except: pass print("%s" % (text)) def is_cancelled(self, inputs): """检查用户是否取消了操作""" if inputs is None: return True if any(value is None for value in inputs): return True return False def validate_model_exists(self, model_name): """检查模型是否存在于数据库中""" if model_name not in mdb.models: raise ValueError("Model '%s' does not exist" % model_name) return True def suppress_all_predefined_fields(self, model): """抑制模型中的所有预定义场""" try: suppressed_count = 0 if hasattr(model, 'predefinedFields') and model.predefinedFields: for field_name in list(model.predefinedFields.keys()): try: model.predefinedFields[field_name].suppress() suppressed_count += 1 self.print_msg("Suppressed predefined field: %s", field_name) except Exception as e: self.print_msg("Error suppressing field %s: %s", field_name, str(e)) self.print_msg("Suppressed %d predefined fields", suppressed_count) else: self.print_msg("No predefined fields found in the model") return suppressed_count except Exception as e: self.print_msg("Error accessing predefined fields: %s", str(e)) return 0 def get_max_displacement(self, odb_path): """从ODB文件中计算最大位移""" try: odb = openOdb(odb_path) step_names = list(odb.steps.keys()) if not step_names: self.print_msg("Warning: No steps found in ODB") odb.close() return 0.0 last_step_name = step_names[-1] last_step = odb.steps[last_step_name] if not last_step.frames: self.print_msg("Warning: No frames found in step %s", last_step_name) odb.close() return 0.0 last_frame = last_step.frames[-1] if 'U' not in last_frame.fieldOutputs: self.print_msg("Warning: No displacement field found in last frame") odb.close() return 0.0 displacement_field = last_frame.fieldOutputs['U'] max_disp = 0.0 for value in displacement_field.values: disp_magnitude = math.sqrt(value.data[0]**2 + value.data[1]**2 + value.data[2]**2) if disp_magnitude > max_disp: max_disp = disp_magnitude odb.close() self.print_msg("Max displacement in %s: %.6f", odb_path, max_disp) return max_disp except Exception as e: self.print_msg("Error calculating max displacement: %s", str(e)) return 0.0 def create_job(self, model_name, job_name, description, num_cpus, memory_percent, num_gpus): """创建分析作业""" return mdb.Job( name=job_name, model=model_name, description=description, type=ANALYSIS, atTime=None, waitMinutes=0, waitHours=0, queue=None, memory=memory_percent, memoryUnits=PERCENTAGE, getMemoryFromAnalysis=True, explicitPrecision=SINGLE, nodalOutputPrecision=SINGLE, echoPrint=OFF, modelPrint=OFF, contactPrint=OFF, historyPrint=OFF, userSubroutine='', scratch='', resultsFormat=ODB, numThreadsPerMpiProcess=1, multiprocessingMode=DEFAULT, numCpus=num_cpus, numDomains=num_cpus, numGPUs=num_gpus ) def create_elastic_trial_model(self, original_model_name, uniform_elastic_modulus=None): """ 创建弹性试验模型副本并将所有材料转换为纯线性弹性 参数: original_model_name: 原始模型名称 uniform_elastic_modulus: 统一弹性模量值(kPa),如果为None则使用原始材料值 """ try: # 生成弹性试验模型名称 elastic_model_name = "%s_ElasticTrial" % original_model_name # 检查原始模型是否存在 self.validate_model_exists(original_model_name) # 删除同名的现有模型 if elastic_model_name in mdb.models: del mdb.models[elastic_model_name] self.print_msg("Deleted existing model: %s", elastic_model_name) time.sleep(1) # 等待模型完全删除 # 复制模型 original_model = mdb.models[original_model_name] elastic_model = mdb.Model(name=elastic_model_name, objectToCopy=original_model) self.print_msg("Successfully created elastic trial model: %s", elastic_model_name) # 修改材料属性:将所有材料转换为纯线性弹性 for mat_name, material in elastic_model.materials.items(): self.print_msg("Processing material: %s", mat_name) # 保存原始弹性参数(如果可用) original_elastic_params = None original_poisson_ratio = 0.3 # 默认泊松比 if hasattr(material, 'elastic') and material.elastic: try: original_elastic_params = material.elastic.table if original_elastic_params and len(original_elastic_params) > 0: # 提取原始泊松比 original_poisson_ratio = original_elastic_params[0][1] if len(original_elastic_params[0]) > 1 else 0.3 self.print_msg("Saved original elastic properties for material: %s", mat_name) except Exception as e: self.print_msg("Error reading elastic properties for material %s: %s", mat_name, str(e)) # 删除所有已知的塑性属性 plasticity_properties = [ 'mohrCoulomb', 'mohrCoulombPlasticity', # Mohr-Coulomb塑性 'plastic', 'plasticity', # 通用塑性 'druckerPrager', # Drucker-Prager塑性 'clayPlasticity', # 粘土塑性 'capPlasticity', # 帽盖塑性 'creep', # 蠕变 'viscoelastic', 'viscous', # 粘弹性/粘性 'concrete', # 混凝土 'crushableFoam', # 可压碎泡沫 'ductileDamage', # 韧性损伤 'gasketPlasticity', # 垫片塑性 'hashinDamage', # Hashin损伤 'johnsonCook', # Johnson-Cook模型 'porousFailure', 'porousMetal', # 多孔材料失效 'tensileFailure', # 拉伸失效 'failureRatios', # 失效比率 'castIronPlasticity' # 铸铁塑性 ] # 使用del命令删除属性 for prop_name in plasticity_properties: try: if hasattr(material, prop_name): # 直接删除属性 delattr(material, prop_name) self.print_msg("Successfully deleted %s property from material: %s", prop_name, mat_name) except Exception as prop_e: self.print_msg("Error deleting %s property from material %s: %s", prop_name, mat_name, str(prop_e)) # 确保正确的弹性属性 try: # 删除现有的弹性属性(如果有) if hasattr(material, 'elastic'): try: delattr(material, 'elastic') self.print_msg("Removed existing elastic property from material: %s", mat_name) except Exception as e: self.print_msg("Error removing elastic property from material %s: %s", mat_name, str(e)) # 重新创建弹性属性 if uniform_elastic_modulus is not None: # 使用统一弹性模量 new_elastic_params = ((uniform_elastic_modulus, original_poisson_ratio),) material.Elastic(table=new_elastic_params) self.print_msg("Set uniform elastic modulus %.2f kPa for material: %s", uniform_elastic_modulus, mat_name) elif original_elastic_params: # 使用原始弹性参数 material.Elastic(table=original_elastic_params) self.print_msg("Restored original elastic properties for material: %s", mat_name) else: # 添加默认弹性属性 default_elastic_params = ((100.0, 0.3),) # E=100000kPa, ν=0.3 material.Elastic(table=default_elastic_params) self.print_msg("Added default elastic properties to material: %s (E=100000kPa, ν=0.3)", mat_name) except Exception as elastic_e: self.print_msg("Error setting elastic properties for material %s: %s", mat_name, str(elastic_e)) # 即使发生错误也继续处理其他材料 # 特殊处理:确保没有塑性属性残留 material_attrs = [attr for attr in dir(material) if not attr.startswith('_')] plastic_attrs_remaining = [attr for attr in material_attrs if any(plastic_term in attr.lower() for plastic_term in ['plastic', 'coulomb', 'prager', 'creep', 'visc'])] if plastic_attrs_remaining: self.print_msg("Warning: Material %s still has possible plastic attributes: %s", mat_name, plastic_attrs_remaining) # 尝试删除这些残留属性 for attr_name in plastic_attrs_remaining: try: if hasattr(material, attr_name): delattr(material, attr_name) self.print_msg("Deleted residual plastic attribute %s from material: %s", attr_name, mat_name) except Exception as e: self.print_msg("Error deleting residual attribute %s from material %s: %s", attr_name, mat_name, str(e)) self.print_msg("Completed converting all materials to linear elastic in model: %s", elastic_model_name) # 验证所有材料现在都是纯弹性的 self.print_msg("Verifying all materials are now purely elastic:") for mat_name, material in elastic_model.materials.items(): material_attrs = [attr for attr in dir(material) if not attr.startswith('_')] elastic_attrs = [attr for attr in material_attrs if 'elastic' in attr.lower()] plastic_attrs = [attr for attr in material_attrs if any(plastic_term in attr.lower() for plastic_term in ['plastic', 'coulomb', 'prager', 'creep', 'visc'])] self.print_msg("Material %s - Elastic attributes: %s", mat_name, elastic_attrs) if plastic_attrs: self.print_msg("Warning: Material %s still has plastic-like attributes: %s", mat_name, plastic_attrs) else: self.print_msg("Material %s is now purely elastic", mat_name) return elastic_model_name except Exception as e: self.print_msg("Error creating elastic trial model: %s", str(e)) return None def run_elastic_trial(self, model_name, base_odb_path, set_name, num_cpus, memory_percent, num_gpus, uniform_elastic_modulus=None): """ 运行弹性试验以获取初始应力场 参数: uniform_elastic_modulus: 统一弹性模量值(kPa),如果为None则使用原始材料值 """ self.print_msg("Starting elastic trial for initial stress field...") # 创建弹性试验模型 elastic_model_name = self.create_elastic_trial_model(model_name, uniform_elastic_modulus) if elastic_model_name is None: self.print_msg("Error: Failed to create elastic trial model") return None # 创建并运行弹性试验作业 elastic_job_name = 'Elastic_Trial' try: elastic_job = self.create_job( elastic_model_name, elastic_job_name, 'Elastic trial for initial stress', num_cpus, memory_percent, num_gpus ) # 提交作业 elastic_job.submit(consistencyChecking=OFF) elastic_job.waitForCompletion() # 检查作业状态 if elastic_job.status != COMPLETED: self.print_msg("Elastic trial job failed with status: %s", elastic_job.status) return None self.print_msg("Elastic trial completed successfully") # 获取ODB路径 elastic_odb_path = os.path.join(base_odb_path, elastic_job_name + '.odb') # 记录弹性试验的位移结果 max_disp = self.get_max_displacement(elastic_odb_path) self.displacement_history.append({ 'job_name': elastic_job_name, 'iteration': -1, # 弹性试验标记为-1 'max_displacement': max_disp, 'type': 'elastic_trial' }) return elastic_odb_path except Exception as e: self.print_msg("Error running elastic trial: %s", str(e)) return None def analyze_convergence_quality(self): """分析收敛质量和地应力场平衡质量""" if len(self.displacement_history) < 2: return "Insufficient data for evaluation" # 提取迭代数据(排除弹性试验) iter_data = [d for d in self.displacement_history if d['type'] == 'iteration'] if len(iter_data) < 2: return "Insufficient iteration data for evaluation" # 计算收敛指标 displacements = [d['max_displacement'] for d in iter_data] final_disp = displacements[-1] # 收敛率计算 convergence_rates = [] for i in range(1, len(displacements)): if displacements[i-1] > 0: rate = abs(displacements[i] - displacements[i-1]) / displacements[i-1] convergence_rates.append(rate) avg_convergence_rate = sum(convergence_rates) / len(convergence_rates) if convergence_rates else 1.0 # 质量评估标准 quality_assessment = [] # 1. 最终位移绝对值评估 if final_disp <= 1e-6: quality_assessment.append("Excellent displacement magnitude (< 1e-6)") elif final_disp <= 1e-4: quality_assessment.append("Good displacement magnitude (< 1e-4)") elif final_disp <= 1e-3: quality_assessment.append("Acceptable displacement magnitude (< 1e-3)") elif final_disp <= 1e-2: quality_assessment.append("Large displacement magnitude (< 1e-2)") else: quality_assessment.append("Excessive displacement magnitude (> 1e-2)") # 2. 收敛性评估 if len(convergence_rates) > 0: if avg_convergence_rate <= 0.1: quality_assessment.append("Excellent convergence (average rate < 10%)") elif avg_convergence_rate <= 0.3: quality_assessment.append("Good convergence (average rate < 30%)") elif avg_convergence_rate <= 0.5: quality_assessment.append("Fair convergence (average rate < 50%)") else: quality_assessment.append("Poor convergence (average rate > 50%)") # 3. 收敛稳定性评估 if len(convergence_rates) > 2: # 修复生成器问题:使用列表推导式而不是生成器表达式 stable_rates = [rate for rate in convergence_rates if rate <= 0.5] stable_count = len(stable_rates) stability_ratio = stable_count / len(convergence_rates) if stability_ratio >= 0.8: quality_assessment.append("Stable convergence process") elif stability_ratio >= 0.6: quality_assessment.append("Moderately stable convergence") else: quality_assessment.append("Unstable convergence process") # 4. 总体评价 # 修复生成器问题:使用列表推导式而不是生成器表达式 excellent_items = [item for item in quality_assessment if "Excellent" in item] excellent_count = len(excellent_items) warning_items = [item for item in quality_assessment if any(warning_term in item for warning_term in ["Large", "Excessive", "Poor", "Unstable"])] warning_count = len(warning_items) if warning_count > 0: overall = "Geostatic field balance quality: POOR" elif excellent_count >= 2: overall = "Geostatic field balance quality: EXCELLENT" else: overall = "Geostatic field balance quality: GOOD" return overall + "\n" + "\n".join(quality_assessment) def print_displacement_summary(self): """打印位移历史总结报告""" if not self.displacement_history: self.print_msg("No displacement history data") return self.print_msg("\n" + "="*80) self.print_msg("Geostatic Analysis Displacement History Summary") self.print_msg("="*80) # 打印表格头 self.print_msg("\n%-20s %-12s %-15s %-20s", "Job Name", "Iteration", "Max Displacement", "Type") self.print_msg("-" * 70) # 打印每个作业的数据 for record in self.displacement_history: job_name = record['job_name'] iteration = record['iteration'] max_disp = record['max_displacement'] record_type = record['type'] if iteration == -1: iter_str = "Elastic Trial" else: iter_str = str(iteration) self.print_msg("%-20s %-12s %-15.6f %-20s", job_name, iter_str, max_disp, record_type) # 只分析迭代数据(排除弹性试验) iter_data = [d for d in self.displacement_history if d['type'] == 'iteration'] if len(iter_data) > 1: self.print_msg("\nConvergence Analysis:") self.print_msg("-" * 40) displacements = [d['max_displacement'] for d in iter_data] for i in range(1, len(displacements)): prev_disp = displacements[i-1] curr_disp = displacements[i] if prev_disp > 0: reduction = (prev_disp - curr_disp) / prev_disp * 100 convergence_rate = abs(curr_disp - prev_disp) / prev_disp * 100 self.print_msg("Iteration %d -> %d: Displacement from %.6f to %.6f (reduction %.2f%%, convergence rate %.2f%%)", i-1, i, prev_disp, curr_disp, reduction, convergence_rate) # 总体收敛统计 total_reduction = (displacements[0] - displacements[-1]) / displacements[0] * 100 self.print_msg("\nOverall convergence: From %.6f to %.6f (total reduction %.2f%%)", displacements[0], displacements[-1], total_reduction) # 质量评估 self.print_msg("\nGeostatic Field Balance Quality Assessment:") self.print_msg("-" * 40) quality_report = self.analyze_convergence_quality() self.print_msg(quality_report) self.print_msg("="*80) def run_analysis(self, control_mode, control_value, base_odb_path, set_name, model_name, num_cpus, memory_percent, num_gpus, use_elastic_trial=True, uniform_elastic_modulus=None): """ 运行迭代地应力分析 参数: uniform_elastic_modulus: 统一弹性模量值(kPa),如果为None则使用原始材料值 """ # 清空历史记录 self.displacement_history = [] self.convergence_data = [] try: self.validate_model_exists(model_name) except Exception as e: self.print_msg("Error validating model: %s", str(e)) return False model = mdb.models[model_name] self.print_msg("Checking for existing predefined fields...") self.suppress_all_predefined_fields(model) self.print_msg("-" * 40) # 根据用户选择决定是否执行弹性试验 elastic_odb_path = None if use_elastic_trial: elastic_odb_path = self.run_elastic_trial(model_name, base_odb_path, set_name, num_cpus, memory_percent, num_gpus, uniform_elastic_modulus) if elastic_odb_path is None: if use_elastic_trial: self.print_msg("Elastic trial failed, proceeding without initial stress field") else: self.print_msg("Skipping elastic trial as requested by user") use_elastic_trial = False else: use_elastic_trial = True self.print_msg("Elastic trial completed, ODB path: %s", elastic_odb_path) self.print_msg("-" * 40) try: a = model.rootAssembly if set_name in a.sets: region = a.sets[set_name] self.print_msg("Using predefined set: %s", set_name) else: region = regionToolset.Region(elements=a.elements) self.print_msg("Set '%s' not found, using all elements: %d", set_name, len(a.elements)) odb = openOdb(elastic_odb_path) step_names = list(odb.steps.keys()) if not step_names: self.print_msg("Warning: No steps found in elastic trial ODB") odb.close() use_elastic_trial = False else: last_step_name = step_names[-1] step_obj = odb.steps[last_step_name] total_increments = len(step_obj.frames) - 1 if hasattr(step_obj, 'frames') else 1 total_increments = max(1, total_increments) odb.close() model.Stress( name='Initial_Stress_Field_From_Elastic', distributionType=FROM_FILE, fileName=elastic_odb_path, step=len(step_names), increment=total_increments, region=region ) self.print_msg("Created initial stress field from elastic trial") except Exception as e: self.print_msg("Error creating initial stress field from elastic trial: %s", str(e)) use_elastic_trial = False self.print_msg("Creating initial job...") initial_job_name = 'Geostatic_Initial' try: initial_job = self.create_job( model_name, initial_job_name, 'Initial geostatic step', num_cpus, memory_percent, num_gpus ) except Exception as e: self.print_msg("Error creating initial job: %s", str(e)) return False self.print_msg("Submitting initial job...") try: initial_job.submit(consistencyChecking=OFF) initial_job.waitForCompletion() except Exception as e: self.print_msg("Error submitting or waiting for initial job: %s", str(e)) return False if initial_job.status != COMPLETED: self.print_msg("Error: Initial job failed with status: %s", initial_job.status) return False self.print_msg("Initial job completed successfully") # 记录初始作业的位移 initial_odb_path = os.path.join(base_odb_path, initial_job_name + '.odb') max_disp = self.get_max_displacement(initial_odb_path) self.displacement_history.append({ 'job_name': initial_job_name, 'iteration': 0, 'max_displacement': max_disp, 'type': 'iteration' }) if use_elastic_trial: try: if 'Initial_Stress_Field_From_Elastic' in model.predefinedFields: model.predefinedFields['Initial_Stress_Field_From_Elastic'].suppress() self.print_msg("Suppressed elastic trial stress field") except Exception as e: self.print_msg("Error suppressing elastic trial stress field: %s", str(e)) if control_mode == 'displacement': if max_disp <= control_value: self.print_msg("Initial job already meets displacement requirement (%.6f <= %.6f)", max_disp, control_value) # 打印总结报告 self.print_displacement_summary() return True iteration_count = 0 max_iterations = control_value if control_mode == 'iterations' else 99 while (control_mode == 'iterations' and iteration_count < max_iterations) or \ (control_mode == 'displacement' and iteration_count < 99 and max_disp > control_value): try: iteration_count += 1 self.print_msg("=" * 50) if control_mode == 'iterations': self.print_msg("Processing iteration %d/%d", iteration_count, max_iterations) else: self.print_msg("Processing iteration %d/99", iteration_count) self.print_msg("Current max displacement: %.6f, Target: %.6f", max_disp, control_value) prev_job_name = 'Geostatic_Iter_%d' % (iteration_count - 1) if iteration_count > 1 else initial_job_name current_job_name = 'Geostatic_Iter_%d' % iteration_count predefined_field_prev = 'Stress_Field_Iter_%d' % (iteration_count - 1) if iteration_count > 1 else 'Initial_Stress_Field' predefined_field_current = 'Stress_Field_Iter_%d' % iteration_count self.print_msg("Current job: %s", current_job_name) self.print_msg("Reference job: %s", prev_job_name) odb_path = os.path.join(base_odb_path, prev_job_name + '.odb') if not os.path.exists(odb_path): self.print_msg("Error: ODB file %s does not exist", odb_path) break odb = openOdb(odb_path) step_names = list(odb.steps.keys()) if hasattr(odb, 'steps') and odb.steps else [] if not step_names: self.print_msg("Warning: No steps found in ODB, using defaults") step_number = 1 total_increments = 1 else: last_step_name = step_names[-1] step_number = len(step_names) step_obj = odb.steps[last_step_name] total_increments = len(step_obj.frames) - 1 if hasattr(step_obj, 'frames') else 1 total_increments = max(1, total_increments) self.print_msg("Using step: %s (number: %d)", last_step_name, step_number) self.print_msg("Increment count: %d", total_increments) odb.close() try: a = model.rootAssembly if set_name in a.sets: region = a.sets[set_name] self.print_msg("Using predefined set: %s", set_name) else: region = regionToolset.Region(elements=a.elements) self.print_msg("Set '%s' not found, using all elements: %d", set_name, len(a.elements)) except Exception as e: self.print_msg("Error creating region: %s", str(e)) break try: self.print_msg("Creating stress field:") self.print_msg(" Name: %s", predefined_field_current) self.print_msg(" File: %s", odb_path) self.print_msg(" Step: %d", step_number) self.print_msg(" Increment: %d", total_increments) model.Stress( name=predefined_field_current, distributionType=FROM_FILE, fileName=odb_path, step=step_number, increment=total_increments, region=region ) self.print_msg("Successfully created predefined field: %s", predefined_field_current) except Exception as e: self.print_msg("Error creating stress field: %s", str(e)) break try: current_job = self.create_job( model_name, current_job_name, 'Geostatic iteration %d' % iteration_count, num_cpus, memory_percent, num_gpus ) except Exception as e: self.print_msg("Error creating job: %s", str(e)) break try: current_job.submit(consistencyChecking=OFF) self.print_msg("Job %s submitted", current_job_name) current_job.waitForCompletion() if current_job.status != COMPLETED: self.print_msg("Warning: Job %s completed with status: %s", current_job_name, current_job.status) break else: self.print_msg("Job %s completed successfully", current_job_name) except Exception as e: self.print_msg("Job submission or execution failed: %s", str(e)) break # 记录当前迭代的位移 current_odb_path = os.path.join(base_odb_path, current_job_name + '.odb') max_disp = self.get_max_displacement(current_odb_path) self.displacement_history.append({ 'job_name': current_job_name, 'iteration': iteration_count, 'max_displacement': max_disp, 'type': 'iteration' }) if control_mode == 'displacement': current_odb_path = os.path.join(base_odb_path, current_job_name + '.odb') max_disp = self.get_max_displacement(current_odb_path) try: if predefined_field_prev in model.predefinedFields: model.predefinedFields[predefined_field_prev].suppress() self.print_msg("Suppressed predefined field: %s", predefined_field_prev) except Exception as e: self.print_msg("Error suppressing field: %s", str(e)) if control_mode == 'iterations': self.print_msg("Iteration %d completed", iteration_count) else: self.print_msg("Iteration %d completed, max displacement: %.6f", iteration_count, max_disp) self.print_msg("=" * 50) except Exception as e: self.print_msg("Unexpected error in iteration %d: %s", iteration_count, str(e)) break if control_mode == 'iterations': self.print_msg("Completed %d iterations as requested", iteration_count) success = True else: if max_disp <= control_value: self.print_msg("Displacement requirement met after %d iterations! (%.6f <= %.6f)", iteration_count, max_disp, control_value) success = True elif iteration_count >= 99: self.print_msg("Reached maximum iteration limit (99) without meeting displacement requirement") self.print_msg("Final displacement: %.6f, Target: %.6f", max_disp, control_value) success = True else: self.print_msg("Iteration stopped due to error") success = False # 打印位移总结报告 try: self.print_displacement_summary() except Exception as e: self.print_msg("Error printing displacement summary: %s", str(e)) self.analysis_completed = success # 如果分析成功,显示保存对话框 if success: try: self.show_completion_dialog() except Exception as e: self.print_msg("Error showing completion dialog: %s", str(e)) # 即使对话框出错,分析本身是成功的 return True return success def show_completion_dialog(self): """显示完成对话框""" try: # 确保在GUI环境中才显示对话框 if not hasattr(__main__, 'gui') and 'ABQcae' not in sys.executable: self.print_msg("Analysis completed successfully. Please save the model manually.") return True response = getInputs( fields=(('Type "SAVE" to confirm saving:', 'SAVE'),), label='All jobs completed successfully!\n\nType "SAVE" and click OK to save the Model.\nClick Cancel or close dialog to exit without saving.', dialogTitle='Completion' ) if response is None: self.print_msg("Dialog cancelled or closed by user. Model not saved.") return False if len(response) > 0 and response[0] is not None: user_input = response[0].strip().upper() if hasattr(response[0], 'strip') else str(response[0]) if user_input == "SAVE": try: mdb.save() self.print_msg("Model saved successfully after user confirmation.") return True except Exception as e: self.print_msg("Error saving model: %s", str(e)) return False else: self.print_msg("User did not confirm saving. Model not saved.") return False else: self.print_msg("No confirmation received. Model not saved.") return False except Exception as e: self.print_msg("Error in completion dialog: %s", str(e)) self.print_msg("Model not saved due to dialog errors.") return False def show_warning_message(self, message, title="Warning"): """显示警告消息(兼容不同版本的Abaqus API)""" try: # 确保在GUI环境中才显示对话框 if not hasattr(__main__, 'gui') and 'ABQcae' not in sys.executable: self.print_msg("WARNING: %s", message) return # 尝试使用新版API getWarningReply(message=message, buttons=('OK',)) except TypeError: # 如果新版API不支持,使用旧版API try: getWarningReply(message=message) except: # 如果所有API都失败,直接打印消息 self.print_msg("WARNING: %s", message) def show_error_message(self, message, title="Error"): """显示错误消息(兼容不同版本的Abaqus API)""" try: # 确保在GUI环境中才显示对话框 if not hasattr(__main__, 'gui') and 'ABQcae' not in sys.executable: self.print_msg("ERROR: %s", message) return # 尝试使用新版API getWarningReply(message=message, buttons=('OK',)) except TypeError: # 如果新版API不支持,使用旧版API try: getWarningReply(message=message) except: # 如果所有API都失败,直接打印消息 self.print_msg("ERROR: %s", message) def run_gui_interface(self): """运行GUI界面""" self.print_msg("=" * 60) self.print_msg("Auto Geostatic Analysis Program (GUI Mode)") self.print_msg("=" * 60) try: # 获取当前CAE文件路径作为默认ODB路径 default_odb_path = "" try: # 尝试获取当前CAE文件的目录 if hasattr(mdb, 'path') and mdb.path: # mdb.path 返回CAE文件所在目录 default_odb_path = mdb.path self.print_msg("Current CAE directory: %s", default_odb_path) else: # 如果CAE文件未保存,使用当前工作目录 default_odb_path = os.getcwd() self.print_msg("Using current working directory: %s", default_odb_path) except Exception as path_error: self.print_msg("Warning: Could not determine default path: %s", str(path_error)) default_odb_path = os.getcwd() # 降级到当前工作目录 control_inputs = getInputs( fields=( ('Control mode (iterations/displacement):', 'iterations'), ), label='Select control mode:\n- "iterations": Fixed number of iterations\n- "displacement": Stop when displacement is below threshold', dialogTitle='Geostatic Analysis Control Mode' ) if self.is_cancelled(control_inputs): self.print_msg("Operation cancelled by user") return control_mode = control_inputs[0].strip().lower() if control_inputs[0] is not None else 'iterations' if control_mode not in ['iterations', 'displacement']: self.show_warning_message('Control mode must be "iterations" or "displacement"') return # 根据控制模式创建参数输入对话框,添加弹性试验选项 if control_mode == 'iterations': inputs = getInputs( fields=( ('Number of iterations:', '5'), ('ODB file path (without filename):', default_odb_path), # 自动填充默认路径 ('Geostatic set name:', 'Geostatic-Set'), ('Model name:', 'Model-1'), ('Number of CPUs:', '24'), ('Memory usage (%):', '90'), ('Number of GPUs:', '2'), ('Use elastic trial? (yes/no):', 'yes'), ('Uniform elastic modulus for trial (kPa, optional):', '') ), label='Enter parameters for iteration-controlled analysis:\n(ODB path is pre-filled with current CAE file directory. Modify if needed.)\n(If using elastic trial, you can optionally specify a uniform elastic modulus for all materials.)\n', dialogTitle='Geostatic Analysis Parameters (Iteration Control)' ) else: inputs = getInputs( fields=( ('Maximum allowed displacement:', '0.001'), ('ODB file path (without filename):', default_odb_path), # 自动填充默认路径 ('Geostatic set name:', 'Geostatic-Set'), ('Model name:', 'Model-1'), ('Number of CPUs:', '24'), ('Memory usage (%):', '90'), ('Number of GPUs:', '2'), ('Use elastic trial? (yes/no):', 'yes'), ('Uniform elastic modulus for trial (kPa, optional):', '') ), label='Enter parameters for displacement-controlled analysis:\n(ODB path is pre-filled with current CAE file directory. Modify if needed.)\n(If using elastic trial, you can optionally specify a uniform elastic modulus for all materials.)\n', dialogTitle='Geostatic Analysis Parameters (Displacement Control)' ) if self.is_cancelled(inputs): self.print_msg("Operation cancelled by user") return # 提取输入参数,包括弹性试验选项和统一模量选项 if control_mode == 'iterations': control_value_str, odb_path, set_name, model_name, num_cpus_str, memory_percent_str, num_gpus_str, use_elastic_trial_str, uniform_elastic_modulus_str = inputs try: control_value = int(control_value_str) if control_value <= 0: self.show_warning_message('Number of iterations must be greater than 0') return except (ValueError, TypeError): self.show_warning_message('Number of iterations must be a number') return else: control_value_str, odb_path, set_name, model_name, num_cpus_str, memory_percent_str, num_gpus_str, use_elastic_trial_str, uniform_elastic_modulus_str = inputs try: control_value = float(control_value_str) if control_value <= 0: self.show_warning_message('Maximum displacement must be greater than 0') return except (ValueError, TypeError): self.show_warning_message('Maximum displacement must be a number') return # 处理弹性试验选项 use_elastic_trial_str = use_elastic_trial_str.strip().lower() if use_elastic_trial_str is not None else 'yes' if use_elastic_trial_str in ['yes', 'y', 'true', '1']: use_elastic_trial = True elif use_elastic_trial_str in ['no', 'n', 'false', '0']: use_elastic_trial = False else: self.show_warning_message('Use elastic trial must be "yes" or "no"') return # 处理统一模量选项 uniform_elastic_modulus = None if use_elastic_trial and uniform_elastic_modulus_str and uniform_elastic_modulus_str.strip(): try: uniform_elastic_modulus = float(uniform_elastic_modulus_str.strip()) if uniform_elastic_modulus <= 0: self.show_warning_message('Uniform elastic modulus must be greater than 0') return except (ValueError, TypeError): self.show_warning_message('Uniform elastic modulus must be a number') return odb_path = odb_path.strip() if not odb_path: self.show_warning_message('ODB path cannot be empty') return set_name = set_name.strip() if not set_name: self.show_warning_message('Set name cannot be empty') return model_name = model_name.strip() if not model_name: self.show_warning_message('Model name cannot be empty') return try: num_cpus = int(num_cpus_str) if num_cpus <= 0: self.show_warning_message('Number of CPUs must be greater than 0') return except (ValueError, TypeError): self.show_warning_message('Number of CPUs must be a number') return try: memory_percent = int(memory_percent_str) if memory_percent <= 0 or memory_percent > 100: self.show_warning_message('Memory usage must be between 1 and 100 percent') return except (ValueError, TypeError): self.show_warning_message('Memory usage must be a number') return try: num_gpus = int(num_gpus_str) if num_gpus < 0: self.show_warning_message('Number of GPUs cannot be negative') return except (ValueError, TypeError): self.show_warning_message('Number of GPUs must be a number') return # 输出参数确认,包括弹性试验选项和统一模量选项 self.print_msg("\nParameter confirmation:") self.print_msg("Control mode: %s", control_mode) if control_mode == 'iterations': self.print_msg("Number of iterations: %d", control_value) else: self.print_msg("Maximum allowed displacement: %.6f", control_value) self.print_msg("ODB path: %s", odb_path) self.print_msg("Set name: %s", set_name) self.print_msg("Model name: %s", model_name) self.print_msg("Number of CPUs: %d", num_cpus) self.print_msg("Memory usage: %d%%", memory_percent) self.print_msg("Number of GPUs: %d", num_gpus) self.print_msg("Use elastic trial: %s", "Yes" if use_elastic_trial else "No") if use_elastic_trial and uniform_elastic_modulus is not None: self.print_msg("Uniform elastic modulus: %.2f kPa", uniform_elastic_modulus) elif use_elastic_trial: self.print_msg("Uniform elastic modulus: Using original material values") self.print_msg("-" * 40) # 使用所有验证过的参数调用核心分析函数 try: success = self.run_analysis(control_mode, control_value, odb_path, set_name, model_name, num_cpus, memory_percent, num_gpus, use_elastic_trial, uniform_elastic_modulus) # 捕获分析期间的异常(作业失败,ODB读取错误) except Exception as e: error_msg = "Analysis failed: %s" % str(e) self.print_msg(error_msg) # 显示错误对话框:通知用户失败原因 self.show_error_message(error_msg) # 捕获GUI界面创建/交互期间的全局异常 except Exception as e: error_msg = "GUI interface failed: %s" % str(e) self.print_msg(error_msg) # 对于取消的操作不显示错误对话框 if "cancelled" not in str(e).lower() and "cancel" not in str(e).lower(): self.show_error_message(error_msg) def run_cli_interface(self): """运行CLI界面""" self.print_msg("=" * 60) self.print_msg("Auto Geostatic Analysis Program (CLI Mode)") self.print_msg("=" * 60) self.print_msg("Command line arguments: %s" % str(sys.argv)) if '--' not in sys.argv: self.print_msg("Error: Missing '--' separator") self.print_msg("Usage: abaqus cae noGUI=script.py -- <control_mode> <control_value> <odb_path> <set_name> [model_name] [num_cpus] [memory_percent] [num_gpus] [use_elastic_trial] [uniform_elastic_modulus]") self.print_msg("Control mode: 'iterations' or 'displacement'") self.print_msg("Example (iteration control): abaqus cae noGUI=script.py -- iterations 5 /path/to/odb/files Geostatic-Set Model-1 4 80 1 yes 1000") self.print_msg("Example (displacement control): abaqus cae noGUI=script.py -- displacement 0.001 /path/to/odb/files Geostatic-Set Model-1 4 80 1 yes 1000") return try: separator_index = sys.argv.index("--") user_args = sys.argv[separator_index + 1:] if len(user_args) < 4: self.print_msg("Error: Not enough user parameters after '--'") self.print_msg("Expected: <control_mode> <control_value> <odb_path> <set_name> [model_name] [num_cpus] [memory_percent] [num_gpus] [use_elastic_trial] [uniform_elastic_modulus]") self.print_msg("Got: %s" % str(user_args)) return control_mode = user_args[0].lower() control_value_str = user_args[1] base_odb_path = user_args[2] set_name = user_args[3] model_name = user_args[4] if len(user_args) > 4 else 'Model-1' num_cpus = int(user_args[5]) if len(user_args) > 5 else 1 memory_percent = int(user_args[6]) if len(user_args) > 6 else 70 num_gpus = int(user_args[7]) if len(user_args) > 7 else 0 use_elastic_trial_str = user_args[8].lower() if len(user_args) > 8 else 'yes' uniform_elastic_modulus_str = user_args[9] if len(user_args) > 9 else '' # 处理弹性试验选项 if use_elastic_trial_str in ['yes', 'y', 'true', '1']: use_elastic_trial = True elif use_elastic_trial_str in ['no', 'n', 'false', '0']: use_elastic_trial = False else: self.print_msg("Error: Use elastic trial must be 'yes' or 'no'") return # 处理统一模量选项 uniform_elastic_modulus = None if use_elastic_trial and uniform_elastic_modulus_str and uniform_elastic_modulus_str.strip(): try: uniform_elastic_modulus = float(uniform_elastic_modulus_str.strip()) if uniform_elastic_modulus <= 0: self.print_msg("Error: Uniform elastic modulus must be greater than 0") return except (ValueError, TypeError): self.print_msg("Error: Uniform elastic modulus must be a number") return if control_mode not in ['iterations', 'displacement']: self.print_msg("Error: Control mode must be 'iterations' or 'displacement'") return if control_mode == 'iterations': try: control_value = int(control_value_str) if control_value <= 0: self.print_msg("Error: Number of iterations must be greater than 0") return except (ValueError, TypeError): self.print_msg("Error: Number of iterations must be an integer") return else: try: control_value = float(control_value_str) if control_value <= 0: self.print_msg("Error: Maximum displacement must be greater than 0") return except (ValueError, TypeError): self.print_msg("Error: Maximum displacement must be a number") return if num_cpus <= 0: self.print_msg("Error: Number of CPUs must be greater than 0") return if memory_percent <= 0 or memory_percent > 100: self.print_msg("Error: Memory usage must be between 1 and 100 percent") return if num_gpus < 0: self.print_msg("Error: Number of GPUs cannot be negative") return if not os.path.exists(base_odb_path): self.print_msg("Error: ODB path does not exist: %s", base_odb_path) return # 输出参数确认,包括弹性试验选项和统一模量选项 self.print_msg("\nParameter confirmation:") self.print_msg("Control mode: %s", control_mode) if control_mode == 'iterations': self.print_msg("Number of iterations: %d", control_value) else: self.print_msg("Maximum allowed displacement: %.6f", control_value) self.print_msg("ODB path: %s", base_odb_path) self.print_msg("Set name: %s", set_name) self.print_msg("Model name: %s", model_name) self.print_msg("Number of CPUs: %d", num_cpus) self.print_msg("Memory usage: %d%%", memory_percent) self.print_msg("Number of GPUs: %d", num_gpus) self.print_msg("Use elastic trial: %s", "Yes" if use_elastic_trial else "No") if use_elastic_trial and uniform_elastic_modulus is not None: self.print_msg("Uniform elastic modulus: %.2f kPa", uniform_elastic_modulus) elif use_elastic_trial: self.print_msg("Uniform elastic modulus: Using original material values") self.print_msg("-" * 40) # 使用所有参数调用核心分析函数 success = self.run_analysis(control_mode, control_value, base_odb_path, set_name, model_name, num_cpus, memory_percent, num_gpus, use_elastic_trial, uniform_elastic_modulus) # 在CLI模式下分析成功后自动保存模型 if success: try: mdb.save() self.print_msg("All jobs completed successfully! Model saved automatically in CLI mode.") except Exception as e: self.print_msg("Error saving model: %s", str(e)) # 捕获参数类型错误(非数字参数,格式错误) except ValueError as e: self.print_msg("Parameter error: %s", str(e)) self.print_msg("Please ensure numeric parameters are valid numbers") # 捕获其他异常(分析失败,内存问题) except Exception as e: error_msg = "Analysis failed: %s" % str(e) self.print_msg(error_msg) def main(): """应用程序的主入口点""" try: analysis = GeostaticAnalysis() is_gui_environment = hasattr(__main__, 'gui') or 'ABQcae' in sys.executable if is_gui_environment: analysis.print_msg("Running in GUI environment") analysis.run_gui_interface() else: analysis.print_msg("Running in CLI environment") analysis.run_cli_interface() except Exception as e: error_msg = "Fatal error in main execution: %s" % str(e) print(error_msg) if 'analysis' in locals() and hasattr(analysis, 'print_msg'): analysis.print_msg(error_msg) if __name__ == '__main__': main()
09-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值