KratosMultiphysics
KRATOS Multiphysics (Kratos) is a framework for building parallel, multi-disciplinary simulation software, aiming at modularity, extensibility, and high performance. Kratos is written in C++, and counts with an extensive Python interface.
trilinos_space.h
Go to the documentation of this file.
1 // | / |
2 // ' / __| _` | __| _ \ __|
3 // . \ | ( | | ( |\__ `
4 // _|\_\_| \__,_|\__|\___/ ____/
5 // Multi-Physics
6 //
7 // License: BSD License
8 // Kratos default license: kratos/license.txt
9 //
10 // Main authors: Riccardo Rossi
11 // Collaborator: Vicente Mataix Ferrandiz
12 //
13 
14 #pragma once
15 
16 // System includes
17 
18 // External includes
19 
20 /* Trilinos includes */
21 #include <Epetra_Import.h>
22 #include <Epetra_MpiComm.h>
23 #include <Epetra_Map.h>
24 #include <Epetra_Vector.h>
25 #include <Epetra_FEVector.h>
26 #include <Epetra_FECrsMatrix.h>
27 #include <Epetra_IntSerialDenseVector.h>
28 #include <Epetra_SerialDenseMatrix.h>
29 #include <Epetra_SerialDenseVector.h>
30 #include <EpetraExt_CrsMatrixIn.h>
31 #include <EpetraExt_VectorIn.h>
32 #include <EpetraExt_RowMatrixOut.h>
33 #include <EpetraExt_MultiVectorOut.h>
34 #include <EpetraExt_MatrixMatrix.h>
35 
36 // Project includes
38 #include "spaces/ublas_space.h"
42 
43 namespace Kratos
44 {
45 
48 
52 
56 
60 
64 
73 template<class TMatrixType, class TVectorType>
75 {
76 public:
79 
82 
84  using DataType = double;
85 
87  using MatrixType = TMatrixType;
88 
90  using VectorType = TVectorType;
91 
93  using IndexType = std::size_t;
94 
96  using SizeType = std::size_t;
97 
101 
105 
109 
112  {
113  }
114 
116  virtual ~TrilinosSpace()
117  {
118  }
119 
123 
127 
133  {
134  return MatrixPointerType(nullptr);
135  }
136 
142  {
143  return VectorPointerType(nullptr);
144  }
145 
151  static MatrixPointerType CreateEmptyMatrixPointer(Epetra_MpiComm& rComm)
152  {
153  const int global_elems = 0;
154  Epetra_Map Map(global_elems, 0, rComm);
155  return MatrixPointerType(new TMatrixType(::Copy, Map, 0));
156  }
157 
163  static VectorPointerType CreateEmptyVectorPointer(Epetra_MpiComm& rComm)
164  {
165  const int global_elems = 0;
166  Epetra_Map Map(global_elems, 0, rComm);
167  return VectorPointerType(new TVectorType(Map));
168  }
169 
175  static IndexType Size(const VectorType& rV)
176  {
177  const int size = rV.GlobalLength();
178  return size;
179  }
180 
186  static IndexType Size1(MatrixType const& rM)
187  {
188  const int size1 = rM.NumGlobalRows();
189  return size1;
190  }
191 
197  static IndexType Size2(MatrixType const& rM)
198  {
199  const int size1 = rM.NumGlobalCols();
200  return size1;
201  }
202 
211  static void GetColumn(
212  const unsigned int j,
213  const MatrixType& rM,
214  VectorType& rX
215  )
216  {
217  KRATOS_ERROR << "GetColumn method is not currently implemented" << std::endl;
218  }
219 
226  static void Copy(
227  const MatrixType& rX,
228  MatrixType& rY
229  )
230  {
231  rY = rX;
232  }
233 
240  static void Copy(
241  const VectorType& rX,
242  VectorType& rY
243  )
244  {
245  rY = rX;
246  }
247 
254  static double Dot(
255  const VectorType& rX,
256  const VectorType& rY
257  )
258  {
259  double value;
260  const int sucess = rY.Dot(rX, &value); //it is prepared to handle vectors with multiple components
261  KRATOS_ERROR_IF_NOT(sucess == 0) << "Error computing dot product" << std::endl;
262  return value;
263  }
264 
270  static double Max(const VectorType& rX)
271  {
272  double value;
273  const int sucess = rX.MaxValue(&value); //it is prepared to handle vectors with multiple components
274  KRATOS_ERROR_IF_NOT(sucess == 0) << "Error computing maximum value" << std::endl;
275  return value;
276  }
277 
283  static double Min(const VectorType& rX)
284  {
285  double value;
286  const int sucess = rX.MinValue(&value); //it is prepared to handle vectors with multiple components
287  KRATOS_ERROR_IF_NOT(sucess == 0) << "Error computing minimum value" << std::endl;
288  return value;
289  }
290 
297  static double TwoNorm(const VectorType& rX)
298  {
299  double value;
300  const int sucess = rX.Norm2(&value); //it is prepared to handle vectors with multiple components
301  KRATOS_ERROR_IF_NOT(sucess == 0) << "Error computing norm" << std::endl;
302  return value;
303  }
304 
311  static double TwoNorm(const MatrixType& rA)
312  {
313  return rA.NormFrobenius();
314  }
315 
323  static void Mult(
324  const MatrixType& rA,
325  const VectorType& rX,
326  VectorType& rY
327  )
328  {
329  constexpr bool transpose_flag = false;
330  const int ierr = rA.Multiply(transpose_flag, rX, rY);
331  KRATOS_ERROR_IF(ierr != 0) << "Epetra multiplication failure " << ierr << std::endl;
332  }
333 
343  static void Mult(
344  const MatrixType& rA,
345  const MatrixType& rB,
346  MatrixType& rC,
347  const bool CallFillCompleteOnResult = true,
348  const bool KeepAllHardZeros = false
349  )
350  {
351  KRATOS_TRY
352 
353  constexpr bool transpose_flag = false;
354  const int ierr = EpetraExt::MatrixMatrix::Multiply(rA, transpose_flag, rB, transpose_flag, rC, CallFillCompleteOnResult, KeepAllHardZeros);
355  KRATOS_ERROR_IF(ierr != 0) << "Epetra multiplication failure. This may result if A or B are not already Filled, or if errors occur in putting values into C, etc. " << std::endl;
356 
357  KRATOS_CATCH("")
358  }
359 
367  static void TransposeMult(
368  const MatrixType& rA,
369  const VectorType& rX,
370  VectorType& rY
371  )
372  {
373  constexpr bool transpose_flag = true;
374  const int ierr = rA.Multiply(transpose_flag, rX, rY);
375  KRATOS_ERROR_IF(ierr != 0) << "Epetra multiplication failure " << ierr << std::endl;
376  }
377 
388  static void TransposeMult(
389  const MatrixType& rA,
390  const MatrixType& rB,
391  MatrixType& rC,
392  const std::pair<bool, bool> TransposeFlag = {false, false},
393  const bool CallFillCompleteOnResult = true,
394  const bool KeepAllHardZeros = false
395  )
396  {
397  KRATOS_TRY
398 
399  const int ierr = EpetraExt::MatrixMatrix::Multiply(rA, TransposeFlag.first, rB, TransposeFlag.second, rC, CallFillCompleteOnResult, KeepAllHardZeros);
400  KRATOS_ERROR_IF(ierr != 0) << "Epetra multiplication failure. This may result if A or B are not already Filled, or if errors occur in putting values into C, etc. " << std::endl;
401 
402  KRATOS_CATCH("")
403  }
404 
414  static void BtDBProductOperation(
415  MatrixType& rA,
416  const MatrixType& rD,
417  const MatrixType& rB,
418  const bool CallFillCompleteOnResult = true,
419  const bool KeepAllHardZeros = false,
420  const bool EnforceInitialGraph = false
421  )
422  {
423  // Define first auxiliary matrix
424  std::vector<int> NumNz;
425  MatrixType aux_1(::Copy, rA.RowMap(), NumNz.data());
426 
427  // First multiplication
428  TransposeMult(rB, rD, aux_1, {true, false}, CallFillCompleteOnResult, KeepAllHardZeros);
429 
430  // If we enforce the initial connectivity
431  if (EnforceInitialGraph) {
432  // Second multiplication
433  MatrixType aux_2(::Copy, rA.RowMap(), NumNz.data());
434  Mult(aux_1, rB, aux_2, CallFillCompleteOnResult, KeepAllHardZeros);
435 
436  // Create an Epetra_Matrix
437  MatrixType* aux_3 = new MatrixType(::Copy, CombineMatricesGraphs(rA, aux_2));
438 
439  // Copy values
440  CopyMatrixValues(*aux_3, aux_2);
441 
442  // Doing a swap
443  std::swap(rA, *aux_3);
444 
445  // Delete the new matrix
446  delete aux_3;
447  } else { // A new matrix
448  // Already existing matrix
449  if (rA.NumGlobalNonzeros() > 0) {
450  // Create an Epetra_Matrix
451  MatrixType* aux_2 = new MatrixType(::Copy, rB.RowMap(), NumNz.data());
452 
453  // Second multiplication
454  Mult(aux_1, rB, *aux_2, CallFillCompleteOnResult, KeepAllHardZeros);
455 
456  // Doing a swap
457  std::swap(rA, *aux_2);
458 
459  // Delete the new matrix
460  delete aux_2;
461  } else { // Empty matrix
462  // Second multiplication
463  Mult(aux_1, rB, rA, CallFillCompleteOnResult, KeepAllHardZeros);
464  }
465  }
466  }
467 
477  static void BDBtProductOperation(
478  MatrixType& rA,
479  const MatrixType& rD,
480  const MatrixType& rB,
481  const bool CallFillCompleteOnResult = true,
482  const bool KeepAllHardZeros = false,
483  const bool EnforceInitialGraph = false
484  )
485  {
486  // Define first auxiliary matrix
487  std::vector<int> NumNz;
488  MatrixType aux_1(::Copy, rA.RowMap(), NumNz.data());
489 
490  // First multiplication
491  Mult(rB, rD, aux_1, CallFillCompleteOnResult, KeepAllHardZeros);
492 
493  // If we enforce the initial connectivity
494  if (EnforceInitialGraph) {
495  // Second multiplication
496  MatrixType aux_2(::Copy, rA.RowMap(), NumNz.data());
497  TransposeMult(aux_1, rB, aux_2, {false, true}, CallFillCompleteOnResult, KeepAllHardZeros);
498 
499  // Create an Epetra_Matrix
500  MatrixType* aux_3 = new MatrixType(::Copy, CombineMatricesGraphs(rA, aux_2));
501 
502  // Copy values
503  CopyMatrixValues(*aux_3, aux_2);
504 
505  // Doing a swap
506  std::swap(rA, *aux_3);
507 
508  // Delete the new matrix
509  delete aux_3;
510  } else { // A new matrix
511  // Already existing matrix
512  if (rA.NumGlobalNonzeros() > 0) {
513  // Create an Epetra_Matrix
514  MatrixType* aux_2 = new MatrixType(::Copy, rA.RowMap(), NumNz.data());
515 
516  // Second multiplication
517  TransposeMult(aux_1, rB, *aux_2, {false, true}, CallFillCompleteOnResult, KeepAllHardZeros);
518 
519  // Doing a swap
520  std::swap(rA, *aux_2);
521 
522  // Delete the new matrix
523  delete aux_2;
524  } else { // Empty matrix
525  // Second multiplication
526  TransposeMult(aux_1, rB, rA, {false, true}, CallFillCompleteOnResult, KeepAllHardZeros);
527  }
528  }
529  }
530 
538  static void InplaceMult(
539  VectorType& rX,
540  const double A
541  )
542  {
543  if (A != 1.00) {
544  const int ierr = rX.Scale(A);
545  KRATOS_ERROR_IF(ierr != 0) << "Epetra scaling failure " << ierr << std::endl;
546  }
547  }
548 
558  static void Assign(
559  VectorType& rX,
560  const double A,
561  const VectorType& rY
562  )
563  {
564  if (A != 1.00) {
565  const int ierr = rX.Scale(A, rY); //not sure
566  KRATOS_ERROR_IF(ierr != 0) << "Epetra assign failure " << ierr << std::endl;
567  } else {
568  rX = rY;
569  }
570  }
571 
581  static void UnaliasedAdd(
582  VectorType& rX,
583  const double A,
584  const VectorType& rY
585  )
586  {
587  const int ierr = rX.Update(A, rY, 1.0);
588  KRATOS_ERROR_IF(ierr != 0) << "Epetra unaliased add failure " << ierr << std::endl;
589  }
590 
600  static void ScaleAndAdd(
601  const double A,
602  const VectorType& rX,
603  const double B,
604  const VectorType& rY,
605  VectorType& rZ
606  )
607  {
608  const int ierr = rZ.Update(A, rX, B, rY, 0.0);
609  KRATOS_ERROR_IF(ierr != 0) << "Epetra scale and add failure " << ierr << std::endl;
610  }
611 
620  static void ScaleAndAdd(
621  const double A,
622  const VectorType& rX,
623  const double B,
624  VectorType& rY
625  )
626  {
627  const int ierr = rY.Update(A, rX, B);
628  KRATOS_ERROR_IF(ierr != 0) << "Epetra scale and add failure " << ierr << std::endl;
629  }
630 
637  static void SetValue(
638  VectorType& rX,
639  IndexType i,
640  const double value
641  )
642  {
643  Epetra_IntSerialDenseVector indices(1);
644  Epetra_SerialDenseVector values(1);
645  indices[0] = i;
646  values[0] = value;
647 
648  int ierr = rX.ReplaceGlobalValues(indices, values);
649  KRATOS_ERROR_IF(ierr != 0) << "Epetra failure found" << std::endl;
650 
651  ierr = rX.GlobalAssemble(Insert,true); //Epetra_CombineMode mode=Add);
652  KRATOS_ERROR_IF(ierr < 0) << "Epetra failure when attempting to insert value in function SetValue" << std::endl;
653  }
654 
661  static void Set(
662  VectorType& rX,
663  const DataType A
664  )
665  {
666  const int ierr = rX.PutScalar(A);
667  KRATOS_ERROR_IF(ierr != 0) << "Epetra set failure " << ierr << std::endl;
668  }
669 
676  static void Resize(
677  MatrixType& rA,
678  const SizeType m,
679  const SizeType n
680  )
681  {
682  KRATOS_ERROR << "Resize is not defined for Trilinos Sparse Matrix" << std::endl;
683  }
684 
690  static void Resize(
691  VectorType& rX,
692  const SizeType n
693  )
694  {
695  KRATOS_ERROR << "Resize is not defined for a reference to Trilinos Vector - need to use the version passing a Pointer" << std::endl;
696  }
697 
703  static void Resize(
704  VectorPointerType& pX,
705  const SizeType n
706  )
707  {
708  //KRATOS_ERROR_IF(pX != NULL) << "Trying to resize a null pointer" << std::endl;
709  int global_elems = n;
710  Epetra_Map Map(global_elems, 0, pX->Comm());
711  VectorPointerType pNewEmptyX = Kratos::make_shared<VectorType>(Map);
712  pX.swap(pNewEmptyX);
713  }
714 
719  static void Clear(MatrixPointerType& pA)
720  {
721  if(pA != NULL) {
722  int global_elems = 0;
723  Epetra_Map Map(global_elems, 0, pA->Comm());
724  MatrixPointerType pNewEmptyA = MatrixPointerType(new TMatrixType(::Copy, Map, 0));
725  pA.swap(pNewEmptyA);
726  }
727  }
728 
733  static void Clear(VectorPointerType& pX)
734  {
735  if(pX != NULL) {
736  int global_elems = 0;
737  Epetra_Map Map(global_elems, 0, pX->Comm());
738  VectorPointerType pNewEmptyX = VectorPointerType(new VectorType(Map));
739  pX.swap(pNewEmptyX);
740  }
741  }
742 
747  inline static void SetToZero(MatrixType& rA)
748  {
749  const int ierr = rA.PutScalar(0.0);
750  KRATOS_ERROR_IF(ierr != 0) << "Epetra set to zero failure " << ierr << std::endl;
751  }
752 
757  inline static void SetToZero(VectorType& rX)
758  {
759  const int ierr = rX.PutScalar(0.0);
760  KRATOS_ERROR_IF(ierr != 0) << "Epetra set to zero failure " << ierr << std::endl;
761  }
762 
764  // template<class TOtherMatrixType, class TEquationIdVectorType>
765 
772  inline static void AssembleLHS(
773  MatrixType& rA,
774  const Matrix& rLHSContribution,
775  const std::vector<std::size_t>& rEquationId
776  )
777  {
778  const unsigned int system_size = Size1(rA);
779 
780  // Count active indices
781  unsigned int active_indices = 0;
782  for (unsigned int i = 0; i < rEquationId.size(); i++)
783  if (rEquationId[i] < system_size)
784  ++active_indices;
785 
786  if (active_indices > 0) {
787  // Size Epetra vectors
788  Epetra_IntSerialDenseVector indices(active_indices);
789  Epetra_SerialDenseMatrix values(active_indices, active_indices);
790 
791  // Fill epetra vectors
792  unsigned int loc_i = 0;
793  for (unsigned int i = 0; i < rEquationId.size(); i++) {
794  if (rEquationId[i] < system_size) {
795  indices[loc_i] = rEquationId[i];
796 
797  unsigned int loc_j = 0;
798  for (unsigned int j = 0; j < rEquationId.size(); j++) {
799  if (rEquationId[j] < system_size) {
800  values(loc_i, loc_j) = rLHSContribution(i, j);
801  ++loc_j;
802  }
803  }
804  ++loc_i;
805  }
806  }
807 
808  const int ierr = rA.SumIntoGlobalValues(indices, values);
809  KRATOS_ERROR_IF(ierr != 0) << "Epetra failure found" << std::endl;
810  }
811  }
812 
813  //***********************************************************************
815  // template<class TOtherVectorType, class TEquationIdVectorType>
816 
823  inline static void AssembleRHS(
824  VectorType& rb,
825  const Vector& rRHSContribution,
826  const std::vector<std::size_t>& rEquationId
827  )
828  {
829  const unsigned int system_size = Size(rb);
830 
831  // Count active indices
832  unsigned int active_indices = 0;
833  for (unsigned int i = 0; i < rEquationId.size(); i++)
834  if (rEquationId[i] < system_size)
835  ++active_indices;
836 
837  if (active_indices > 0) {
838  // Size Epetra vectors
839  Epetra_IntSerialDenseVector indices(active_indices);
840  Epetra_SerialDenseVector values(active_indices);
841 
842  // Fill epetra vectors
843  unsigned int loc_i = 0;
844  for (unsigned int i = 0; i < rEquationId.size(); i++) {
845  if (rEquationId[i] < system_size) {
846  indices[loc_i] = rEquationId[i];
847  values[loc_i] = rRHSContribution[i];
848  ++loc_i;
849  }
850  }
851 
852  const int ierr = rb.SumIntoGlobalValues(indices, values);
853  KRATOS_ERROR_IF(ierr != 0) << "Epetra failure found" << std::endl;
854  }
855  }
856 
861  inline static constexpr bool IsDistributed()
862  {
863  return true;
864  }
865 
872  inline static double GetValue(
873  const VectorType& rX,
874  const std::size_t I
875  )
876  {
877  // index must be local to this proc
878  KRATOS_ERROR_IF_NOT(rX.Map().MyGID(static_cast<int>(I))) << " non-local id: " << I << "." << std::endl;
879  // Epetra_MultiVector::operator[] is used here to get the pointer to
880  // the zeroth (only) local vector.
881  return rX[0][rX.Map().LID(static_cast<int>(I))];
882  }
883 
890  static void GatherValues(
891  const VectorType& rX,
892  const std::vector<int>& IndexArray,
893  double* pValues
894  )
895  {
896  KRATOS_TRY
897  double tot_size = IndexArray.size();
898 
899  //defining a map as needed
900  Epetra_Map dof_update_map(-1, tot_size, &(*(IndexArray.begin())), 0, rX.Comm());
901 
902  //defining the importer class
903  Epetra_Import importer(dof_update_map, rX.Map());
904 
905  //defining a temporary vector to gather all of the values needed
906  Epetra_Vector temp(importer.TargetMap());
907 
908  //importing in the new temp vector the values
909  int ierr = temp.Import(rX, importer, Insert);
910  if(ierr != 0) KRATOS_THROW_ERROR(std::logic_error,"Epetra failure found","");
911 
912  temp.ExtractCopy(&pValues);
913 
914  rX.Comm().Barrier();
915  KRATOS_CATCH("")
916  }
917 
925  const std::string FileName,
926  Epetra_MpiComm& rComm
927  )
928  {
929  KRATOS_TRY
930 
931  Epetra_CrsMatrix* pp = nullptr;
932 
933  int error_code = EpetraExt::MatrixMarketFileToCrsMatrix(FileName.c_str(), rComm, pp);
934 
935  KRATOS_ERROR_IF(error_code != 0) << "Eerror thrown while reading Matrix Market file "<<FileName<< " error code is : " << error_code;
936 
937  rComm.Barrier();
938 
939  const Epetra_CrsGraph& rGraph = pp->Graph();
940  MatrixPointerType paux = Kratos::make_shared<Epetra_FECrsMatrix>( ::Copy, rGraph, false );
941 
942  IndexType NumMyRows = rGraph.RowMap().NumMyElements();
943 
944  int* MyGlobalElements = new int[NumMyRows];
945  rGraph.RowMap().MyGlobalElements(MyGlobalElements);
946 
947  for(IndexType i = 0; i < NumMyRows; ++i) {
948 // std::cout << pA->Comm().MyPID() << " : I=" << i << std::endl;
949  IndexType GlobalRow = MyGlobalElements[i];
950 
951  int NumEntries;
952  std::size_t Length = pp->NumGlobalEntries(GlobalRow); // length of Values and Indices
953 
954  double* Values = new double[Length]; // extracted values for this row
955  int* Indices = new int[Length]; // extracted global column indices for the corresponding values
956 
957  error_code = pp->ExtractGlobalRowCopy(GlobalRow, Length, NumEntries, Values, Indices);
958 
959  KRATOS_ERROR_IF(error_code != 0) << "Error thrown in ExtractGlobalRowCopy : " << error_code;
960 
961  error_code = paux->ReplaceGlobalValues(GlobalRow, Length, Values, Indices);
962 
963  KRATOS_ERROR_IF(error_code != 0) << "Error thrown in ReplaceGlobalValues : " << error_code;
964 
965  delete [] Values;
966  delete [] Indices;
967  }
968 
969  paux->GlobalAssemble();
970 
971  delete [] MyGlobalElements;
972  delete pp;
973 
974  return paux;
975  KRATOS_CATCH("");
976  }
977 
985  const std::string& rFileName,
986  Epetra_MpiComm& rComm,
987  const int N
988  )
989  {
990  KRATOS_TRY
991 
992  Epetra_Map my_map(N, 0, rComm);
993  Epetra_Vector* pv = nullptr;
994 
995  int error_code = EpetraExt::MatrixMarketFileToVector(rFileName.c_str(), my_map, pv);
996 
997  KRATOS_ERROR_IF(error_code != 0) << "error thrown while reading Matrix Market Vector file " << rFileName << " error code is: " << error_code;
998 
999  rComm.Barrier();
1000 
1001  IndexType num_my_rows = my_map.NumMyElements();
1002  std::vector<int> gids(num_my_rows);
1003  my_map.MyGlobalElements(gids.data());
1004 
1005  std::vector<double> values(num_my_rows);
1006  pv->ExtractCopy(values.data());
1007 
1008  VectorPointerType final_vector = Kratos::make_shared<VectorType>(my_map);
1009  int ierr = final_vector->ReplaceGlobalValues(gids.size(),gids.data(), values.data());
1010  KRATOS_ERROR_IF(ierr != 0) << "Epetra failure found with code ierr = " << ierr << std::endl;
1011 
1012  final_vector->GlobalAssemble();
1013 
1014  delete pv;
1015  return final_vector;
1016  KRATOS_CATCH("");
1017  }
1018 
1024  static Epetra_CrsGraph CombineMatricesGraphs(
1025  const MatrixType& rA,
1026  const MatrixType& rB
1027  )
1028  {
1029  // Row maps must be the same
1030  KRATOS_ERROR_IF_NOT(rA.RowMap().SameAs(rB.RowMap())) << "Row maps are not compatible" << std::endl;
1031 
1032  // Getting the graphs
1033  const auto& r_graph_a = rA.Graph();
1034  const auto& r_graph_b = rB.Graph();
1035 
1036  // Assuming local indexes
1037  KRATOS_ERROR_IF_NOT(r_graph_a.IndicesAreLocal() && r_graph_b.IndicesAreLocal()) << "Graphs indexes must be local" << std::endl;
1038 
1039  // Some definitions
1040  int i, j, ierr;
1041  int num_entries; // Number of non-zero entries
1042  int* cols; // Column indices of row non-zero values
1043  std::unordered_set<int> combined_indexes;
1044  const bool same_col_map = rA.ColMap().SameAs(rB.ColMap());
1045  Epetra_CrsGraph graph = same_col_map ? Epetra_CrsGraph(::Copy, rA.RowMap(), rA.ColMap(), 1000) : Epetra_CrsGraph(::Copy, rA.RowMap(), 1000);
1046 
1047  // Same column map. Local indices, simpler and faster
1048  if (same_col_map) {
1049  for (i = 0; i < r_graph_a.NumMyRows(); i++) {
1050  // First graph
1051  ierr = r_graph_a.ExtractMyRowView(i, num_entries, cols);
1052  KRATOS_ERROR_IF(ierr != 0) << "Epetra failure found extracting indices (I) with code ierr = " << ierr << std::endl;
1053  for (j = 0; j < num_entries; j++) {
1054  combined_indexes.insert(cols[j]);
1055  }
1056  // Second graph
1057  ierr = r_graph_b.ExtractMyRowView(i, num_entries, cols);
1058  KRATOS_ERROR_IF(ierr != 0) << "Epetra failure found extracting indices (II) with code ierr = " << ierr << std::endl;
1059  for (j = 0; j < num_entries; j++) {
1060  combined_indexes.insert(cols[j]);
1061  }
1062  // Vector equivalent
1063  std::vector<int> combined_indexes_vector(combined_indexes.begin(), combined_indexes.end());
1064  num_entries = combined_indexes_vector.size();
1065  // Adding to graph
1066  ierr = graph.InsertMyIndices(i, num_entries, combined_indexes_vector.data());
1067  KRATOS_ERROR_IF(ierr != 0) << "Epetra failure inserting indices with code ierr = " << ierr << std::endl;
1068  // Clear set
1069  combined_indexes.clear();
1070  }
1071  } else { // Different column map, global indices
1072  for (i = 0; i < r_graph_a.NumMyRows(); i++) {
1073  const int global_row_index = r_graph_a.GRID(i);
1074  // First graph
1075  ierr = r_graph_a.ExtractMyRowView(i, num_entries, cols);
1076  KRATOS_ERROR_IF(ierr != 0) << "Epetra failure found extracting indices (I) with code ierr = " << ierr << std::endl;
1077  for (j = 0; j < num_entries; j++) {
1078  combined_indexes.insert(r_graph_a.GCID(cols[j]));
1079  }
1080  // Vector equivalent
1081  std::vector<int> combined_indexes_vector(combined_indexes.begin(), combined_indexes.end());
1082  num_entries = combined_indexes_vector.size();
1083  // Adding to graph
1084  ierr = graph.InsertGlobalIndices(global_row_index, num_entries, combined_indexes_vector.data());
1085  KRATOS_ERROR_IF(ierr != 0) << "Epetra failure inserting indices with code ierr = " << ierr << std::endl;
1086  // Clear set
1087  combined_indexes.clear();
1088  }
1089  for (i = 0; i < r_graph_b.NumMyRows(); i++) {
1090  const int global_row_index = r_graph_b.GRID(i);
1091  // Second graph
1092  ierr = r_graph_b.ExtractMyRowView(i, num_entries, cols);
1093  KRATOS_ERROR_IF(ierr != 0) << "Epetra failure found extracting indices (II) with code ierr = " << ierr << std::endl;
1094  for (j = 0; j < num_entries; j++) {
1095  combined_indexes.insert(r_graph_b.GCID(cols[j]));
1096  }
1097  // Vector equivalent
1098  std::vector<int> combined_indexes_vector(combined_indexes.begin(), combined_indexes.end());
1099  num_entries = combined_indexes_vector.size();
1100  // Adding to graph
1101  ierr = graph.InsertGlobalIndices(global_row_index, num_entries, combined_indexes_vector.data());
1102  KRATOS_ERROR_IF(ierr != 0) << "Epetra failure inserting indices with code ierr = " << ierr << std::endl;
1103  // Clear set
1104  combined_indexes.clear();
1105  }
1106  }
1107 
1108  // Finalizing graph construction
1109  ierr = graph.FillComplete();
1110  KRATOS_ERROR_IF(ierr < 0) << ": Epetra failure in Epetra_CrsGraph.FillComplete. Error code: " << ierr << std::endl;
1111 
1112  return graph;
1113  }
1114 
1121  static void CopyMatrixValues(
1122  MatrixType& rA,
1123  const MatrixType& rB
1124  )
1125  {
1126  // Cleaning destination matrix
1127  SetToZero(rA);
1128 
1129  // The current process id
1130  const int rank = rA.Comm().MyPID();
1131 
1132  // Row maps must be the same
1133  const bool same_col_map = rA.ColMap().SameAs(rB.ColMap());
1134 
1135  // Getting the graphs
1136  const auto& r_graph_b = rB.Graph();
1137 
1138  // Copy values from rB to intermediate
1139  int i, ierr;
1140  int num_entries; // Number of non-zero entries (rB matrix)
1141  double* vals; // Row non-zero values (rB matrix)
1142  int* cols; // Column indices of row non-zero values (rB matrix)
1143  if (same_col_map) {
1144  for (i = 0; i < rB.NumMyRows(); i++) {
1145  ierr = rB.ExtractMyRowView(i, num_entries, vals, cols);
1146  KRATOS_ERROR_IF(ierr != 0) << "Epetra failure found extracting values in local row " << i << " in rank " << rank << " with code ierr = " << ierr << std::endl;
1147  ierr = rA.ReplaceMyValues(i, num_entries, vals, cols);
1148  KRATOS_ERROR_IF(ierr != 0) << "Epetra failure found replacing values in local row " << i << " in rank " << rank << " with code ierr = " << ierr << std::endl;
1149  }
1150  } else {
1151  for (i = 0; i < rB.NumMyRows(); i++) {
1152  ierr = rB.ExtractMyRowView(i, num_entries, vals, cols);
1153  KRATOS_ERROR_IF(ierr != 0) << "Epetra failure found extracting values in local row " << i << " in rank " << rank << " with code ierr = " << ierr << std::endl;
1154  const int global_row_index = r_graph_b.GRID(i);
1155  for (int j = 0; j < num_entries; j++) {
1156  cols[j] = r_graph_b.GCID(cols[j]);
1157  }
1158  ierr = rA.ReplaceGlobalValues(global_row_index, num_entries, vals, cols);
1159  KRATOS_ERROR_IF(ierr != 0) << "Epetra failure found extracting values in global row " << global_row_index << " in rank " << rank << " with code ierr = " << ierr << std::endl;
1160  }
1161  }
1162  }
1163 
1174  const ProcessInfo& rProcessInfo,
1175  MatrixType& rA,
1176  VectorType& rb,
1177  const SCALING_DIAGONAL ScalingDiagonal = SCALING_DIAGONAL::NO_SCALING
1178  )
1179  {
1180  KRATOS_TRY
1181 
1182  // Define zero value tolerance
1183  const double zero_tolerance = std::numeric_limits<double>::epsilon();
1184 
1185  // The diagonal considered
1186  const double scale_factor = GetScaleNorm(rProcessInfo, rA, ScalingDiagonal);
1187 
1188  for (int i = 0; i < rA.NumMyRows(); i++) {
1189  int numEntries; // Number of non-zero entries
1190  double* vals; // Row non-zero values
1191  int* cols; // Column indices of row non-zero values
1192  rA.ExtractMyRowView(i, numEntries, vals, cols);
1193  const int row_gid = rA.RowMap().GID(i);
1194  bool empty = true;
1195  int j;
1196  for (j = 0; j < numEntries; j++) {
1197  const int col_gid = rA.ColMap().GID(cols[j]);
1198  // Check diagonal value
1199  if (col_gid == row_gid) {
1200  if(std::abs(vals[j]) > zero_tolerance) {
1201  empty = false;
1202  }
1203  break;
1204  }
1205  }
1206 
1207  // If diagonal empty assign scale factor
1208  if (empty) {
1209  vals[j] = scale_factor;
1210  rb[0][i] = 0.0;
1211  }
1212  }
1213 
1214  // Global assembly
1215  rb.GlobalAssemble();
1216  rA.GlobalAssemble();
1217 
1218  return scale_factor;
1219 
1220  KRATOS_CATCH("");
1221  }
1222 
1230  static double GetScaleNorm(
1231  const ProcessInfo& rProcessInfo,
1232  const MatrixType& rA,
1233  const SCALING_DIAGONAL ScalingDiagonal = SCALING_DIAGONAL::NO_SCALING
1234  )
1235  {
1236  KRATOS_TRY
1237 
1238  switch (ScalingDiagonal) {
1240  return 1.0;
1242  KRATOS_ERROR_IF_NOT(rProcessInfo.Has(BUILD_SCALE_FACTOR)) << "Scale factor not defined at process info" << std::endl;
1243  return rProcessInfo.GetValue(BUILD_SCALE_FACTOR);
1244  }
1246  return GetDiagonalNorm(rA)/static_cast<double>(Size1(rA));
1248  return GetMaxDiagonal(rA);
1249  default:
1250  return GetMaxDiagonal(rA);
1251  }
1252 
1253  KRATOS_CATCH("");
1254  }
1255 
1261  static double GetDiagonalNorm(const MatrixType& rA)
1262  {
1263  KRATOS_TRY
1264 
1265  Epetra_Vector diagonal(rA.RowMap());
1266  const int ierr = rA.ExtractDiagonalCopy(diagonal);
1267  KRATOS_ERROR_IF(ierr != 0) << "Epetra failure extracting diagonal " << ierr << std::endl;
1268 
1270 
1271  KRATOS_CATCH("");
1272  }
1273 
1279  static double GetAveragevalueDiagonal(const MatrixType& rA)
1280  {
1281  KRATOS_TRY
1282 
1283  return 0.5 * (GetMaxDiagonal(rA) + GetMinDiagonal(rA));
1284 
1285  KRATOS_CATCH("");
1286  }
1287 
1293  static double GetMaxDiagonal(const MatrixType& rA)
1294  {
1295  KRATOS_TRY
1296 
1297  Epetra_Vector diagonal(rA.RowMap());
1298  const int ierr = rA.ExtractDiagonalCopy(diagonal);
1299  KRATOS_ERROR_IF(ierr != 0) << "Epetra failure extracting diagonal " << ierr << std::endl;
1301 
1302  KRATOS_CATCH("");
1303  }
1304 
1310  static double GetMinDiagonal(const MatrixType& rA)
1311  {
1312  KRATOS_TRY
1313 
1314  Epetra_Vector diagonal(rA.RowMap());
1315  const int ierr = rA.ExtractDiagonalCopy(diagonal);
1316  KRATOS_ERROR_IF(ierr != 0) << "Epetra failure extracting diagonal " << ierr << std::endl;
1318 
1319  KRATOS_CATCH("");
1320  }
1321 
1327  static constexpr bool IsDistributedSpace()
1328  {
1329  return true;
1330  }
1331 
1335 
1339 
1343 
1348  virtual std::string Info() const
1349  {
1350  return "TrilinosSpace";
1351  }
1352 
1357  virtual void PrintInfo(std::ostream& rOStream) const
1358  {
1359  rOStream << "TrilinosSpace";
1360  }
1361 
1366  virtual void PrintData(std::ostream& rOStream) const
1367  {
1368  }
1369 
1377  template< class TOtherMatrixType >
1379  const char* pFileName,
1380  const TOtherMatrixType& rM,
1381  const bool Symmetric
1382  )
1383  {
1384  // the argument "Symmetric" does not have an effect for Trilinos => needed for compatibility with other Spaces
1385  KRATOS_TRY;
1386  return EpetraExt::RowMatrixToMatrixMarketFile(pFileName, rM); // Returns 0 if no error, -1 if any problems with file system.
1387  KRATOS_CATCH("");
1388  }
1389 
1396  template< class VectorType >
1398  const char* pFileName,
1399  const VectorType& rV
1400  )
1401  {
1402  KRATOS_TRY;
1403  return EpetraExt::MultiVectorToMatrixMarketFile(pFileName, rV);
1404  KRATOS_CATCH("");
1405  }
1406 
1412  {
1414  return tmp.Create();
1415  }
1416 
1418 private:
1421 
1423  TrilinosSpace & operator=(TrilinosSpace const& rOther);
1424 
1426  TrilinosSpace(TrilinosSpace const& rOther);
1427 
1429 }; // Class TrilinosSpace
1430 
1432 
1433 } // namespace Kratos.
bool Has(const Variable< TDataType > &rThisVariable) const
Checks if the data container has a value associated with a given variable.
Definition: data_value_container.h:382
TDataType & GetValue(const Variable< TDataType > &rThisVariable)
Gets the value associated with a given variable.
Definition: data_value_container.h:268
Utility class to update the values of degree of freedom (Dof) variables after solving the system.
Definition: dof_updater.h:40
ProcessInfo holds the current value of different solution parameters.
Definition: process_info.h:59
Utility class to update the values of degree of freedom (Dof) variables after solving the system.
Definition: trilinos_dof_updater.h:39
The space adapted for Trilinos vectors and matrices.
Definition: trilinos_space.h:75
static void BDBtProductOperation(MatrixType &rA, const MatrixType &rD, const MatrixType &rB, const bool CallFillCompleteOnResult=true, const bool KeepAllHardZeros=false, const bool EnforceInitialGraph=false)
Calculates the product operation BDB'.
Definition: trilinos_space.h:477
static void Clear(VectorPointerType &pX)
Clears a vector.
Definition: trilinos_space.h:733
static void SetToZero(VectorType &rX)
Sets a vector to zero.
Definition: trilinos_space.h:757
static void SetValue(VectorType &rX, IndexType i, const double value)
Sets a value in a vector.
Definition: trilinos_space.h:637
static void AssembleLHS(MatrixType &rA, const Matrix &rLHSContribution, const std::vector< std::size_t > &rEquationId)
TODO: creating the the calculating reaction version.
Definition: trilinos_space.h:772
static double GetValue(const VectorType &rX, const std::size_t I)
This function returns a value from a given vector according to a given index.
Definition: trilinos_space.h:872
static void Resize(VectorPointerType &pX, const SizeType n)
Resizes a vector.
Definition: trilinos_space.h:703
TVectorType VectorType
Definition of the vector type.
Definition: trilinos_space.h:90
typename Kratos::shared_ptr< TMatrixType > MatrixPointerType
Definition of the pointer types.
Definition: trilinos_space.h:99
typename Kratos::shared_ptr< TVectorType > VectorPointerType
Definition: trilinos_space.h:100
std::size_t IndexType
Definition of the index type.
Definition: trilinos_space.h:93
virtual std::string Info() const
Turn back information as a string.
Definition: trilinos_space.h:1348
static double Dot(const VectorType &rX, const VectorType &rY)
Returns the product of two vectors.
Definition: trilinos_space.h:254
virtual void PrintInfo(std::ostream &rOStream) const
Print information about this object.
Definition: trilinos_space.h:1357
static constexpr bool IsDistributed()
This function returns if we are in a distributed system.
Definition: trilinos_space.h:861
virtual void PrintData(std::ostream &rOStream) const
Print object's data.
Definition: trilinos_space.h:1366
static void Copy(const MatrixType &rX, MatrixType &rY)
Returns a copy of the matrix rX.
Definition: trilinos_space.h:226
static void ScaleAndAdd(const double A, const VectorType &rX, const double B, VectorType &rY)
Returns the unaliased addition of two vectors by a scalar.
Definition: trilinos_space.h:620
static void BtDBProductOperation(MatrixType &rA, const MatrixType &rD, const MatrixType &rB, const bool CallFillCompleteOnResult=true, const bool KeepAllHardZeros=false, const bool EnforceInitialGraph=false)
Calculates the product operation B'DB.
Definition: trilinos_space.h:414
static void GatherValues(const VectorType &rX, const std::vector< int > &IndexArray, double *pValues)
This function gathers the values of a given vector according to a given index array.
Definition: trilinos_space.h:890
TrilinosSpace()
Default constructor.
Definition: trilinos_space.h:111
static Epetra_CrsGraph CombineMatricesGraphs(const MatrixType &rA, const MatrixType &rB)
Generates a graph combining the graphs of two matrices.
Definition: trilinos_space.h:1024
static void Resize(MatrixType &rA, const SizeType m, const SizeType n)
Resizes a matrix.
Definition: trilinos_space.h:676
static double Min(const VectorType &rX)
Returns the minimum value of the vector rX.
Definition: trilinos_space.h:283
static IndexType Size2(MatrixType const &rM)
Returns number of columns of rM.
Definition: trilinos_space.h:197
KRATOS_CLASS_POINTER_DEFINITION(TrilinosSpace)
Pointer definition of TrilinosSpace.
static double GetMaxDiagonal(const MatrixType &rA)
This method returns the diagonal max value.
Definition: trilinos_space.h:1293
static double GetAveragevalueDiagonal(const MatrixType &rA)
This method returns the diagonal max value.
Definition: trilinos_space.h:1279
MatrixPointerType ReadMatrixMarket(const std::string FileName, Epetra_MpiComm &rComm)
Read a matrix from a MatrixMarket file.
Definition: trilinos_space.h:924
static double GetMinDiagonal(const MatrixType &rA)
This method returns the diagonal min value.
Definition: trilinos_space.h:1310
static void CopyMatrixValues(MatrixType &rA, const MatrixType &rB)
Copy values from one matrix to another.
Definition: trilinos_space.h:1121
static void Resize(VectorType &rX, const SizeType n)
Resizes a vector.
Definition: trilinos_space.h:690
static bool WriteMatrixMarketVector(const char *pFileName, const VectorType &rV)
Writes a vector to a file in MatrixMarket format.
Definition: trilinos_space.h:1397
std::size_t SizeType
Definition of the size type.
Definition: trilinos_space.h:96
static double GetScaleNorm(const ProcessInfo &rProcessInfo, const MatrixType &rA, const SCALING_DIAGONAL ScalingDiagonal=SCALING_DIAGONAL::NO_SCALING)
This method returns the scale norm considering for scaling the diagonal.
Definition: trilinos_space.h:1230
static MatrixPointerType CreateEmptyMatrixPointer()
This method creates an empty pointer to a matrix.
Definition: trilinos_space.h:132
static void TransposeMult(const MatrixType &rA, const MatrixType &rB, MatrixType &rC, const std::pair< bool, bool > TransposeFlag={false, false}, const bool CallFillCompleteOnResult=true, const bool KeepAllHardZeros=false)
Returns the transpose multiplication matrix-matrix.
Definition: trilinos_space.h:388
static void Set(VectorType &rX, const DataType A)
assigns a scalar to a vector
Definition: trilinos_space.h:661
static void ScaleAndAdd(const double A, const VectorType &rX, const double B, const VectorType &rY, VectorType &rZ)
Returns the unaliased addition of two vectors by a scalar.
Definition: trilinos_space.h:600
static double CheckAndCorrectZeroDiagonalValues(const ProcessInfo &rProcessInfo, MatrixType &rA, VectorType &rb, const SCALING_DIAGONAL ScalingDiagonal=SCALING_DIAGONAL::NO_SCALING)
This method checks and corrects the zero diagonal values.
Definition: trilinos_space.h:1173
double DataType
Definition of the data type.
Definition: trilinos_space.h:84
static bool WriteMatrixMarketMatrix(const char *pFileName, const TOtherMatrixType &rM, const bool Symmetric)
Writes a matrix to a file in MatrixMarket format.
Definition: trilinos_space.h:1378
static double GetDiagonalNorm(const MatrixType &rA)
This method returns the diagonal norm considering for scaling the diagonal.
Definition: trilinos_space.h:1261
static void Mult(const MatrixType &rA, const MatrixType &rB, MatrixType &rC, const bool CallFillCompleteOnResult=true, const bool KeepAllHardZeros=false)
Returns the multiplication matrix-matrix.
Definition: trilinos_space.h:343
static void Assign(VectorType &rX, const double A, const VectorType &rY)
Returns the multiplication of a vector by a scalar.
Definition: trilinos_space.h:558
static void Clear(MatrixPointerType &pA)
Clears a matrix.
Definition: trilinos_space.h:719
VectorPointerType ReadMatrixMarketVector(const std::string &rFileName, Epetra_MpiComm &rComm, const int N)
Read a vector from a MatrixMarket file.
Definition: trilinos_space.h:984
static void TransposeMult(const MatrixType &rA, const VectorType &rX, VectorType &rY)
Returns the transpose multiplication of a matrix by a vector.
Definition: trilinos_space.h:367
static VectorPointerType CreateEmptyVectorPointer(Epetra_MpiComm &rComm)
This method creates an empty pointer to a vector using epetra communicator.
Definition: trilinos_space.h:163
static void Mult(const MatrixType &rA, const VectorType &rX, VectorType &rY)
Returns the multiplication of a matrix by a vector.
Definition: trilinos_space.h:323
static IndexType Size1(MatrixType const &rM)
Returns number of rows of rM.
Definition: trilinos_space.h:186
static constexpr bool IsDistributedSpace()
Check if the TrilinosSpace is distributed.
Definition: trilinos_space.h:1327
static void InplaceMult(VectorType &rX, const double A)
Returns the multiplication of a vector by a scalar.
Definition: trilinos_space.h:538
static double TwoNorm(const VectorType &rX)
Returns the norm of the vector rX.
Definition: trilinos_space.h:297
typename DofUpdater< TrilinosSpace< TMatrixType, TVectorType > >::UniquePointer DofUpdaterPointerType
Definition: trilinos_space.h:104
static void UnaliasedAdd(VectorType &rX, const double A, const VectorType &rY)
Returns the unaliased addition of a vector by a scalar times a vector.
Definition: trilinos_space.h:581
TMatrixType MatrixType
Definition of the matrix type.
Definition: trilinos_space.h:87
virtual ~TrilinosSpace()
Destructor.
Definition: trilinos_space.h:116
static void Copy(const VectorType &rX, VectorType &rY)
Returns a copy of the vector rX.
Definition: trilinos_space.h:240
static VectorPointerType CreateEmptyVectorPointer()
This method creates an empty pointer to a vector.
Definition: trilinos_space.h:141
static void AssembleRHS(VectorType &rb, const Vector &rRHSContribution, const std::vector< std::size_t > &rEquationId)
TODO: creating the the calculating reaction version.
Definition: trilinos_space.h:823
static double TwoNorm(const MatrixType &rA)
Returns the Frobenius norm of the matrix rX.
Definition: trilinos_space.h:311
static double Max(const VectorType &rX)
Returns the maximum value of the vector rX.
Definition: trilinos_space.h:270
static IndexType Size(const VectorType &rV)
Returns size of vector rV.
Definition: trilinos_space.h:175
static DofUpdaterPointerType CreateDofUpdater()
Creates a new dof updater.
Definition: trilinos_space.h:1411
static void SetToZero(MatrixType &rA)
Sets a matrix to zero.
Definition: trilinos_space.h:747
static MatrixPointerType CreateEmptyMatrixPointer(Epetra_MpiComm &rComm)
This method creates an empty pointer to a matrix using epetra communicator.
Definition: trilinos_space.h:151
static void GetColumn(const unsigned int j, const MatrixType &rM, VectorType &rX)
Returns the column of the matrix in the given position.
Definition: trilinos_space.h:211
#define KRATOS_THROW_ERROR(ExceptionType, ErrorMessage, MoreInfo)
Definition: define.h:77
#define KRATOS_CATCH(MoreInfo)
Definition: define.h:110
#define KRATOS_TRY
Definition: define.h:109
#define KRATOS_ERROR
Definition: exception.h:161
#define KRATOS_ERROR_IF_NOT(conditional)
Definition: exception.h:163
#define KRATOS_ERROR_IF(conditional)
Definition: exception.h:162
string FileName
Export to vtk.
Definition: GenerateWind.py:175
PolynomialType Multiply(const PolynomialType &rA, const PolynomialType &rB)
Definition: polynomial_utilities.cpp:102
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
std::shared_ptr< T > shared_ptr
Definition: smart_pointers.h:27
SCALING_DIAGONAL
Definition: ublas_space.h:98
TABLE_NUMBER_ANGULAR_VELOCITY TABLE_NUMBER_MOMENT I33 BEAM_INERTIA_ROT_UNIT_LENGHT_Y KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, double, BEAM_INERTIA_ROT_UNIT_LENGHT_Z) typedef std double
Definition: DEM_application_variables.h:182
pp
Definition: all_t_win_vs_m_fixed_error.py:140
list values
Definition: bombardelli_test.py:42
tuple tmp
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:98
int n
manufactured solution and derivatives (u=0 at z=0 dudz=0 at z=domain_height)
Definition: ode_solve.py:402
int j
Definition: quadrature.py:648
float temp
Definition: rotating_cone.py:85
int m
Definition: run_marine_rain_substepping.py:8
A
Definition: sensitivityMatrix.py:70
N
Definition: sensitivityMatrix.py:29
B
Definition: sensitivityMatrix.py:76
integer i
Definition: TensorModule.f:17