210 const FSIData &data = fsi_data(base_data);
211 const auto &vvals = data.vals(FSIData::Velocity);
212 const int dim = components(data, FSIData::Velocity);
213 Eigen::VectorXd residual = Eigen::VectorXd::Zero(local_total_size(data));
215 Eigen::MatrixXd body_force;
216 if (data.body_force_evaluator)
218 Eigen::MatrixXd points(data.da.size(), dim);
219 for (
int q = 0; q < data.da.size(); ++q)
220 points.row(q) = ale_point(data, q).point;
221 data.body_force_evaluator(vvals.element_id, points, data.t, body_force);
223 if (body_force.size() == 0)
224 body_force = Eigen::MatrixXd::Zero(data.da.size(), dim);
226 for (
int q = 0; q < data.da.size(); ++q)
228 const ALEPoint ale = ale_point(data, q);
229 const Eigen::VectorXd velocity = interpolate_vector(vvals, data.velocity(), dim, q);
230 const Eigen::VectorXd mesh_velocity = interpolate_vector(
231 data.vals(FSIData::MeshDisplacement), data.mesh_velocity, dim, q);
232 const Eigen::MatrixXd grad_velocity = velocity_gradient(data, q, ale.F_inv);
233 const double viscosity =
viscosity_(ale.point, data.t, vvals.element_id);
234 const double rho =
density_(vvals.quadrature.points.row(q), ale.point, data.t, vvals.element_id);
235 const double weight = data.spatial_weight * ale.J * data.da(q);
237 for (
int i = 0; i < int(vvals.basis_values.size()); ++i)
239 const double phi_i = vvals.basis_values[i].val(q);
240 const Eigen::RowVectorXd grad_i = spatial_gradient(data, FSIData::Velocity, i, q, ale.F_inv);
241 for (
int m = 0; m < dim; ++m)
243 const double viscous = viscosity * grad_velocity.row(m).dot(grad_i);
244 const double convection = rho * (velocity - mesh_velocity).dot(grad_velocity.row(m)) * phi_i;
245 const double force = -rho * body_force(q, m) * phi_i;
246 residual(i * dim + m) += weight * (viscous + convection + force);
256 const FSIData &data = fsi_data(base_data);
257 if (row_space != FSIData::Velocity)
258 return Eigen::MatrixXd::Zero(local_size(data, row_space), local_size(data, col_space));
259 if (col_space == FSIData::MeshDisplacement)
261 const auto &vvals = data.vals(FSIData::Velocity);
262 const auto &dvals = data.vals(FSIData::MeshDisplacement);
263 const int dim = components(data, FSIData::Velocity);
264 Eigen::MatrixXd jacobian = Eigen::MatrixXd::Zero(local_size(data, row_space), local_size(data, col_space));
265 std::vector<ALEPoint> ale(data.da.size());
266 for (
int q = 0; q < data.da.size(); ++q)
267 ale[q] = ale_point(data, q);
268 Eigen::MatrixXd body_force;
269 std::vector<Eigen::MatrixXd> body_force_gradient;
270 evaluate_body_force(data, ale, body_force, &body_force_gradient);
272 for (
int q = 0; q < data.da.size(); ++q)
274 const Eigen::VectorXd velocity = interpolate_vector(vvals, data.velocity(), dim, q);
275 const Eigen::VectorXd mesh_velocity = interpolate_vector(dvals, data.mesh_velocity, dim, q);
276 const Eigen::VectorXd relative_velocity = velocity - mesh_velocity;
277 const Eigen::MatrixXd grad_velocity = velocity_gradient(data, q, ale[q].
F_inv);
278 const double viscosity =
viscosity_(ale[q].
point, data.t, vvals.element_id);
279 const double rho =
density_(vvals.quadrature.points.row(q), ale[q].point, data.t, vvals.element_id);
280 Eigen::VectorXd viscosity_gradient(dim), density_gradient(dim);
281 for (
int n = 0; n < dim; ++n)
283 viscosity_gradient(n) = coordinate_derivative(
286 density_gradient(n) = coordinate_derivative(
288 [&](
const Eigen::RowVectorXd &
point) {
289 return density_(vvals.quadrature.points.row(q),
point, data.t, vvals.element_id);
292 const double weight = data.spatial_weight * ale[q].J * data.da(q);
294 for (
int i = 0; i < int(vvals.basis_values.size()); ++i)
296 const double phi_i = vvals.basis_values[i].val(q);
297 const Eigen::RowVectorXd grad_i = spatial_gradient(data, FSIData::Velocity, i, q, ale[q].
F_inv);
298 for (
int j = 0; j < int(dvals.basis_values.size()); ++j)
300 const double phi_j = dvals.basis_values[j].val(q);
301 const Eigen::RowVectorXd grad_j = spatial_gradient(data, FSIData::MeshDisplacement, j, q, ale[q].
F_inv);
302 for (
int n = 0; n < dim; ++n)
304 const double theta = grad_j(n);
305 const Eigen::VectorXd dmesh_velocity =
306 phi_j * data.dmesh_velocity_dmesh_displacement * Eigen::VectorXd::Unit(dim, n);
307 const double dviscosity = phi_j * viscosity_gradient(n);
308 const double drho = phi_j * density_gradient(n);
309 for (
int m = 0; m < dim; ++m)
311 const Eigen::RowVectorXd dgrad_velocity = -grad_velocity(m, n) * grad_j;
312 const Eigen::RowVectorXd dgrad_i = -grad_i(n) * grad_j;
313 const double viscous = viscosity * grad_velocity.row(m).dot(grad_i);
314 const double convection = rho * relative_velocity.dot(grad_velocity.row(m)) * phi_i;
315 const double force = -rho * body_force(q, m) * phi_i;
316 double derivative = theta * (viscous + convection + force);
317 derivative += dviscosity * grad_velocity.row(m).dot(grad_i)
318 + viscosity * (dgrad_velocity.dot(grad_i) + grad_velocity.row(m).dot(dgrad_i));
319 derivative += drho * relative_velocity.dot(grad_velocity.row(m)) * phi_i
320 + rho * (-dmesh_velocity.dot(grad_velocity.row(m)) + relative_velocity.dot(dgrad_velocity))
322 derivative -= (drho * body_force(q, m)
323 + rho * phi_j * body_force_gradient[n](q, m))
325 jacobian(i * dim + m, j * dim + n) += weight * derivative;
333 if (col_space != FSIData::Velocity)
334 return Eigen::MatrixXd::Zero(local_size(data, row_space), local_size(data, col_space));
336 const auto &vvals = data.vals(FSIData::Velocity);
337 const int dim = components(data, FSIData::Velocity);
338 Eigen::MatrixXd jacobian = Eigen::MatrixXd::Zero(local_size(data, row_space), local_size(data, col_space));
339 for (
int q = 0; q < data.da.size(); ++q)
341 const ALEPoint ale = ale_point(data, q);
342 const Eigen::VectorXd velocity = interpolate_vector(vvals, data.velocity(), dim, q);
343 const Eigen::VectorXd mesh_velocity = interpolate_vector(
344 data.vals(FSIData::MeshDisplacement), data.mesh_velocity, dim, q);
345 const Eigen::MatrixXd grad_velocity = velocity_gradient(data, q, ale.F_inv);
346 const double viscosity =
viscosity_(ale.point, data.t, vvals.element_id);
347 const double rho =
density_(vvals.quadrature.points.row(q), ale.point, data.t, vvals.element_id);
348 const double weight = data.spatial_weight * ale.J * data.da(q);
350 for (
int i = 0; i < int(vvals.basis_values.size()); ++i)
352 const double phi_i = vvals.basis_values[i].val(q);
353 const Eigen::RowVectorXd grad_i = spatial_gradient(data, FSIData::Velocity, i, q, ale.F_inv);
354 for (
int j = 0; j < int(vvals.basis_values.size()); ++j)
356 const double phi_j = vvals.basis_values[j].val(q);
357 const Eigen::RowVectorXd grad_j = spatial_gradient(data, FSIData::Velocity, j, q, ale.F_inv);
358 for (
int m = 0; m < dim; ++m)
359 for (
int n = 0; n < dim; ++n)
363 value += viscosity * grad_i.dot(grad_j)
364 + rho * (velocity - mesh_velocity).dot(grad_j) * phi_i;
366 value += rho * phi_j * grad_velocity(m, n) * phi_i;
367 jacobian(i * dim + m, j * dim + n) += weight * value;
389 const FSIData &data = fsi_data(base_data);
390 const auto &vvals = data.vals(FSIData::Velocity);
391 const auto &pvals = data.vals(FSIData::Pressure);
392 const int dim = components(data, FSIData::Velocity);
393 Eigen::VectorXd residual = Eigen::VectorXd::Zero(local_total_size(data));
394 const int pressure_offset = local_offset(data, FSIData::Pressure);
396 for (
int q = 0; q < data.da.size(); ++q)
398 const ALEPoint ale = ale_point(data, q);
399 const Eigen::MatrixXd grad_velocity = velocity_gradient(data, q, ale.F_inv);
400 const double pressure = interpolate_scalar(pvals, data.pressure(), q);
401 const double weight = data.spatial_weight * ale.J * data.da(q);
403 for (
int i = 0; i < int(vvals.basis_values.size()); ++i)
405 const Eigen::RowVectorXd grad_i = spatial_gradient(data, FSIData::Velocity, i, q, ale.F_inv);
406 for (
int m = 0; m < dim; ++m)
407 residual(i * dim + m) -= weight * pressure * grad_i(m);
409 for (
int i = 0; i < int(pvals.basis_values.size()); ++i)
410 residual(pressure_offset + i) -= weight * pvals.basis_values[i].val(q) * grad_velocity.trace();
418 const FSIData &data = fsi_data(base_data);
419 if (col_space == FSIData::MeshDisplacement
420 && (row_space == FSIData::Velocity || row_space == FSIData::Pressure))
422 const auto &vvals = data.vals(FSIData::Velocity);
423 const auto &pvals = data.vals(FSIData::Pressure);
424 const auto &dvals = data.vals(FSIData::MeshDisplacement);
425 const int dim = components(data, FSIData::Velocity);
426 Eigen::MatrixXd jacobian = Eigen::MatrixXd::Zero(local_size(data, row_space), local_size(data, col_space));
427 for (
int q = 0; q < data.da.size(); ++q)
429 const ALEPoint ale = ale_point(data, q);
430 const Eigen::MatrixXd grad_velocity = velocity_gradient(data, q, ale.F_inv);
431 const double pressure = interpolate_scalar(pvals, data.pressure(), q);
432 const double weight = data.spatial_weight * ale.J * data.da(q);
433 for (
int j = 0; j < int(dvals.basis_values.size()); ++j)
435 const Eigen::RowVectorXd grad_j = spatial_gradient(data, FSIData::MeshDisplacement, j, q, ale.F_inv);
436 for (
int n = 0; n < dim; ++n)
438 const double theta = grad_j(n);
439 if (row_space == FSIData::Velocity)
441 for (
int i = 0; i < int(vvals.basis_values.size()); ++i)
443 const Eigen::RowVectorXd grad_i = spatial_gradient(data, FSIData::Velocity, i, q, ale.F_inv);
444 const Eigen::RowVectorXd dgrad_i = -grad_i(n) * grad_j;
445 for (
int m = 0; m < dim; ++m)
446 jacobian(i * dim + m, j * dim + n) -= weight * pressure * (theta * grad_i(m) + dgrad_i(m));
451 double ddivergence = 0;
452 for (
int c = 0; c < dim; ++c)
453 ddivergence -= grad_velocity(c, n) * grad_j(c);
454 for (
int i = 0; i < int(pvals.basis_values.size()); ++i)
455 jacobian(i, j * dim + n) -= weight * pvals.basis_values[i].val(q)
456 * (theta * grad_velocity.trace() + ddivergence);
464 Eigen::MatrixXd jacobian = Eigen::MatrixXd::Zero(local_size(data, row_space), local_size(data, col_space));
465 if (!((row_space == FSIData::Velocity && col_space == FSIData::Pressure)
466 || (row_space == FSIData::Pressure && col_space == FSIData::Velocity)))
469 const auto &vvals = data.vals(FSIData::Velocity);
470 const auto &pvals = data.vals(FSIData::Pressure);
471 const int dim = components(data, FSIData::Velocity);
472 for (
int q = 0; q < data.da.size(); ++q)
474 const ALEPoint ale = ale_point(data, q);
475 const double weight = data.spatial_weight * ale.J * data.da(q);
476 for (
int i = 0; i < int(vvals.basis_values.size()); ++i)
478 const Eigen::RowVectorXd grad_i = spatial_gradient(data, FSIData::Velocity, i, q, ale.F_inv);
479 for (
int j = 0; j < int(pvals.basis_values.size()); ++j)
480 for (
int m = 0; m < dim; ++m)
482 const double value = -weight * pvals.basis_values[j].val(q) * grad_i(m);
483 if (row_space == FSIData::Velocity)
484 jacobian(i * dim + m, j) += value;
486 jacobian(j, i * dim + m) += value;
544 const FSIData &data = fsi_data(base_data);
545 Eigen::MatrixXd jacobian = Eigen::MatrixXd::Zero(local_size(data, row_space), local_size(data, col_space));
546 if (!data.include_inertia || row_space != FSIData::Velocity)
548 if (col_space == FSIData::MeshDisplacement)
550 const auto &vvals = data.vals(FSIData::Velocity);
551 const auto &dvals = data.vals(FSIData::MeshDisplacement);
552 const int dim = components(data, FSIData::Velocity);
553 for (
int q = 0; q < data.da.size(); ++q)
555 const ALEPoint ale = ale_point(data, q);
556 const Eigen::VectorXd velocity = interpolate_vector(vvals, data.velocity(), dim, q);
557 const Eigen::VectorXd velocity_tilde = interpolate_vector(vvals, data.velocity_tilde, dim, q);
558 const double rho =
density_(vvals.quadrature.points.row(q), ale.point, data.t, vvals.element_id);
559 Eigen::VectorXd density_gradient(dim);
560 for (
int n = 0; n < dim; ++n)
561 density_gradient(n) = coordinate_derivative(
563 [&](
const Eigen::RowVectorXd &
point) {
564 return density_(vvals.quadrature.points.row(q), point, data.t, vvals.element_id);
566 const double weight = ale.J * data.da(q);
567 for (
int i = 0; i < int(vvals.basis_values.size()); ++i)
568 for (
int j = 0; j < int(dvals.basis_values.size()); ++j)
570 const double phi_j = dvals.basis_values[j].val(q);
571 const Eigen::RowVectorXd grad_j = spatial_gradient(data, FSIData::MeshDisplacement, j, q, ale.F_inv);
572 for (
int m = 0; m < dim; ++m)
573 for (
int n = 0; n < dim; ++n)
574 jacobian(i * dim + m, j * dim + n) +=
575 weight * vvals.basis_values[i].val(q)
576 * (rho * grad_j(n) + phi_j * density_gradient(n))
577 * (velocity(m) - velocity_tilde(m));
582 if (col_space != FSIData::Velocity)
585 const auto &vvals = data.vals(FSIData::Velocity);
586 const int dim = components(data, FSIData::Velocity);
587 for (
int q = 0; q < data.da.size(); ++q)
589 const ALEPoint ale = ale_point(data, q);
590 const double rho =
density_(vvals.quadrature.points.row(q), ale.point, data.t, vvals.element_id);
591 const double weight = rho * ale.J * data.da(q);
592 for (
int i = 0; i < int(vvals.basis_values.size()); ++i)
593 for (
int j = 0; j < int(vvals.basis_values.size()); ++j)
594 for (
int m = 0; m < dim; ++m)
595 jacobian(i * dim + m, j * dim + m) += weight * vvals.basis_values[i].val(q) * vvals.basis_values[j].val(q);