void FHierarchicalLODBuilder::BuildClusters(ULevel* InLevel, const bool bCreateMeshes) { SCOPE_LOG_TIME(TEXT("STAT_HLOD_BuildClusters"), nullptr); // I'm using stack mem within this scope of the function // so we need this FMemMark Mark(FMemStack::Get()); // you still have to delete all objects just in case they had it and didn't want it anymore TArray<UObject*> AssetsToDelete; for (int32 ActorId=InLevel->Actors.Num()-1; ActorId >= 0; --ActorId) { ALODActor* LodActor = Cast<ALODActor>(InLevel->Actors[ActorId]); if (LodActor) { for (auto& Asset: LodActor->SubObjects) { // @TOOD: This is not permanent fix if (Asset) { AssetsToDelete.Add(Asset); } } World->DestroyActor(LodActor); } } ULevel::BuildStreamingData(InLevel->OwningWorld, InLevel); for (auto& Asset : AssetsToDelete) { Asset->MarkPendingKill(); ObjectTools::DeleteSingleObject(Asset, false); } // garbage collect CollectGarbage( GARBAGE_COLLECTION_KEEPFLAGS, true ); // only build if it's enabled if(InLevel->GetWorld()->GetWorldSettings()->bEnableHierarchicalLODSystem && InLevel->GetWorld()->GetWorldSettings()->HierarchicalLODSetup.Num() != 0) { // Handle HierachicalLOD volumes first HandleHLODVolumes(InLevel); AWorldSettings* WorldSetting = InLevel->GetWorld()->GetWorldSettings(); const int32 TotalNumLOD = InLevel->GetWorld()->GetWorldSettings()->HierarchicalLODSetup.Num(); for(int32 LODId=0; LODId<TotalNumLOD; ++LODId) { // we use meter for bound. Otherwise it's very easy to get to overflow and have problem with filling ratio because // bound is too huge const float DesiredBoundRadius = WorldSetting->HierarchicalLODSetup[LODId].DesiredBoundRadius * CM_TO_METER; const float DesiredFillingRatio = WorldSetting->HierarchicalLODSetup[LODId].DesiredFillingPercentage * 0.01f; ensure(DesiredFillingRatio!=0.f); const float HighestCost = FMath::Pow(DesiredBoundRadius, 3) / (DesiredFillingRatio); const int32 MinNumActors = WorldSetting->HierarchicalLODSetup[LODId].MinNumberOfActorsToBuild; check (MinNumActors > 0); // test parameter I was playing with to cull adding to the array // intialization can have too many elements, decided to cull // the problem can be that we can create disconnected tree // my assumption is that if the merge cost is too high, then it's not worth merge anyway static int32 CullMultiplier=1; // since to show progress of initialization, I'm scoping it { FString LevelName = FPackageName::GetShortName(InLevel->GetOutermost()->GetName()); FFormatNamedArguments Arguments; Arguments.Add(TEXT("LODIndex"), FText::AsNumber(LODId+1)); Arguments.Add(TEXT("LevelName"), FText::FromString(LevelName)); FScopedSlowTask SlowTask(100, FText::Format(LOCTEXT("HierarchicalLOD_InitializeCluster", "Initializing Clusters for LOD {LODIndex} of {LevelName}..."), Arguments)); SlowTask.MakeDialog(); // initialize Clusters InitializeClusters(InLevel, LODId, HighestCost*CullMultiplier); // move a half way - I know we can do this better but as of now this is small progress SlowTask.EnterProgressFrame(50); // now we have all pair of nodes FindMST(); } // now we have to calculate merge clusters and build actors MergeClustersAndBuildActors(InLevel, LODId, HighestCost, MinNumActors, bCreateMeshes); } } else { // Fire map check warnings if HLOD System is not enabled FMessageLog MapCheck("MapCheck"); MapCheck.Warning() ->AddToken(FUObjectToken::Create(InLevel->GetWorld()->GetWorldSettings())) ->AddToken(FTextToken::Create(LOCTEXT("MapCheck_Message_HLODSystemNotEnabled", "Hierarchical LOD System is disabled or no HLOD level settings available, unable to build LOD actors."))) ->AddToken(FMapErrorToken::Create(FMapErrors::HLODSystemNotEnabled)); } // Clear Clusters. It is using stack mem, so it won't be good after this Clusters.Empty(); Clusters.Shrink(); }
void ExplicitSolverStrategy::Initialize() { KRATOS_TRY ModelPart& r_model_part = GetModelPart(); ProcessInfo& r_process_info = r_model_part.GetProcessInfo(); SendProcessInfoToClustersModelPart(); // Omp initializations mNumberOfThreads = OpenMPUtils::GetNumThreads(); mNeighbourCounter.resize(mNumberOfThreads); RebuildListOfSphericParticles<SphericParticle>(r_model_part.GetCommunicator().LocalMesh().Elements(), mListOfSphericParticles); RebuildListOfSphericParticles<SphericParticle>(r_model_part.GetCommunicator().GhostMesh().Elements(), mListOfGhostSphericParticles); CreatePropertiesProxies(mFastProperties, *mpDem_model_part, *mpInlet_model_part, *mpCluster_model_part); RepairPointersToNormalProperties(mListOfSphericParticles); // The particles sent to this partition have their own copy of the Kratos properties they were using in the previous partition!! RepairPointersToNormalProperties(mListOfGhostSphericParticles); RebuildPropertiesProxyPointers(mListOfSphericParticles); RebuildPropertiesProxyPointers(mListOfGhostSphericParticles); GetSearchControl() = r_process_info[SEARCH_CONTROL]; InitializeDEMElements(); InitializeFEMElements(); UpdateMaxIdOfCreatorDestructor(); InitializeClusters(); // This adds elements to the balls modelpart RebuildListOfSphericParticles<SphericParticle>(r_model_part.GetCommunicator().LocalMesh().Elements(), mListOfSphericParticles); RebuildListOfSphericParticles<SphericParticle>(r_model_part.GetCommunicator().GhostMesh().Elements(), mListOfGhostSphericParticles); InitializeSolutionStep(); ApplyInitialConditions(); // Search Neighbours and related operations SetSearchRadiiOnAllParticles(r_model_part, r_process_info[SEARCH_TOLERANCE], 1.0); SearchNeighbours(); ComputeNewNeighboursHistoricalData(); SetSearchRadiiWithFemOnAllParticles(r_model_part, r_process_info[SEARCH_TOLERANCE], 1.0); SearchRigidFaceNeighbours(); //initial search is performed with hierarchical method in any case MSI ComputeNewRigidFaceNeighboursHistoricalData(); //set flag to 2 (search performed this timestep) mSearchControl = 2; // Finding overlapping of initial configurations if (r_process_info[CLEAN_INDENT_OPTION]) { for (int i = 0; i < 10; i++) CalculateInitialMaxIndentations(); } if (r_process_info[CRITICAL_TIME_OPTION]) { //InitialTimeStepCalculation(); //obsolete call CalculateMaxTimeStep(); } r_process_info[PARTICLE_INELASTIC_FRICTIONAL_WORK] = 0.0; // 5. Finalize Solution Step. //FinalizeSolutionStep(); //KRATOS_WATCH(r_model_part.GetNodalSolutionStepVariablesList()) KRATOS_CATCH("") }// Initialize()