IBAMR中应力函数的 *ctx使用
Coding
2025-07-09 11:17:34
ctx 的使用
vector<PK1StressFcnData> stress_fcn_data_vec = { … }; // 为每个部分设置应力函数
for (int part = 0; part < num_part; ++part)
{
ibfe_method->registerPK1StressFunction(stress_fcn_data_vec[part], part);
}
首先,使用上下文指针,通过将指向部件编号的指针传递给应力函数,告知其正在操作哪个部件:
void my_PK1_stress_fcn(
TensorValue<double>& F,
const TensorValue<double>& FF,
const Point& x,
const Point& X,
Elem* elem,
const Vector<const Vector<double>*>& system_var_data,
const Vector<const Vector<VectorValue<double>>*>& system_grad_var_data,
double data_time,
void* ctx)
{
// 将 ctx 解释为指向整数的指针:
int* part_num_ptr = static_cast<int*>(ctx);
// 取消引用指针以获取部件编号:
int part_num = *part_num_ptr;
/// 注意:上述代码可以在一行中完成:int part_num = *static_cast<int*>(ctx);
// 其余实现……
}
(上下文可以是更复杂的对象,提供更多规范信息。)
最后,在设置应力函数时,可以执行以下操作: 首先创建一个包含零件编号的向量。 因为如果调整向量的大小,vector::push_back 可以在内存中移动数据 所以我们需要在单独的循环中执行此操作,因为我们最终会将指向这些数据项的指针传递给 PK1 应力函数规范。如果调整向量大小,这些指针可能会失效。
for (int part = 0; part < num_part; ++part)
{
part_num_vec.push_back(part);
}
// 然后创建一个包含 PK1 应力函数规范的向量,并将其内容传递给
// IBFE 方法对象。
vector<PK1StressFcnData> stress_fcn_data_vec;
for (int part = 0; part < num_part; ++part)
{
// 注意,我们传入了一个指向整数的指针,该整数用于捕获零件编号
// 作为此处的 ctx:
stress_fcn_data_vec.push_back(PK1StressFcnData(my_PK1_stress_fcn, {}, &part_num_vec[part]));
ibfe_method->registerPK1StressFunction(stress_fcn_data_vec[part], part);
}
为每个part设置blockID
PS 不使用ctx的最简单方式
int num_parts = … ;
vector<shared_ptr<Mesh>> mesh_shared_ptr_vec(num_parts);
vector<Mesh> mesh_ptr_vec(num_parts);
for (int part = 0; part < num_parts; ++part)
{
mesh_shared_ptr_vec[part] = make_shared<Mesh>(init.comm(), NDIM));
mesh_shared_ptr_vec[part]->read(mesh_filename);
mesh_shared_ptr_vec[part]->prepare_for_use();
// the IBFE interface still takes in raw pointers, so we need to get it from the
// shared_ptr:
mesh_ptr_vec[part] = mesh_shared_ptr_vec[part].get();
}
for (int part = 0; part < num_parts; ++part)
{
Mesh* mesh = mesh_ptr_vec[part];
for (auto& elem : mesh->element_ptr_range())
{
elem->sudomain_id() = part;
}
}
(如果您知道“默认”子域 ID,可以使用 MeshTools::Modification::change_subdomain_id() 来更改 ID。但是,如果您不知道 ID,则似乎必须通过循环遍历元素来“手动”重置这些 ID。)
然后在应力和/或力函数中,您可以直接从元素中查找子域 ID:
void my_PK1_stress_fcn(
TensorValue<double>& F,
const TensorValue<double>& FF,
const Point& x,
const Point& X,
Elem* elem,
const Vector<const Vector<double>*>& system_var_data,
const Vector<const Vector<VectorValue<double>>*>& system_grad_var_data,
double data_time,
void* ctx)
{
int part_num = elem->subdomain_id();
// 其余实现…
}
详细可见 <https://groups.google.com/g/ibamr-users/c/ZrLq6NiB8NE/m/-GIrJHhRAgAJ