Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
testActorIndexCaches.cpp
Go to the documentation of this file.
2#include <NetworkLinkActor.h>
3#include <NetworkLoopActor.h>
4#include <QApplication>
5#include <vtkActorCollection.h>
6#include <vtkCellData.h>
7#include <vtkRenderer.h>
8#include <filesystem>
9#include <fstream>
10#include <iomanip>
11#include <chrono>
12#include <iostream>
13
14void require(bool condition,const char* message)
15{
16 if(!condition)
17 {
18 throw std::runtime_error(message);
19 }
20}
21
22void checkLine(vtkPolyData* data,vtkIdType index,vtkIdType source,vtkIdType sink)
23{
24 vtkIdType count=0;
25 const vtkIdType* ids=nullptr;
26 data->GetLines()->GetNextCell(count,ids);
27 require(index<data->GetNumberOfLines() && count==2 && ids[0]==source && ids[1]==sink,
28 "Cached connectivity differs from legacy networkID ordering");
29}
30
31void checkActors(model::DefectiveCrystal<3>& crystal,bool changeTopology)
32{
34 auto window=vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
35 window->SetReadyForRendering(false);
36 auto renderer=vtkSmartPointer<vtkRenderer>::New();
37 window->AddRenderer(renderer);
38 model::NetworkLinkActor links(window,renderer,crystal);
39 const int loopStart=renderer->GetActors()->GetNumberOfItems();
40 model::NetworkLoopActor loops(window,renderer,crystal);
41 const auto verify=[&]()
42 {
43 const auto nodeCount=network->networkNodes().size();
44 const auto loopNodeCount=network->loopNodes().size();
45 std::map<std::pair<size_t,size_t>,std::set<size_t>> sharing;
46 auto points=vtkSmartPointer<vtkPoints>::New();
47 for(const auto& entry : network->networkNodes())
48 {
49 points->InsertNextPoint(entry.second.lock()->get_P().data());
50 }
51 auto input=vtkSmartPointer<vtkPolyData>::New();
52 input->SetPoints(points);
53 for(const auto& entry : network->networkLinks())
54 {
55 for(const auto* ll : entry.second.lock()->loopLinks())
56 {
57 sharing[entry.first].insert(ll->loop->sID);
58 }
59 }
60 links.updateConfiguration(input,{});
61 loops.updateConfiguration({});
62 vtkPolyData* data[3];
63 vtkIdType counts[3]={0,0,0};
64 for(int group=0;group<3;++group)
65 {
66 auto* actor=vtkActor::SafeDownCast(renderer->GetActors()->GetItemAsObject(group));
67 auto* tube=vtkTubeFilter::SafeDownCast(actor->GetMapper()->GetInputAlgorithm());
68 require(tube,"Missing segment tube filter");
69 data[group]=vtkPolyData::SafeDownCast(tube->GetInputDataObject(0,0));
70 require(data[group] && data[group]->GetPoints()==points,"Segment points changed");
71 data[group]->GetLines()->InitTraversal();
72 }
73 for(const auto& entry : network->networkLinks())
74 {
75 const auto link=entry.second.lock();
76 const int group=link->hasZeroBurgers()?2:((link->isBoundarySegment() || link->isGrainBoundarySegment())?1:0);
77 checkLine(data[group],counts[group],link->source->networkID(),link->sink->networkID());
78 if(group!=2)
79 {
80 const auto expected=links.computeColor(link->burgers(),link->chord(),link->slipSystem(),{});
81 auto* colors=group==0?data[group]->GetCellData()->GetArray("Colors"):data[group]->GetCellData()->GetScalars();
82 require(colors,"Missing segment colors");
83 for(int k=0;k<3;++k)
84 {
85 require(colors->GetComponent(counts[group],k)==static_cast<unsigned char>(expected(k)),"Segment color changed");
86 }
87 }
88 std::set<size_t> memberships;
89 for(const auto* ll : link->loopLinks())
90 {
91 memberships.insert(ll->loop->sID);
92 }
93 require(memberships==sharing.at(entry.first),"Actor update changed junction sharing");
94 ++counts[group];
95 }
96 for(int group=0;group<3;++group)
97 {
98 require(counts[group]==data[group]->GetNumberOfLines(),"Segment count changed");
99 }
100 auto* loopActor=vtkActor::SafeDownCast(renderer->GetActors()->GetItemAsObject(loopStart+1));
101 auto* loopData=vtkPolyData::SafeDownCast(loopActor->GetMapper()->GetInputDataObject(0,0));
102 require(loopData && loopData->GetNumberOfPoints()==static_cast<vtkIdType>(loopNodeCount),"Loop occurrences were merged");
103 require(loopData->GetNumberOfLines()==static_cast<vtkIdType>(network->loopLinks().size()),"Loop line count changed");
104 loopData->GetLines()->InitTraversal();
105 vtkIdType i=0;
106 for(const auto& entry : network->loopLinks())
107 {
108 checkLine(loopData,i++,entry.second.source->networkID(),entry.second.sink->networkID());
109 }
110 for(const auto& entry : network->loopNodes())
111 {
112 const auto node=entry.second.lock();
113 double xyz[3];
114 loopData->GetPoint(node->networkID(),xyz);
115 for(int k=0;k<3;++k)
116 {
117 require(xyz[k]==static_cast<float>(node->get_P()(k)),"Loop point position changed");
118 }
119 }
120 require(network->networkNodes().size()==nodeCount && network->loopNodes().size()==loopNodeCount,
121 "Actor update changed topology");
122 };
123 verify();
124 if(changeTopology)
125 {
126 std::shared_ptr<model::DislocationNetwork<3>::NetworkLinkType> shared;
127 for(const auto& entry : network->networkLinks())
128 {
129 const auto link=entry.second.lock();
130 if(link->loopLinks().size()>1 && link->chordLength()>1 && !link->isBoundarySegment())
131 {
132 shared=link;
133 break;
134 }
135 }
136 require(bool(shared),"Fixture has no shared junction");
137 const auto memberships=shared->loopLinks().size();
138 auto inserted=network->networkNodes().create(shared->get_r(0.5));
139 network->expandNetworkLink(shared,inserted);
140 shared.reset();
141 require(inserted->loopNodes().size()==memberships,"Expansion lost junction sharing");
142 network->updateGeometry();
143 verify();
144 network->removeNetworkNode(inserted->sID);
145 inserted.reset();
146 network->updateGeometry();
147 verify();
148 }
149}
150
151int main(int argc,char** argv)
152{
153 QApplication app(argc,argv);
154 try
155 {
156 require(argc == 2, "Expected repository root");
157 const std::filesystem::path root(argv[1]);
158 const auto folder = std::filesystem::temp_directory_path() /
159 ("actor-index-caches-" + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count()));
160 const auto input = folder / "inputFiles";
161 std::filesystem::create_directories(input);
162 std::filesystem::create_directories(folder / "F");
163 std::filesystem::copy_file(root / "Library/Materials/W.txt", input / "W.txt");
164
165 std::filesystem::copy_file(root / "Library/Meshes/bicrystal_48.msh", input / "mesh.msh");
166 std::filesystem::copy_file(root / "Library/DislocationDynamics/DD.txt", input / "DD.txt");
167 std::filesystem::create_directories(folder / "config");
168 const double length=3671.9477120460206;
169 {
170 std::ofstream f(input / "DefectiveCrystal.txt");
171 f << "physics=DislocationDynamics;\nuseFEM=0;\nNsteps=0;\nmaxResolveSteps=0;\ndtMax=1;\noutputFrequency=1;\noutputBinary=0;\nstartAtTimeStep=0;\nperiodicImageSize=0 0 0;\nEwaldLengthFactor=0;\n";
172 std::ofstream p(input / "polycrystal.txt");
173 p << std::setprecision(17) << "materialFile=W.txt;\nmeshFile=mesh.msh;\nabsoluteTemperature=300;\nC2G1=1 0 0 0 1 0 0 0 1;\n"
174 << "C2G2=0.8 0 0.6 0 1 0 -0.6 0 0.8;\nF=" << length << " 0 0 0 " << length << " 0 0 0 " << length
175 << ";\nX0=0 0 0;\nperiodicFaceIDs=-1;\n";
176 }
177 // Match the tutorial remeshing length, without depending on its inputs.
178 {
179 const auto dd=input/"DD.txt";
180 std::ifstream source(dd);
181 std::string contents((std::istreambuf_iterator<char>(source)),std::istreambuf_iterator<char>());
182 const auto location=contents.find("Lmax=100;");
183 require(location!=std::string::npos,"Expected library remeshing default");
184 contents.replace(location,std::string("Lmax=100;").size(),"Lmax=150;");
185 std::ofstream output(dd);
186 output<<contents;
187 }
188
189 for(const std::string fixture : {"bicrystalBoundary430.txt","bicrystalBoundary500.txt","bicrystalSharedConstraints1915.txt"})
190 {
191 model::DefectiveCrystalBase<3> base(folder.string());
192 model::DefectiveCrystal<3> crystal(base);
194 model::DefectiveCrystalConfigIO<3> saved(folder.string());
195 std::ifstream stream(root/"tests/data"/fixture);
196 require(bool(stream),"Missing bicrystal fixture");
197 saved.readTxtStream(stream);
198 network->initializeConfiguration(saved,std::ofstream(),std::ofstream());
199 checkActors(crystal,fixture=="bicrystalSharedConstraints1915.txt");
200 }
201 std::filesystem::remove_all(folder);
202 std::cout<<"PASS: actor points, connectivity, colors and junction sharing match legacy indexing\n";
203 return 0;
204 }
205 catch(const std::exception& error)
206 {
207 std::cerr<<error.what()<<std::endl;
208 return 1;
209 }
210}
void initializeConfiguration(const DefectiveCrystalConfigIO< dim > &configIO, const std::ofstream &f_file, const std::ofstream &F_labels) override
function int_R syms a b c u real f
Definition int_R.m:4
std::shared_ptr< MicrostructureType > getUniqueTypedMicrostructure() const
void updateConfiguration(const SlipSystemTab::SlipSystemColorMapType &sscm)
void checkActors(model::DefectiveCrystal< 3 > &crystal, bool changeTopology)
void require(bool condition, const char *message)
void checkLine(vtkPolyData *data, vtkIdType index, vtkIdType source, vtkIdType sink)
fs::path fixture(const fs::path &root, int rank, int reactions, bool source, const std::string &name="unitCube24.msh")
void verify(Network &network)
void argv
int index
void b int argc
vertex p[3]
int k
int i