登录

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

加入讨论

登录或注册以发表评论