Program Listing for File generation.h

↰ Return to documentation for file (include/immersx/vascularization/generation.h)

// Copyright (C) 2026 by Luca Heltai
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#ifndef immersx_vascularization_generation_h
#define immersx_vascularization_generation_h

#include <deal.II/base/mpi.h>
#include <deal.II/base/parameter_acceptor.h>

#include <deal.II/fe/mapping.h>

#include <deal.II/grid/tria.h>

#include <immersx/vascularization/discretization.h>
#include <immersx/vascularization/growth_work.h>
#include <immersx/vascularization/mesh_scale.h>
#include <immersx/vascularization/metrics.h>
#include <immersx/vascularization/network.h>
#include <immersx/vascularization/reference_flow.h>

namespace ImmersX::Vascularization
{
  struct CalibrationParameters
  {
    void
    validate() const;

    double volume_fraction    = 0.;
    double relative_tolerance = .05;
    double       minimum_coverage  = 0.;
    unsigned int minimum_terminals = 1;
    unsigned int maximum_terminals = 0;
    unsigned int attempt_budget    = 12;
  };

  struct TissueIntegrationParameters
  {
    void
                 validate() const;
    unsigned int quadrature_order     = 2;
    unsigned int samples_per_terminal = 64;
    unsigned int maximum_points       = 4000000;
    unsigned int refinement_budget    = 8;
  };

  enum class CalibrationStatus
  {
    not_requested,
    converged,
    incompatible,
    exhausted
  };

  struct CalibrationAttempt
  {
    unsigned int     terminal_count = 0;
    TissueMetrics    tissue;
    ValidationReport generation_validation;
    std::uint64_t    sampled_points = 0;
  };

  struct CalibrationReport
  {
    CalibrationStatus               status = CalibrationStatus::not_requested;
    std::vector<CalibrationAttempt> attempts;
    std::uint64_t sampled_points = 0;
  };

  struct CompanionParameters
  {
    bool             enabled = false;
    std::vector<Id>  selected_terminals;
    dealii::Point<3> seed_position, seed_inward_port_normal;
    double           seed_radius     = 0.;
    double           murray_exponent = 3.;
    double terminal_separation = .25;
    double microvascular_resistance = 0.;
  };

  using VenousParameters = CompanionParameters;

  struct Parameters : dealii::ParameterAcceptor
  {
    explicit Parameters(const std::string &section = "/Vascularization/");
    void
    validate(bool creating_seed = true) const;

    TissueIntegrationParameters tissue_integration;
    DiscretizationParameters    discretization;
    CoverageParameters          coverage;
    CalibrationParameters       calibration;
    VenousParameters            venous;
    CompanionParameters         portal;
    double portal_flow_fraction = .5;
    std::array<double, 3> compartment_resistances{};
    ReferenceConditions reference_conditions;
    ReferenceParameters reference_parameters;
    std::vector<Id>     selected_terminals;
    dealii::Point<3>    seed_position;
    dealii::Point<3> seed_direction;
    dealii::Point<3> seed_inward_port_normal;
    double           seed_radius              = 0.;
    double           seed_length              = 1.;
    double           viscosity                = 0.;
    double           clearance                = 0.;
    unsigned int     geometry_depth           = 18;
    unsigned int     geometry_work            = 100000;
    unsigned int     terminal_count           = 1;
    unsigned int     random_seed              = 1;
    unsigned int     sample_budget            = 2000;
    unsigned int     candidate_count          = 12;
    unsigned int     optimization_steps       = 10;
    double           arterial_murray_exponent = 3.;
    double           minimum_radius           = 0.;
    double           minimum_length           = .1;
    double           minimum_angle            = 15.;
    double           dissipation_weight       = 0.;
    double           density_beta             = 3.;
    std::string      terminal_weight          = "1";
    double           terminal_weight_bound    = 1.;
    std::string tissue_demand = "1";
    double reference_flow = 0.;
    std::string terminal_count_multiplier_factor = "background cell count";
    std::string length_scale = "local mesh size";
  };

  struct Territory
  {
    Id                          id = invalid_id;
    dealii::Point<3>            position;
    dealii::types::subdomain_id owner  = 0;
    double                      demand = 1.;
  };

  struct GrowthStatistics
  {
    GrowthWork    work, initialization_work, finalization_work;
    System        system              = System::arterial;
    unsigned int  requested_terminals = 0;
    std::uint64_t first_terminals = 0, last_terminals = 0;
    // Global accepted/peak cardinalities: use max, not sum, across ranks.
    std::uint64_t demand_quadrature_points      = 0,
                  demand_quadrature_peak_points = 0;
    std::uint64_t batches = 0, sampled_points = 0, proposed_insertions = 0,
                  accepted_insertions = 0, committed_batches = 0,
                  rejected_batches = 0, active_writer_batches = 0;
    std::uint64_t owned_vessels_first = 0, owned_vessels_last = 0,
                  owned_vessels_maximum = 0;
    double initialization_seconds = 0., sampling_seconds = 0.,
           search_seconds = 0., optimization_seconds = 0.,
           selection_seconds = 0., commit_seconds = 0.,
           redistribution_seconds = 0., physiology_seconds = 0.,
           certification_seconds = 0., finalization_seconds = 0.,
           total_seconds = 0.;
  };

  struct GenerationResult
  {
    MeshLengthScale length_scale;
    unsigned int    base_terminal_count = 0, initial_terminal_count = 0,
                 requested_terminal_count = 0, effective_terminal_count = 0;
    std::map<Id, ScaledVesselMeasure> normalized_geometry;
    NetworkData                       network;
    std::vector<Territory>            territories;
    std::vector<TerminalPair>         terminal_pairs;
    ValidationReport                  validation;
    DiscretizationResult              discretization;
    TissueMetrics                     tissue;
    std::vector<GrowthStatistics> growth_statistics;
    CalibrationReport             calibration;
    ReferenceResult reference;
    std::map<Id, double> target_terminal_flows;
    std::map<Id, double> target_attachment_flows;
    std::map<Id, Id>             attachment_roots;
    std::uint64_t                sampled_points      = 0;
    unsigned int                 accepted_insertions = 0;
    std::vector<TerminalTriplet> terminal_triplets;
  };

  GenerationResult
  generate(const dealii::Triangulation<3> &background,
           const dealii::Mapping<3>       &mapping,
           const NetworkData              &initial,
           const Parameters               &parameters,
           MPI_Comm                        communicator);
  GenerationResult
  generate(const dealii::Triangulation<3>  &background,
           const dealii::Mapping<3>        &mapping,
           const NetworkData               &initial,
           const Parameters                &parameters,
           MPI_Comm                         communicator,
           const std::vector<Territory>    &initial_territories,
           const std::vector<TerminalPair> &initial_pairs);

  GenerationResult
  generate(const dealii::Triangulation<3>     &background,
           const dealii::Mapping<3>           &mapping,
           const NetworkData                  &initial,
           const Parameters                   &parameters,
           MPI_Comm                            communicator,
           const std::vector<Territory>       &initial_territories,
           const std::vector<TerminalPair>    &initial_pairs,
           const std::vector<TerminalTriplet> &initial_triplets);
} // namespace ImmersX::Vascularization
#endif