Exemplo n.º 1
0
void MyFrame::OnSaveFrequencies(wxCommandEvent& event)
{
   wxFileDialog *dlg = new wxFileDialog(this, _T("Save frequencies"), uiState.currentWorkingDirectory, _T(""), _T("Frequency Files(*.freq)|*.freq|All files(*.*)|*.*"), wxFD_SAVE /*| wxHIDE_READONLY*/, wxDefaultPosition);

  if ( dlg->ShowModal() == wxID_OK )
  {
    wxString frequencyFilename( dlg->GetPath());
    SaveCurrentWorkingDirectory(frequencyFilename);
    if( !frequencyFilename.empty() )
    {
      const char * filename = frequencyFilename.mb_str();
      int code = WriteMatrixToDisk((char*)filename,
        precomputationState.rLin, 1, precomputationState.frequencies);

      if (code != 0)
      {
        this->errMsg( _T("Saving error"),  
          _T("Unable to save frequencies to ") + frequencyFilename );
        dlg->Destroy();
        return;
      }
    }
  }

  dlg->Destroy();
}
Exemplo n.º 2
0
void MyFrame::OnExportFrequencies(wxCommandEvent& event)
{
   wxFileDialog *dlg = new wxFileDialog(this, _T("Export frequencies"), uiState.currentWorkingDirectory, _T(""), _T("Text Files(*.txt)|*.txt|All files(*.*)|*.*"), wxFD_SAVE /*| wxHIDE_READONLY*/, wxDefaultPosition);

  if ( dlg->ShowModal() == wxID_OK )
  {
    wxString frequencyFilename( dlg->GetPath() );
    SaveCurrentWorkingDirectory(frequencyFilename);
    if( !frequencyFilename.empty() )
    {
      const char * filename = frequencyFilename.mb_str();
      FILE * fout = fopen((char*)filename, "w");
      if (fout)
      {
        fprintf(fout,"%d\n", precomputationState.rLin);
        for(int j=0; j<precomputationState.rLin; j++)
        {
          fprintf(fout, "%.15f\n", precomputationState.frequencies[j]);
        }
        fclose(fout);
      }
      else
      {
        this->errMsg( _T("Exporting error"),  
          _T("Unable to export frequencies to ") + frequencyFilename );
        dlg->Destroy();
        return;
      }
    }
  }

  dlg->Destroy();
}
Exemplo n.º 3
0
void MyFrame::OnSaveNonLinearModes(wxCommandEvent& event)
{
  wxFileDialog *dlg = new wxFileDialog(this, _T("Save nonlinear modes"), uiState.currentWorkingDirectory, _T(""), _T("Modal Matrix Files(*.U)|*.U|All files(*.*)|*.*"), wxFD_SAVE /*| wxHIDE_READONLY*/, wxDefaultPosition);

  if ( dlg->ShowModal() == wxID_OK )
  {
    wxString nonLinearModesFilename( dlg->GetPath());
    SaveCurrentWorkingDirectory(nonLinearModesFilename);
    if( !nonLinearModesFilename.empty() )
    {
      const char * filename = nonLinearModesFilename.mb_str();
      int code = WriteMatrixToDisk((char*)filename,
        3 * precomputationState.nonLinearModalMatrix->Getn(), 
        precomputationState.nonLinearModalMatrix->Getr(), 
        precomputationState.nonLinearModalMatrix->GetMatrix());

      if (code != 0)
      {
        this->errMsg( _T("Saving error"),  
            _T("Unable to save nonlinear modes to ") + nonLinearModesFilename );
        dlg->Destroy();
        return;
      }
    }
  }

  dlg->Destroy();
}
Exemplo n.º 4
0
void MyFrame::OnLoadFixedVertices(wxCommandEvent& event)
{
  wxFileDialog *dlg = new wxFileDialog(this, _T("Load fixed vertices"),
    uiState.currentWorkingDirectory, _T(""), _T("Comma-separated 1-indexed file(*.bou)|*.bou|All files(*.*)|*.*"), wxFD_OPEN /*| wxHIDE_READONLY*/, wxDefaultPosition);

  if ( dlg->ShowModal() == wxID_OK )
  {
    wxString fixedVerticesFilename( dlg->GetPath() );
    delete(dlg);
    SaveCurrentWorkingDirectory(fixedVerticesFilename);
    if( !fixedVerticesFilename.empty() )
    {
      int code = LoadFixedVertices(fixedVerticesFilename);
      if (code != 0)
      {
        printf("Error: failed to load fixed vertices from file %s , exit code %d.\n", (const char*)fixedVerticesFilename.mb_str(), code);
        return;
      }
    }
  }
  else
  {
    dlg->Destroy();
  }
}
Exemplo n.º 5
0
void MyFrame::OnSaveFixedVertices(wxCommandEvent& event)
{
  wxFileDialog *dlg = new wxFileDialog(this, _T("Save fixed vertices"),
    uiState.currentWorkingDirectory, _T(""), _T("Fixed Vertices Files(*.bou)|*.bou|All files(*.*)|*.*"),
    wxFD_SAVE /*| wxHIDE_READONLY*/, wxDefaultPosition);

  if ( dlg->ShowModal() == wxID_OK )
  {
    wxString vertexFilename( dlg->GetPath() );
    SaveCurrentWorkingDirectory(vertexFilename);
    if( !vertexFilename.empty() )
    {
      int numFixedVertices = (int)(precomputationState.fixedVertices.size());
      int * fixedVerticesC = (int*) malloc (sizeof(int) * numFixedVertices);
      set<int> :: iterator iter;
      int i=0;
      for(iter = precomputationState.fixedVertices.begin(); iter != precomputationState.fixedVertices.end(); iter++)
      {
        fixedVerticesC[i] = *iter;
        i++;
      }

      //loadList.sort(numFixedVertices, fixedVertices);
      int offset = 1;
      const char * filename = vertexFilename.mb_str();
      int code = LoadList::save((char*)filename, numFixedVertices, fixedVerticesC, offset);
      free(fixedVerticesC);
      if (code != 0)
        this->errMsg( _T("Saving error"), _T("Unable to save fixed vertices to ") +  vertexFilename );
    }
  }

  dlg->Destroy();
}
Exemplo n.º 6
0
void MyFrame::OnLoadNonLinearModes(wxCommandEvent& event)
{
  wxFileDialog *dlg = new wxFileDialog(this, _T("Load nonlinear modes"), uiState.currentWorkingDirectory, _T(""), _T("Modal Matrix Files(*.U)|*.U|All files(*.*)|*.*"), wxFD_OPEN /*| wxHIDE_READONLY*/, wxDefaultPosition);

  if ( dlg->ShowModal() == wxID_OK )
  {
    wxString nonLinearModesFilename( dlg->GetPath());
    SaveCurrentWorkingDirectory(nonLinearModesFilename);
    if( !nonLinearModesFilename.empty() )
    {
      int newrNonLin;
      double * newNonLinearModes = NULL;

      int n1;
      SetCursor(*wxHOURGLASS_CURSOR);
      const char * filename = nonLinearModesFilename.mb_str();
      int code = ReadMatrixFromDisk((char*)filename, &n1, &newrNonLin, &newNonLinearModes);
      SetCursor(*wxSTANDARD_CURSOR);

      if (code != 0)
      {
        this->errMsg( _T("Loading error"),  
          _T("Unable to load nonlinear modes from ") + nonLinearModesFilename );
        dlg->Destroy();
        return;
      }

      if (n1 != 3 * precomputationState.simulationMesh->getNumVertices())
      {
        this->errMsg( _T("Loading error"),  
          _T("The number of vertices in ") + nonLinearModesFilename + _T(" does not match the simulation mesh."));
        free(newNonLinearModes);
        dlg->Destroy();
        return;
      }

      // success
      delete(precomputationState.nonLinearModalMatrix);
      precomputationState.rNonLin = newrNonLin;
      precomputationState.nonLinearModalMatrix = new ModalMatrix(precomputationState.simulationMesh->getNumVertices(), precomputationState.rNonLin, newNonLinearModes);
      free(newNonLinearModes);

      precomputationState.nonLinearModesAvailable = true;

      modeSelectionControl->SetValue(1);

      SelectView(UIState::VIEW_NONLINEAR_MODES);
      SetAutoRenderingMagnitude(precomputationState.nonLinearModalMatrix);

      UpdateMenus();

      myGLCanvas->UpdateNonLinearModesRenderData();

      Refresh();
    }
  }

  dlg->Destroy();
}
Exemplo n.º 7
0
void MyFrame::ExportMassMatrix(bool fullMatrix)
{
  if ((!fullMatrix) && (!precomputationState.fixedVerticesAvailable))
  {
    this->errMsg( _T("Error"),  
      _T("No fixed vertices have been specified.") );
    return;
  }

  wxFileDialog *dlg = new wxFileDialog(this, _T("Export mass matrix"), uiState.currentWorkingDirectory, _T(""), _T("Mass Matrix Files(*.M)|*.M|All files(*.*)|*.*"), wxFD_SAVE /*| wxHIDE_READONLY*/, wxDefaultPosition);
  if ( dlg->ShowModal() == wxID_OK )
  {
    wxString massMatrixFilename( dlg->GetPath() );
    SaveCurrentWorkingDirectory(massMatrixFilename);
    if( !massMatrixFilename.empty() )
    {
      // create mass matrix

      SparseMatrix * massMatrix;
      GenerateMassMatrix::computeMassMatrix(precomputationState.simulationMesh, &massMatrix, true); 

      if (!fullMatrix)
      {
        // constrain the degrees of freedom
        int numConstrainedVertices = (int) (precomputationState.fixedVertices.size());
        int * constrainedDOFs = (int*) malloc (sizeof(int) * 3 * numConstrainedVertices);
        int i = 0;
        for(set<int> :: iterator iter = precomputationState.fixedVertices.begin(); 
          iter != precomputationState.fixedVertices.end(); iter++)
        {
          constrainedDOFs[3*i+0] = 3 * (*iter) + 1;
          constrainedDOFs[3*i+1] = 3 * (*iter) + 2;
          constrainedDOFs[3*i+2] = 3 * (*iter) + 3;
          i++;
        }

        int oneIndexed = 1;
        massMatrix->RemoveRowsColumns(
          3 * numConstrainedVertices, constrainedDOFs, oneIndexed);
        free(constrainedDOFs);
      }

      const char * filename = massMatrixFilename.mb_str();
      int code = massMatrix->Save((char*)filename);
      delete(massMatrix);
      if (code != 0)
      {
        this->errMsg( _T("Saving error"),  
          _T("Unable to save mass matrix to ") + massMatrixFilename );
        dlg->Destroy();
        return;
      }
    }
  }

  dlg->Destroy();
}
Exemplo n.º 8
0
void MyFrame::OnLoadSketchData(wxCommandEvent& event)
{
  wxFileDialog *dlg = new wxFileDialog(this, _T("Load external simulation data"), uiState.currentWorkingDirectory, _T(""), _T("External Data Files(*.UData)|*.UData|All files(*.*)|*.*"), wxFD_OPEN /*| wxHIDE_READONLY*/, wxDefaultPosition);

  if ( dlg->ShowModal() == wxID_OK )
  {
    wxString sketchDataFilename( dlg->GetPath());
    SaveCurrentWorkingDirectory(sketchDataFilename);
    if( !sketchDataFilename.empty() )
    {
      int newSketchDatasamples;
      double * newSketchData = NULL;

      int n1;
      SetCursor(*wxHOURGLASS_CURSOR);
      const char * filename = sketchDataFilename.mb_str();
      printf("Loading external simulation data from %s.\n", filename);
      int code = ReadMatrixFromDisk((char*)filename, 
        &n1, &newSketchDatasamples, &newSketchData);
      SetCursor(*wxSTANDARD_CURSOR);

      if (code != 0)
      {
        this->errMsg( _T("Loading error"),  
          _T("Unable to load external simulation data from ") + sketchDataFilename );
        dlg->Destroy();
        return;
      }

      if (n1 != 3 * precomputationState.simulationMesh->getNumVertices())
      {
        this->errMsg( _T("Loading error"),  
          _T("The number of vertices in ") + sketchDataFilename + _T(" does not match the simulation mesh."));
        free(newSketchData);
        dlg->Destroy();
        return;
      }

      // success
      delete(precomputationState.sketchDataMatrix);
      precomputationState.sketchDataMatrix = new 
        ModalMatrix(precomputationState.simulationMesh->getNumVertices(), 
          newSketchDatasamples, newSketchData);
      free(newSketchData);

      precomputationState.sketchDataAvailable = true;

      UpdateMenus();

      Refresh();
    }
  }

  dlg->Destroy();
}
Exemplo n.º 9
0
void MyFrame::OnLoadFrequencies(wxCommandEvent& event)
{
  wxFileDialog *dlg = new wxFileDialog(this, _T("Load frequencies"), uiState.currentWorkingDirectory, _T(""), _T("Frequency Files(*.freq)|*.freq|All files(*.*)|*.*"), wxFD_OPEN /*| wxHIDE_READONLY*/, wxDefaultPosition);

  if ( dlg->ShowModal() == wxID_OK )
  {
    wxString frequencyFilename( dlg->GetPath() );
    SaveCurrentWorkingDirectory(frequencyFilename);
    if( !frequencyFilename.empty() )
    {
      int newr;
      double * newFrequencies = NULL;

      int m1;
      SetCursor(*wxHOURGLASS_CURSOR);
      const char * filename = frequencyFilename.mb_str();
      int code = ReadMatrixFromDisk((char*)filename, &newr, &m1, &newFrequencies);
      SetCursor(*wxSTANDARD_CURSOR);

      if (code != 0)
      {
        this->errMsg( _T("Loading error"),  _T("Unable to load frequencies from ") + frequencyFilename );
        dlg->Destroy();
        return;
      }

      if (precomputationState.linearModesAvailable && (newr != precomputationState.rLin))
      {
        char s[4096];
        const char * filename = frequencyFilename.mb_str();
        sprintf(s, "The number of frequencies (%d) "
          "in %s does not match the currently available number of linear modes (%d).",
          newr, (char*)filename, precomputationState.rLin);
        this->errMsg( _T("Loading error"), wxString(s, wxConvUTF8));
        free(newFrequencies);
        dlg->Destroy();
        return;
      }

      // success
      free(precomputationState.frequencies);
      precomputationState.rLin = newr;
      precomputationState.frequencies = newFrequencies;

      precomputationState.frequenciesAvailable = true;
      UpdateMenus();
      UpdateModalToolbar();

      Refresh();
    }
  }

  dlg->Destroy();
}
Exemplo n.º 10
0
void MyFrame::InterpolateMatrix(wxString dataDescription, ModalMatrix * inputModalMatrix)
{
  wxFileDialog *dlg = new wxFileDialog(this, _T("Interpolate ") + dataDescription + _T(" to triangle mesh"), uiState.currentWorkingDirectory, _T(""), _T("Modal Matrix Files(*.U)|*.U|All files(*.*)|*.*"), wxFD_SAVE /*| wxHIDE_READONLY*/, wxDefaultPosition);

  if ( dlg->ShowModal() == wxID_OK )
  {
    wxString outputFilename( dlg->GetPath() );
    SaveCurrentWorkingDirectory(outputFilename);
    if( !outputFilename.empty() )
    {
      SetCursor(*wxHOURGLASS_CURSOR);
      if (!precomputationState.interpolationDataAvailable)
        BuildInterpolant();

      // interpolate
      printf("Interpolating data...\n");
      double * inputMatrix = inputModalMatrix->GetMatrix();
      int nTarget = (int)(precomputationState.renderingMesh->getNumVertices());
      double * outputMatrix = (double*) malloc (sizeof(double) * 3 * nTarget * inputModalMatrix->Getr());
      for(int i=0; i<inputModalMatrix->Getr(); i++)
      {
        precomputationState.simulationMesh->interpolate(
          &inputMatrix[ELT(3*precomputationState.simulationMesh->getNumVertices(),0,i)],
          &outputMatrix[ELT(3*nTarget,0,i)],
          nTarget, precomputationState.simulationMesh->getNumElementVertices(),
          precomputationState.interpolationData_vertices,
          precomputationState.interpolationData_weights);
      }

      // save file to disk
      const char * filename = outputFilename.mb_str();
	  printf("Saving output to %s.\n", (char*)filename);
	  int code = WriteMatrixToDisk((char*)filename,
        3 * nTarget, 
        inputModalMatrix->Getr(), 
        outputMatrix);

      free(outputMatrix);

      SetCursor(*wxSTANDARD_CURSOR);

      if (code != 0)
      {
        this->errMsg( _T("Saving error"),  
          _T("Unable to save interpolated data to ") + outputFilename );
        dlg->Destroy();
        return;
      }
    }
  }

  dlg->Destroy();
}
Exemplo n.º 11
0
void MyFrame::OnExportLinearModes(wxCommandEvent& event)
{
  wxFileDialog *dlg = new wxFileDialog(this, _T("Export linear modes"),
	uiState.currentWorkingDirectory, _T(""), _T("Text Files(*.txt)|*.txt|All files(*.*)|*.*"),
	wxFD_SAVE /*| wxHIDE_READONLY*/, wxDefaultPosition);
  if ( dlg->ShowModal() == wxID_OK )
  {
    wxString linearModesFilename( dlg->GetPath().GetData() );
    SaveCurrentWorkingDirectory(linearModesFilename);
    if( !linearModesFilename.empty() )
    {
      const char * filename = linearModesFilename.mb_str();
      FILE * fout = fopen((char*)filename, "w");
      if (fout)
      {
        double * U = precomputationState.linearModalMatrix->GetMatrix();
        int n = precomputationState.linearModalMatrix->Getn();
        fprintf(fout,"%d\n%d\n", 3*n, precomputationState.rLin);
        for(int i=0; i<3*n; i++)
        {
          for(int j=0; j<precomputationState.rLin; j++)
          {
            fprintf(fout, "%.15f ", U[ELT(3*n,i,j)]);
          }
          fprintf(fout,"\n");
        }
        fclose(fout);
      }
      else
      {
        this->errMsg( _T("Exporting error"),  
          _T("Unable to export linear modes to ") + linearModesFilename );
        dlg->Destroy();
        return;
      }
    }
  }

  dlg->Destroy();
}
Exemplo n.º 12
0
void MyFrame::OnSaveInterpolant(wxCommandEvent& event)
{
  wxFileDialog * dlg = new wxFileDialog(this, _T("Save interpolant to file"), uiState.currentWorkingDirectory, _T(""), _T("Interpolant Text Files(*.interp)|*.interp|All files(*.*)|*.*"), wxFD_SAVE /*| wxHIDE_READONLY*/, wxDefaultPosition);

  if ( dlg->ShowModal() == wxID_OK )
  {
    wxString outputFilename( dlg->GetPath() );
    SaveCurrentWorkingDirectory(outputFilename);
    if( !outputFilename.empty() )
    {
      SetCursor(*wxHOURGLASS_CURSOR);
      if (!precomputationState.interpolationDataAvailable)
        BuildInterpolant();

      int nTarget = (int)(precomputationState.renderingMesh->getNumVertices());
      const char * filename = outputFilename.mb_str();

      int code = precomputationState.simulationMesh->saveInterpolationWeights
        ((char*)filename, nTarget, 
         precomputationState.simulationMesh->getNumElementVertices(),
         precomputationState.interpolationData_vertices, 
         precomputationState.interpolationData_weights);

      SetCursor(*wxSTANDARD_CURSOR);

      if (code != 0)
      {
        this->errMsg( _T("Saving error"),  
          _T("Unable to save interpolated data to ") + outputFilename );
        dlg->Destroy();
        return;
      }
    }
  }

  dlg->Destroy();  
}
Exemplo n.º 13
0
void MyFrame::ExportStiffnessMatrix(bool fullMatrix)
{
  if ((!fullMatrix) && (!precomputationState.fixedVerticesAvailable))
  {
    this->errMsg( _T("Error"),  
      _T("No fixed vertices have been specified.") );
    return;
  }

  wxFileDialog *dlg = new wxFileDialog(this, _T("Export stiffness matrix"), uiState.currentWorkingDirectory, _T(""), _T("Stiffness Matrix Files(*.K)|*.K|All files(*.*)|*.*"), wxFD_SAVE /*| wxHIDE_READONLY*/, wxDefaultPosition);
  if ( dlg->ShowModal() == wxID_OK )
  {
    wxString stiffnessMatrixFilename( dlg->GetPath() );
    SaveCurrentWorkingDirectory(stiffnessMatrixFilename);
    if( !stiffnessMatrixFilename.empty() )
    {
      // create stiffness matrix
      StVKElementABCD * precomputedIntegrals = StVKElementABCDLoader::load(precomputationState.simulationMesh);
      StVKInternalForces * internalForces = 
        new StVKInternalForces(precomputationState.simulationMesh, precomputedIntegrals);

      SparseMatrix * stiffnessMatrix;
      StVKStiffnessMatrix * stiffnessMatrixClass = new StVKStiffnessMatrix(internalForces);
      stiffnessMatrixClass->GetStiffnessMatrixTopology(&stiffnessMatrix);
      double * zero = (double*) calloc(3 * precomputationState.simulationMesh->getNumVertices(), sizeof(double));
      stiffnessMatrixClass->ComputeStiffnessMatrix(zero, stiffnessMatrix);

      free(zero);
      delete(precomputedIntegrals);
      delete(stiffnessMatrixClass);
      delete(internalForces);

      if (!fullMatrix)
      {
        // constrain the degrees of freedom
        int numConstrainedVertices = (int) (precomputationState.fixedVertices.size());
        int * constrainedDOFs = (int*) malloc (sizeof(int) * 3 * numConstrainedVertices);
        int i = 0;
        for(set<int> :: iterator iter = precomputationState.fixedVertices.begin(); 
          iter != precomputationState.fixedVertices.end(); iter++)
        {
          constrainedDOFs[3*i+0] = 3 * (*iter) + 1;
          constrainedDOFs[3*i+1] = 3 * (*iter) + 2;
          constrainedDOFs[3*i+2] = 3 * (*iter) + 3;
          i++;
        }

        int oneIndexed = 1;
        stiffnessMatrix->RemoveRowsColumns(
          3 * numConstrainedVertices, constrainedDOFs, oneIndexed);
        free(constrainedDOFs);
      }

      const char * filename = stiffnessMatrixFilename.mb_str();
      int code = stiffnessMatrix->Save((char*)filename);

      delete(stiffnessMatrix);

      if (code != 0)
      {
        this->errMsg( _T("Saving error"),  
          _T("Unable to save stiffness matrix to ") + stiffnessMatrixFilename );
        dlg->Destroy();
        return;
      }
    }
  }

  dlg->Destroy();
}
Exemplo n.º 14
0
void MyFrame::OnLoadLinearModes(wxCommandEvent& event)
{
  wxFileDialog *dlg = new wxFileDialog(this, _T("Load linear modes"), uiState.currentWorkingDirectory, _T(""), _T("Modal Matrix Files(*.Ulin)|*.Ulin|Modal Matrix Files(*.U)|*.U|All files(*.*)|*.*"), wxFD_OPEN /*| wxHIDE_READONLY*/, wxDefaultPosition);

  if ( dlg->ShowModal() == wxID_OK )
  {
    wxString linearModesFilename( dlg->GetPath());
    SaveCurrentWorkingDirectory(linearModesFilename);
    if( !linearModesFilename.empty() )
    {
      int newr;
      double * newLinearModes = NULL;

      int n1;
      SetCursor(*wxHOURGLASS_CURSOR);
      const char * filename = linearModesFilename.mb_str();
      int code = ReadMatrixFromDisk((char*)filename, &n1, &newr, &newLinearModes);
      SetCursor(*wxSTANDARD_CURSOR);

      if (code != 0)
      {
        this->errMsg( _T("Loading error"),  _T("Unable to load linear modes from ") + linearModesFilename );
        dlg->Destroy();
        return;
      }

      if (n1 != 3 * precomputationState.simulationMesh->getNumVertices())
      {
        this->errMsg( _T("Loading error"), _T("The number of vertices in ") + linearModesFilename + _T(" does not match the simulation mesh."));
        free(newLinearModes);
        dlg->Destroy();
        return;
      }

      if (precomputationState.frequenciesAvailable)
      {
        // check that the number of modes is consistent with the existing number of frequencies
        if (newr != precomputationState.rLin)
        {
          wxMessageDialog * confirmationDialog = new wxMessageDialog (this, _T("Warning: number of existing frequencies does not match the number of modes. Delete existing frequencies?"), _T("Mismatch in the number of frequencies"), wxYES_NO | wxICON_EXCLAMATION);

          if (confirmationDialog->ShowModal() != wxID_YES)
          {
            free(newLinearModes);
            delete(confirmationDialog);
            dlg->Destroy();
            return;
          }
          else
          {
            delete(confirmationDialog);
            free(precomputationState.frequencies);
            precomputationState.frequenciesAvailable = false;
          }
        }
      }

      // success
      delete(precomputationState.linearModalMatrix);
      precomputationState.rLin = newr;
      precomputationState.linearModalMatrix = new ModalMatrix(
        precomputationState.simulationMesh->getNumVertices(), precomputationState.rLin, newLinearModes);
      free(newLinearModes);

      precomputationState.linearModesAvailable = true;

      uiState.numComputedNonLinearModes = 2 * (precomputationState.rLin - precomputationState.numRigidModes);
      uiState.eraseRangeHi = precomputationState.rLin;

      modeSelectionControl->SetValue(1);

      SelectView(UIState::VIEW_LINEAR_MODES);
      SetAutoRenderingMagnitude(precomputationState.linearModalMatrix);

      UpdateMenus();

      myGLCanvas->UpdateLinearModesRenderData();

      Refresh();
    }
  }

  dlg->Destroy();
}