1 /*=========================================================================
2 *
3 * Copyright Insight Software Consortium
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0.txt
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *=========================================================================*/
18
19 #include "itkFEMSolverHyperbolic.h"
20 #include "itkFEMSpatialObjectReader.h"
21 #include "itkFEMLinearSystemWrapperDenseVNL.h"
22 #include "itkFEMLinearSystemWrapperItpack.h"
23
24
25 using FEMSolverType = itk::fem::SolverHyperbolic<2>;
26
27
28 // Print K - the global stiffness matrix
PrintK(FEMSolverType * S)29 void PrintK(FEMSolverType *S)
30 {
31 itk::fem::LinearSystemWrapper::Pointer lsw = S->GetLinearSystemWrapper();
32
33 std::cout << std::endl << "k" << "=[";
34 for( unsigned int j = 0; j < lsw->GetSystemOrder(); j++ )
35 {
36 std::cout << " [";
37 for( unsigned int k = 0; k < lsw->GetSystemOrder(); k++ )
38 {
39 std::cout << lsw->GetMatrixValue(j, k);
40 if( (k + 1) < lsw->GetSystemOrder() )
41 {
42 std::cout << ", ";
43 }
44 }
45 if( j < lsw->GetSystemOrder() - 1 )
46 {
47 std::cout << " ]," << std::endl;
48 }
49 else
50 {
51 std::cout << "]";
52 }
53 }
54 std::cout << "];" << std::endl;
55 }
56
57 // Print F - the global load vector
PrintF(FEMSolverType * S)58 void PrintF(FEMSolverType *S)
59 {
60 itk::fem::LinearSystemWrapper::Pointer lsw = S->GetLinearSystemWrapper();
61
62 std::cout << std::endl << "f" << "=[";
63 for( unsigned int j = 0; j < lsw->GetSystemOrder(); j++ )
64 {
65 if( j > 0 )
66 {
67 std::cout << ", ";
68 }
69 std::cout << lsw->GetVectorValue(j);
70 }
71 std::cout << "];" << std::endl;
72 }
73
PrintNodalCoordinates(FEMSolverType * S)74 void PrintNodalCoordinates(FEMSolverType *S)
75 // Print the nodal coordinates
76 {
77 std::cout << std::endl << "Nodal coordinates: " << std::endl;
78
79 std::cout << "xyz" << "=[";
80
81 int numberOfNodes = S->GetInput()->GetNumberOfNodes();
82 for( int i = 0; i < numberOfNodes; i++ )
83 {
84 std::cout << " [";
85 std::cout << S->GetInput()->GetNode(i)->GetCoordinates();
86 std::cout << "]";
87 }
88 std::cout << "];" << std::endl;
89 }
90
91
92 // Useful for display purposes - lets you draw each element
93 // individually, instead of just a stream of nodes
PrintElementCoordinates(FEMSolverType * S)94 void PrintElementCoordinates(FEMSolverType *S )
95 {
96 std::cout << std::endl << "Element coordinates: " << std::endl;
97 int ct = 1;
98
99 const unsigned int invalidID = itk::fem::Element::InvalidDegreeOfFreedomID;
100
101 int numberOfElements = S->GetInput()->GetNumberOfElements();
102
103 for(int i = 0; i < numberOfElements; i++ )
104 {
105 std::cout << "e(" << ct << ",:,:)=[";
106
107 for (unsigned int n=0; n < S->GetInput()->GetElement(i)->GetNumberOfNodes(); n++)
108 {
109 itk::fem::Element::VectorType nc = S->GetInput()->GetElement(i)->GetNodeCoordinates(n);
110
111 for (unsigned int d=0, dof; ( dof = S->GetInput()->GetElement(i)->GetNode(n)->GetDegreeOfFreedom(d) ) != invalidID; d++)
112 {
113 nc[d] += S->GetSolution( dof );
114 }
115 std::cout << nc << std::endl;
116 }
117 std::cout << "];" << std::endl;
118 ct++;
119 }
120 }
121
122 // Useful for display purposes - lets you draw each element
123 // individually, instead of just a stream of nodes
PrintSolution(FEMSolverType * S)124 void PrintSolution(FEMSolverType *S )
125 {
126 std::cout << std::endl << "Solution: " << std::endl;
127 const unsigned int invalidID = itk::fem::Element::InvalidDegreeOfFreedomID;
128 int numberOfNodes = S->GetInput()->GetNumberOfNodes();
129
130 for (int i = 0; i < numberOfNodes; i++ )
131 {
132 std::cout << "Solution Node " << i << ":";
133 for (unsigned int d=0, dof; ( dof = S->GetInput()->GetNode(i)->GetDegreeOfFreedom(d) ) != invalidID; d++)
134 {
135 std::cout << " " << S->GetSolution( dof );
136 }
137 std::cout << std::endl;
138 }
139 }
140
itkFEMSolverHyperbolicTest(int ac,char * av[])141 int itkFEMSolverHyperbolicTest(int ac, char* av[])
142 {
143
144 if (ac < 4)
145 {
146 std::cout << "Usage: " << av[0];
147 std::cout << " input-file iterations lsw (0=VNL, 1=Dense VNL, 2=Itpack)";
148 std::cout << std::endl;
149 return EXIT_FAILURE;
150 }
151
152 itk::FEMFactoryBase::GetFactory()->RegisterDefaultTypes();
153
154 unsigned int niter = std::stoi ( av[2] );
155 unsigned int w = std::stoi( av[3] );
156 std::vector<double> solution;
157 if (ac > 4)
158 {
159 solution.resize( ac - 4 );
160 for (int i=4;i<ac;i++)
161 {
162 solution[i-4] = std::stod(av[i]);
163 }
164 }
165
166 using FEMSpatialObjectReaderType = itk::FEMSpatialObjectReader<2>;
167 using FEMSpatialObjectReaderPointer = FEMSpatialObjectReaderType::Pointer;
168 FEMSpatialObjectReaderPointer SpatialReader = FEMSpatialObjectReaderType::New();
169 SpatialReader->SetFileName( av[1] );
170 try
171 {
172 SpatialReader->Update();
173 }
174 catch (::itk::fem::FEMException & e)
175 {
176 std::cout<<"Error reading FEM problem: "<< av[1] <<"!\n";
177 e.Print(std::cout);
178 return EXIT_FAILURE;
179 }
180
181 using FEMObjectSpatialObjectType = itk::FEMObjectSpatialObject<2>;
182 FEMObjectSpatialObjectType::ChildrenListType* children = SpatialReader->GetGroup()->GetChildren();
183 FEMObjectSpatialObjectType::Pointer femSO =
184 dynamic_cast<FEMObjectSpatialObjectType *>( (*(children->begin() ) ).GetPointer() );
185 if (!femSO)
186 {
187 std::cout << " dynamic_cast [FAILED]" << std::endl;
188 return EXIT_FAILURE;
189 }
190 delete children;
191
192 femSO->GetFEMObject()->FinalizeMesh();
193
194 /**
195 * Third, create the FEM solver object and generate the solution
196 */
197
198 FEMSolverType::Pointer SH = FEMSolverType::New();
199 SH->SetInput( femSO->GetFEMObject() );
200 SH->SetTimeStep( .5 );
201 SH->SetNumberOfIterations( niter );
202
203 itk::fem::LinearSystemWrapperDenseVNL lsw_dvnl;
204 itk::fem::LinearSystemWrapperItpack lsw_itpack;
205 itk::fem::LinearSystemWrapperVNL lsw_vnl;
206
207 switch (w)
208 {
209 case 0:
210 // VNL
211 std::cout << std::endl << ">>>>>Using LinearSystemWrapperVNL" << std::endl;
212 SH->SetLinearSystemWrapper(&lsw_vnl);
213 break;
214 case 1:
215 // Dense VNL
216 std::cout << std::endl << ">>>>>Using LinearSystemWrapperDenseVNL" << std::endl;
217 SH->SetLinearSystemWrapper(&lsw_dvnl);
218 break;
219 case 2:
220 // IT Pack
221 std::cout << std::endl << ">>>>>Using LinearSystemWrapperItpack" << std::endl;
222 SH->SetLinearSystemWrapper(&lsw_itpack);
223 break;
224 default:
225 // Sparse VNL - default
226 std::cout << std::endl << ">>>>>Using LinearSystemWrapperVNL" << std::endl;
227 SH->SetLinearSystemWrapper(&lsw_vnl);
228 break;
229 }
230
231 try
232 {
233 SH->Update();
234 }
235 catch (itk::ExceptionObject &err)
236 {
237 std::cerr << "ITK exception detected: " << err;
238 return EXIT_FAILURE;
239 }
240
241 PrintK( SH );
242 PrintF( SH );
243 PrintNodalCoordinates( SH );
244 PrintSolution( SH );
245
246 if (ac > 4)
247 {
248 int numberOfNodes = SH->GetInput()->GetNumberOfNodes();
249 const unsigned int invalidID = itk::fem::Element::InvalidDegreeOfFreedomID;
250 for (int i = 0; i < numberOfNodes; i++ )
251 {
252 for (unsigned int d=0, dof; ( dof = SH->GetInput()->GetNode(i)->GetDegreeOfFreedom(d) ) != invalidID; d++)
253 {
254 double result = SH->GetSolution( dof );
255 if (fabs(result-solution[dof]) > 1.0e-5)
256 {
257 std::cerr << "Error: Solution outside the expected range: " << result << ", " << dof << std::endl;
258 return EXIT_FAILURE;
259 }
260 }
261 }
262 }
263 return EXIT_SUCCESS;
264 }
265