Falsche Ergebnisse im Release Mode
-
Hallo,
wie vermutlich viele vor mir, habe ich das Problem, das mein Programm im Release Mode falsche Ergebnisse liefert, aber im Debug Mode die korrekten Werte berechnet.
Ich schreibe mit C++ unter Linux ein Programm zur Simulation von Einebnungen einer Feinblechoberfläche im Mikrometerbereich. Dazu nutze ich eine FEM-Bibliothek namens "deal.ii". Ich versuche nun einen speziellen Löser (eine Klasse entwickelt von jemand anderem) in meinen bestehenden Code einzubauen, wobei der besagte Fehler auftritt.Die Klassendeklaration sieht folgendermaßen aus:
// includes aus der deal.ii-Bibliothek #include "../../deal.II/deal.II/include/fe/mapping_q.h" #include <numerics/data_out.h> #include <lac/eigen.h> #include <lac/matrix_lib.h> #include <lac/vector_memory.h> #include <base/function.h> #include <lac/sparsity_pattern.h> #include <lac/sparse_matrix.h> #include <iostream> #include <fstream> #include <set> #include <vector> template <int dim> struct PointInformation { Point<dim> point, normal_vector; double gap, dist; std::vector<unsigned int> dof; int boundary_index; }; template <int dim> class SignoriniRotatingSolver2 { public: SignoriniRotatingSolver2(SolverControl &sc, DoFHandler<dim> &dof_handler, double precondition_omega, const Vector<double> _complete_displacement, const double _kn); virtual ~SignoriniRotatingSolver2(); template <class MATRIX, class FUNCTION> void solve(const MATRIX &A, Vector<double> &u, const Vector<double> &rhs, const std::vector<FUNCTION* > &obstacle_function, std::vector<unsigned char> direction, std::vector<unsigned char> &boundary_indicator, double precondition_omega, double &relative_correction); void get_point_information_list(std::list< PointInformation<dim> > &a_list); private: void loop_along_boundary(Vector<double> u_0); void project(Vector<double> &v); template<class MATRIX> double calculate_residual(const MATRIX &A, const Vector<double> &u, const Vector<double> &rhs); void calculate_gap(typename std::list<PointInformation<dim> >::iterator &point_it, double tol); template <class MATRIX, class VECTOR> void relax(const MATRIX &A, VECTOR &v, const VECTOR &b); SolverControl* solver_control; DoFHandler<dim> &dofhandler; double omega; std::set<unsigned int> contact_dofs; unsigned int n,m; std::vector<Vector<double>* > obs_vector; std::list< PointInformation<dim> > point_information_list; std::vector< Point<dim> > support_points; std::vector< unsigned char> boundary_indicator; std::vector<unsigned char> direction; Vector<double> u_0; std::map<unsigned int ,double> gap; std::vector<Function<dim-1>* > obstacle_function; // Fuer MUS+ einfuegt Variabeln const Vector<double> complete_displacement; const double kn; };In der folgenden Methode "solve()":
template <int dim> template <class MATRIX, class FUNCTION> void SignoriniRotatingSolver2<dim>::solve(const MATRIX &A, Vector<double> &u, const Vector<double> &rhs, const std::vector<FUNCTION* > &obstacle_function, std::vector<unsigned char> direction, std::vector<unsigned char> &boundary_indicator, double precondition_omega, double &relative_correction) ////////////////////////////////////////////////////////////////////// // // __dim = 2__: // direction[i] gibt an, in welcher Richtung das i-te Hindernis zum // Kontaktrand liegt: // 3 // ________________________ // // | ___________________ | // | / \ | // 0 | | Omega | | 1 // | | | | // | \___________________/ | // _______________________ // 2 // // // // ////////////////////////////////////////////////////////////////////// { Vector<double> u_twin(A.n()); u_twin=u; if(precondition_omega!=0) omega=precondition_omega; this->boundary_indicator=boundary_indicator; this->direction=direction; this->obstacle_function=obstacle_function; assert(A.n()==A.m()); assert(u.size()==n); assert(rhs.size()==n); m=obstacle_function.size(); assert(direction.size()==m); assert(boundary_indicator.size()==m); unsigned int i,j; bool good_u=false; for(i=1;i<m;i++) assert(direction[i]<2*dim); //Finde die Randpunkte und berechne Normalenvektoren und Abstand zum Hindernis, speichere alles in point_information_list: loop_along_boundary(u); ...(Die Methode ist noch wesentlich länger.) wird die Methode "loop_along_boundary()" aufgerufen:
template<> void SignoriniRotatingSolver2<3>::loop_along_boundary(Vector<double> u_0) { const int dim=3; unsigned int counter=0, i, j, k, n_dofs_per_face=dofhandler.get_fe().n_dofs_per_face(); unsigned int n_dofs_per_cell=dofhandler.get_fe().n_dofs_per_cell(); double pd, pc, norm_av; std::map<unsigned int, PointInformation3D> point3d_map; PointInformation3D point3d; Point<3> n_av, n, p, d, c; std::vector<Point<3> > t(2);//alt point3d.dof.resize(3); std::list<PointInformation<3> >::iterator point_it; std::vector<std::vector<unsigned int> > corner(4); for(i=0;i<4;i++) corner[i].resize(3); std::vector<unsigned int> dof_indices(n_dofs_per_face), dof_indices_cell(n_dofs_per_cell); std::map<unsigned int, PointInformation3D>::iterator point3d_it, point3d_end=point3d_map.end(); DoFHandler<dim>::active_face_iterator face=dofhandler.begin_active_face(); DoFHandler<dim>::active_cell_iterator cell=dofhandler.begin_active(); DoFHandler<dim>::active_cell_iterator end_cell=dofhandler.end(); for(;cell!=end_cell;cell++) if(cell->at_boundary()) { for(k=0;k<GeometryInfo<dim>::faces_per_cell;k++) if(cell->at_boundary(k)) { face=cell->face(k); bool signorini_boundary=false; for(unsigned int l=0;!signorini_boundary&&l<boundary_indicator.size();l++) if((int)(face->boundary_indicator())==(int)(boundary_indicator[l])) signorini_boundary=true; if(signorini_boundary)//tu nur etwas, wenn face Teil des Signorini-Randes ist. { point3d.boundary_index=face->boundary_indicator(); //Achtung, hier! point3d.neighbours.clear(); cell->get_dof_indices(dof_indices_cell); switch(k) { case 0: for(i=0;i<4;i++) for(j=0;j<3;j++) corner[i][j]=dof_indices_cell[i*3+j]; break; case 1: for(i=7;i>3;i--) for(j=0;j<3;j++) corner[7-i][j]=dof_indices_cell[i*3+j]; break; case 2: for(j=0;j<3;j++) { corner[0][j]=dof_indices_cell[1*3+j]; corner[1][j]=dof_indices_cell[0*3+j]; corner[2][j]=dof_indices_cell[4*3+j]; corner[3][j]=dof_indices_cell[5*3+j]; } break; case 3: for(j=0;j<3;j++) { corner[0][j]=dof_indices_cell[1*3+j]; corner[1][j]=dof_indices_cell[5*3+j]; corner[2][j]=dof_indices_cell[6*3+j]; corner[3][j]=dof_indices_cell[2*3+j]; } break; case 4: for(j=0;j<3;j++) { corner[0][j]=dof_indices_cell[2*3+j]; corner[1][j]=dof_indices_cell[6*3+j]; corner[2][j]=dof_indices_cell[7*3+j]; corner[3][j]=dof_indices_cell[3*3+j]; } break; case 5: for(j=0;j<3;j++) { corner[0][j]=dof_indices_cell[0*3+j]; corner[1][j]=dof_indices_cell[3*3+j]; corner[2][j]=dof_indices_cell[7*3+j]; corner[3][j]=dof_indices_cell[4*3+j]; } break; } point3d.neighbours.push_back(corner); face->get_dof_indices(dof_indices); for(i=0;i<n_dofs_per_face/3;i++) { for(j=0;j<3;j++) point3d.dof[dofhandler.get_fe().system_to_component_index(i*3+j).first]=dof_indices[i*3+j]; point3d_it=point3d_map.find(point3d.dof[0]); if(point3d_it==point3d_map.end()) point3d_map[point3d.dof[0]]=point3d; else { /* bool signorini_boundary=false; for(unsigned int l=0;!signorini_boundary&&l<boundary_indicator.size();l++) if((int)(boundary_indicator[l])==(int)(point3d_it->second.boundary_index)) signorini_boundary=true;//Stelle sicher, daß Signorini-Punkte keinen Nicht-Signorini-Index kriegen. if(!signorini_boundary) point3d_it->second.boundary_index=point3d.boundary_index; */ point3d_it->second.neighbours.push_back(corner); } } } } } point_information_list.clear(); PointInformation<3> point_info; point_info.dof.resize(3); std::list<std::vector<std::vector<unsigned int> > >::iterator neighbour_it; for(point3d_it=point3d_map.begin();point3d_it!=point3d_map.end();point3d_it++) { n_av=Point<dim>(); point_info.dof=point3d_it->second.dof; point_info.point=support_points[point_info.dof[0]]; point_info.boundary_index=255; for(i=0;i<boundary_indicator.size();i++) { if(((int)(boundary_indicator[i]))==((int)(point3d_it->second.boundary_index))) point_info.boundary_index=i; } p=point_info.point; for(k=0;k<3;k++) p(k)+=u_0(point_info.dof[k]); point_info.point=p; for(neighbour_it=point3d_it->second.neighbours.begin(); neighbour_it!=point3d_it->second.neighbours.end();neighbour_it++) {//Schleife über alle mit dem Punkt inzidenten Rechtecke for(j=0;j<2;j++) {//Berechne Tangentenvektoren d=support_points[(*neighbour_it)[2+j][0]]; c=support_points[(*neighbour_it)[j][0]]; for(k=0;k<3;k++) { d(k)+=u_0((*neighbour_it)[2+j][k]); c(k)+=u_0((*neighbour_it)[j][k]); } pd=p.distance(d); pc=p.distance(c); t[j]=p-c; if(pd>0) t[j]*=pd*pd; if(pc>0) { t[j]+=(pc*pc)*d; t[j]-=(pc*pc)*p; } else t[j]=d-p; } //Berechne Normalenvektor: n(0)=t[0](1)*t[1](2)-t[0](2)*t[1](1);//Kreuzprodukt n(1)=t[0](2)*t[1](0)-t[0](0)*t[1](2); n(2)=t[0](0)*t[1](1)-t[0](1)*t[1](0); n*=1/n.norm(); n_av+=n; } n_av*=1/n_av.norm(); point_info.normal_vector=n_av; if(point_info.boundary_index!=255) {//Speichere den Randpunkt nur, wenn er auch am Signorini-Rand liegt. point_information_list.push_back(point_info); point_it=point_information_list.end(); point_it--; calculate_gap(point_it, .000001); } } }Je nachdem an welcher Stelle der letzten Methode ich eine Ausgabe mit std::cout platziere, erhalte ich andere, teilweise "bessere" Werte.
Kann mir jemand einen Tip geben, wo der Fehler liegen könnte bzw. wie ich bei der Fehlersuche am besten vorgehen soll.
Die Suche nach der Nadel im Heuhaufen dauert nun schon einige Wochen an.Danke schonmal im voraus
Gruß
Pucky
-
Ich hab mir deinen Code nicht angeschaut, aber ich kann dir ein Paar allgemeine Tipps geben:
- Initialisiere _alle_ Variablen mit einem sinnvollen Standard Wert (z.B. 0). Also auch Membervariablen in deinen Klassen. Die bekommen im Debugmodus in der Regel einen Defaultwert zugewiesen (wobei sie im Releasemodus einen Zufallswert enthalten)
- Vermeide das mischen von Datentypen bei Rechenoperationen z.B.:float erg = 0; int zahl1 = 3; float zahl2 = 2; erg = zahl1 / zahl2;
-
Chris++ schrieb:
- Initialisiere _alle_ Variablen mit einem sinnvollen Standard Wert (z.B. 0).
da sollte solch' ein Problem in 99,5% aller Fälle lösen und in dem speziellen Fall würde ich erst mal einen Default-Konstruktor für PointInformation schreiben:
template <int dim> struct PointInformation { PointInformation() : point() , normal_vector() , gap(0.0) , dist(0.0) , dof() , boundary_index(0) {} // usw.... ohne den Code anzusehen, wette ich 2:1, dass es dann geht.
-
Eventuell noch die Verwendung von C-Arrays komplett verhindern und eine Möglichkeit einbauen, ragne-checks bei vector-Zugriffen einzuschalten, auch im Releasemodus.
Außerdem nochmal prüfen ob wirklich alle Iteratoren noch gültig sind.
-
Wobei die STL im Debug-Modus mit Assertions abgecheckt sein sollte, Zugriffs- und Iteratorfehler wären also erkennbar...
-
Also ich habe zunächst mal für beide structs einen default-Konstruktor geschrieben:
template <int dim> struct PointInformation { PointInformation():point(), normal_vector(), gap(0.0), dist(0.0), dof(), boundary_index(0) {} Point<dim> point, normal_vector; double gap, dist; std::vector<unsigned int> dof; int boundary_index; }; struct PointInformation3D { PointInformation3D():dof(), neighbours(), boundary_index(0) {} std::vector<unsigned int> dof; std::list<std::vector<std::vector<unsigned int> > > neighbours; int boundary_index; };Außerdem habe ich alle Membervariabeln initialisiert:
template <int dim> SignoriniRotatingSolver2<dim>::SignoriniRotatingSolver2(SolverControl &sc, DoFHandler<dim> &dof_handler, double precondition_omega, const Vector<double> _complete_displacement, const double _kn): solver_control(&sc), dofhandler(dof_handler), omega(precondition_omega), contact_dofs(), m(0), obs_vector(), point_information_list(), support_points(), boundary_indicator(), direction(), u_0(), gap(), obstacle_function(), complete_displacement(_complete_displacement), kn(_kn) { n=dof_handler.n_dofs(); MappingQ<dim> mapping(1); support_points.resize(n); DoFTools::map_dofs_to_support_points(mapping, dofhandler, support_points); }Leider hat das alles noch nicht den gewünschten Erfolg gebracht.
Hier mal die Ausgabe beim Kompilieren im Debug Mode:Makefile:146: lib/Makefile.dep: Datei oder Verzeichnis nicht gefunden =====waves=======3d================== Remaking lib/Makefile.dep =====waves=======3d====debug=====MT== functions.cc source/functions.cc:85: warning: unused parameter ‘p’ source/functions.cc: In instantiation of ‘void RelativeVelocity<dim>::vector_value(const Point<dim>&, Vector<double>&) const [with int dim = 3]’: source/functions.cc:223: instantiated from here source/functions.cc:190: warning: unused parameter ‘p’ =====waves=======3d====debug=====MT== input.cc source/input.cc: In instantiation of ‘double Input<dim>::mikro_height_func(double, double, double) [with int dim = 3]’: source/input.cc:225: instantiated from here source/input.cc:26: warning: unused parameter ‘x’ source/input.cc:26: warning: unused parameter ‘y’ source/input.cc:26: warning: unused parameter ‘z’ source/input.cc: In instantiation of ‘double Input<dim>::mikro_height(double, double, double) [with int dim = 3]’: source/input.cc:225: instantiated from here source/input.cc:41: warning: unused parameter ‘z’ =====waves=======3d====debug=====MT== input_werkzeug.cc source/input_werkzeug.cc: In instantiation of ‘double InputWerkzeug<dim>::mikro_height_func(double, double, double) [with int dim = 3]’: source/input_werkzeug.cc:238: instantiated from here source/input_werkzeug.cc:26: warning: unused parameter ‘x’ source/input_werkzeug.cc:26: warning: unused parameter ‘y’ source/input_werkzeug.cc:26: warning: unused parameter ‘z’ source/input_werkzeug.cc: In instantiation of ‘double InputWerkzeug<dim>::mikro_height(double, double, double) [with int dim = 3]’: source/input_werkzeug.cc:238: instantiated from here source/input_werkzeug.cc:54: warning: unused parameter ‘z’ =====waves=======3d====debug=====MT== my_assembler.cc source/../include/my_assembler.h: In constructor ‘MyAssembler<dim>::MyAssembler(DoFHandler<dim>&, FESystem<dim>&, SparsityPattern&, std::vector<double, std::allocator<double> >, std::vector<PointHistory<dim>, std::allocator<PointHistory<dim> > >, double, bool) [with int dim = 3]’: source/my_assembler.cc:1192: instantiated from here source/../include/my_assembler.h:39: warning: ‘MyAssembler<3>::materialpara_liste’ will be initialized after source/../include/my_assembler.h:32: warning: ‘const double MyAssembler<3>::mu_G’ source/../include/my_assembler.h:51: warning: when initialized here source/../include/my_assembler.h:32: warning: ‘MyAssembler<3>::mu_G’ will be initialized after source/../include/my_assembler.h:30: warning: ‘const double MyAssembler<3>::mu_B’ source/../include/my_assembler.h:51: warning: when initialized here source/../include/my_assembler.h:31: warning: ‘MyAssembler<3>::kappa_G’ will be initialized after source/../include/my_assembler.h:29: warning: ‘const double MyAssembler<3>::kappa_B’ source/../include/my_assembler.h:51: warning: when initialized here source/../include/my_assembler.h:34: warning: ‘MyAssembler<3>::fliessgrenze_G’ will be initialized after source/../include/my_assembler.h:33: warning: ‘const double MyAssembler<3>::fliessgrenze_B’ source/../include/my_assembler.h:51: warning: when initialized here source/my_assembler.cc: At global scope: source/my_assembler.cc: In instantiation of ‘void MyAssembler<dim>::compute_nl_term(const Vector<double>&, const Vector<double>&, Vector<double>&, const typename DoFHandler<dim>::active_cell_iterator&, const typename DoFHandler<dim>::active_cell_iterator&) [with int dim = 3]’: source/my_assembler.cc:1192: instantiated from here source/my_assembler.cc:47: warning: unused parameter ‘old_data’ source/my_assembler.cc: In instantiation of ‘void MyAssembler<dim>::compute_nl_matrix(const Vector<double>&, const Vector<double>&, SparseMatrix<double>&, const typename DoFHandler<dim>::active_cell_iterator&, const typename DoFHandler<dim>::active_cell_iterator&) [with int dim = 3]’: source/my_assembler.cc:1192: instantiated from here source/my_assembler.cc:208: warning: unused parameter ‘old_data’ source/my_assembler.cc: In instantiation of ‘void MyAssembler<dim>::update_quadrature_point_history(Vector<double>&, std::vector<PointHistory<dim>, std::allocator<PointHistory<dim> > >, Vector<double>&, SymmetricTensor<2, dim>&, SymmetricTensor<2, dim>&) [with int dim = 3]’: source/my_assembler.cc:1192: instantiated from here source/my_assembler.cc:608: warning: unused parameter ‘quadrature_point_history’ source/my_assembler.cc: In instantiation of ‘void MyAssembler<dim>::assemble_elast_system(Vector<double>&, Vector<double>&, SparseMatrix<double>&, const typename DoFHandler<dim>::active_cell_iterator&, const typename DoFHandler<dim>::active_cell_iterator&) [with int dim = 3]’: source/my_assembler.cc:1192: instantiated from here source/my_assembler.cc:797: warning: unused parameter ‘elast_solution’ =====waves=======3d====debug=====MT== my_solver.cc source/../include/my_solver.h: In constructor ‘MySolver<dim>::MySolver(SolverControl&, DoFHandler<dim>&, const Vector<double>&, Vector<double>&, SparsityPattern&, double) [with int dim = 3]’: source/my_solver.cc:347: instantiated from here source/../include/my_solver.h:18: warning: ‘MySolver<3>::reduction_control’ will be initialized after source/../include/my_solver.h:12: warning: ‘const Vector<double> MySolver<3>::complete_displacement’ source/../include/my_solver.h:29: warning: when initialized here source/my_solver.cc: In member function ‘void MySolver<dim>::solve_SSOR_2(Vector<double>&, const SparseMatrix<double>&, const Vector<double>&) [with int dim = 3]’: source/my_solver.cc:347: instantiated from here source/my_solver.cc:73: warning: unused variable ‘stop’ =====waves=======3d====debug=====MT== output.cc source/output.cc: In member function ‘void Output<dim>::save_gmv(Vector<double>, Vector<double>, const char*) const [with int dim = 3]’: source/output.cc:397: instantiated from here source/output.cc:72: warning: unused variable ‘cnt’ source/output.cc: In member function ‘void Output<dim>::output_fk_wk(double&, double&, double&, double&, Vector<double>, Vector<double>, Vector<double>, double, double) [with int dim = 3]’: source/output.cc:397: instantiated from here source/output.cc:283: warning: unused variable ‘index_y’ source/output.cc:397: instantiated from here source/output.cc:308: warning: unused variable ‘index_x’ source/output.cc:309: warning: unused variable ‘index_y’ source/output.cc:397: instantiated from here source/output.cc:341: warning: unused variable ‘index_x’ source/output.cc:342: warning: unused variable ‘index_y’ source/output.cc: At global scope: source/output.cc: In instantiation of ‘void Output<dim>::output_fk_wk(double&, double&, double&, double&, Vector<double>, Vector<double>, Vector<double>, double, double) [with int dim = 3]’: source/output.cc:397: instantiated from here source/output.cc:253: warning: unused parameter ‘MUS_Flaeche’ =====waves=======3d====debug=====MT== prandtl_reuss_problem.cc source/../include/../include/parameter.h: In constructor ‘Daten::Daten(char*)’: source/../include/../include/parameter.h:85: warning: format ‘%s’ expects type ‘char*’, but argument 3 has type ‘char (*)[1000]’ source/../include/../include/parameter.h:86: warning: format ‘%s’ expects type ‘char*’, but argument 3 has type ‘char (*)[1000]’ source/prandtl_reuss_problem.cc: In member function ‘void PrandtlReussProblem<dim>::run() [with int dim = 3]’: source/prandtl_reuss_problem.cc:1294: instantiated from here source/prandtl_reuss_problem.cc:1001: warning: deprecated conversion from string constant to ‘char*’' source/prandtl_reuss_problem.cc: At global scope: source/prandtl_reuss_problem.cc: In instantiation of ‘void PrandtlReussProblem<dim>::solve_SQP(double, Vector<double>) [with int dim = 3]’: source/prandtl_reuss_problem.cc:1300: instantiated from here source/prandtl_reuss_problem.cc:342: warning: unused parameter ‘surface_vector’ source/../include/../include/my_assembler.h: In constructor ‘MyAssembler<dim>::MyAssembler(DoFHandler<dim>&, FESystem<dim>&, SparsityPattern&, std::vector<double, std::allocator<double> >, std::vector<PointHistory<dim>, std::allocator<PointHistory<dim> > >, double, bool) [with int dim = 3]’: source/prandtl_reuss_problem.cc:1018: instantiated from ‘void PrandtlReussProblem<dim>::run() [with int dim = 3]’ source/prandtl_reuss_problem.cc:1294: instantiated from here source/../include/../include/my_assembler.h:39: warning: ‘MyAssembler<3>::materialpara_liste’ will be initialized after source/../include/../include/my_assembler.h:32: warning: ‘const double MyAssembler<3>::mu_G’ source/../include/../include/my_assembler.h:51: warning: when initialized here source/../include/../include/my_assembler.h:32: warning: ‘MyAssembler<3>::mu_G’ will be initialized after source/../include/../include/my_assembler.h:30: warning: ‘const double MyAssembler<3>::mu_B’ source/../include/../include/my_assembler.h:51: warning: when initialized here source/../include/../include/my_assembler.h:31: warning: ‘MyAssembler<3>::kappa_G’ will be initialized after source/../include/../include/my_assembler.h:29: warning: ‘const double MyAssembler<3>::kappa_B’ source/../include/../include/my_assembler.h:51: warning: when initialized here source/../include/../include/my_assembler.h:34: warning: ‘MyAssembler<3>::fliessgrenze_G’ will be initialized after source/../include/../include/my_assembler.h:33: warning: ‘const double MyAssembler<3>::fliessgrenze_B’ source/../include/../include/my_assembler.h:51: warning: when initialized here source/../include/my_solver.h: In constructor ‘MySolver<dim>::MySolver(SolverControl&, DoFHandler<dim>&, const Vector<double>&, Vector<double>&, SparsityPattern&, double) [with int dim = 3]’: source/prandtl_reuss_problem.cc:364: instantiated from ‘void PrandtlReussProblem<dim>::solve_SQP(double, Vector<double>) [with int dim = 3]’ source/prandtl_reuss_problem.cc:1300: instantiated from here source/../include/my_solver.h:18: warning: ‘MySolver<3>::reduction_control’ will be initialized after source/../include/my_solver.h:12: warning: ‘const Vector<double> MySolver<3>::complete_displacement’ source/../include/my_solver.h:29: warning: when initialized here =====waves=======3d====debug=====MT== SignoriniRotatingSolver2.cc =====waves=======3d==============MT== Linking Elasto-Plast-3dDa erscheinen noch einige Warnungen aus anderen Klassen. Bei denen ich aber nicht sehe wie sie schaden könnten und vor allem nicht an dieser Stelle.
Wie könnte ich denn am einfachsten die Gültigkeit von Iteratoren abfragen?
Danke schonmal vorab für eure Antworten?