⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lfel.c

📁 The Free Finite Element Package is a library which contains numerical methods required when working
💻 C
📖 第 1 页 / 共 5 页
字号:
  meml_vector_free(r);  if ( level-1 == lastLevel)    {#ifdef __HAVE_UMFPACK		xDown = disl_umfpack (A[lastLevel],rDown);#else	xDown = meml_vector_new(rDown->dim);      if (A[lastLevel]->symmetric=='y')	itsl_minres (A[lastLevel], rDown,xDown,1e-12);      else	itsl_gmres_jacobi (A[lastLevel], rDown,xDown,1e-12,50);#endif    }  else    {      xDown = meml_vector_new(rDown->dim);      lfel_multigrid_function(A, rDown, xDown,mesh,level-1, lastLevel,k1,k2);    }    meml_vector_free(rDown);  x = meml_matrix_t_vector_mul (mesh[level]->restriction,xDown);    meml_vector_free(xDown);  meml_vector_add_f(x,guess);    meml_vector_free(x);  for (i=0;i<k2;i++)    glaetter(A[level], b, guess);  }double lfel_multigrid_solver(ME_MATRIX ** A, VECTOR * b, VECTOR * guess, 			     MESH ** mesh, MEML_INT level, MEML_INT lastLevel,			     MEML_INT k1,MEML_INT k2, MEML_FLOAT eps, 			     MEML_INT maxiterations){  double rneu=eps+1;  double ralt = 0;  VECTOR * r, *temp;  int durchlauf = 0,i;  if ( level <= lastLevel)    {#ifdef __HAVE_UMFPACK		temp = disl_umfpack (A[level],b);	meml_vector_copy_f (temp,guess);	meml_vector_free(temp);	return(0);#else      if (A[lastLevel]->symmetric=='y')	itsl_minres (A[level], b,guess,eps);      else	itsl_gmres_jacobi (A[level], b,guess,1e-12,eps);#endif      return(1e-12);    }  r = meml_matrix_vector_mul(A[level],b);  meml_vector_add_ff(-1,b,r);  rneu = meml_vector_norm(r);  meml_vector_free(r);  ralt = rneu+1;  if (MEML_VERBOSE)    {      printf ("ML : r%d = %e \n", 0,rneu);    }    while ( (rneu>eps) && (rneu <ralt) && (maxiterations>durchlauf) )    {      durchlauf++;      temp = meml_vector_copy(guess);      lfel_multigrid_function(A, b, temp, mesh, level, lastLevel,k1,k2);            r = meml_matrix_vector_mul(A[level],temp);      meml_vector_add_ff(-1,b,r);      ralt = rneu;      rneu = meml_vector_norm(r);      meml_vector_free(r);      if (MEML_VERBOSE)	{	  printf ("ML : r%d = %e \n", durchlauf,rneu);	}      if ( rneu >= ralt )	{	  printf("Multigrid divergiert bei %e nach %d Schritten \n",		 rneu,durchlauf);	  printf("liefere Naeherung mit %e \n",ralt);	  meml_vector_free(temp);	#ifdef __HAVE_UMFPACK		  temp = disl_umfpack (A[level],b);	  meml_vector_copy_f (temp,guess);	  meml_vector_free(temp);	  return(0);#else	  if (A[lastLevel]->symmetric=='y')	    itsl_minres (A[level], b,guess,eps);	  else	    itsl_gmres_jacobi (A[level], b,guess,1e-12,eps);#endif	}      else	{	  for (i=0;i<guess->dim;i++)	    guess->data[i] = temp->data[i];	  meml_vector_free(temp);	}    }  return (rneu);}/** * \brief applies the values of the function f to the vector x *  * The order in x depends on the order of the points in mesh.  * t is the time argument of the function f.  *   */void lfel_apply_function_to_vector_f (VECTOR * v, MESH * mesh,				      xyt_function f, MEML_FLOAT t){  MEML_INT i;  MEML_FLOAT x, y;  for (i = 0; i < mesh->number_of_points; i++)    {      x = mesh->points->data[2 * i];      y = mesh->points->data[(2 * i) + 1];      v->data[i] = (*f) (x, y, t);    }}/** * \brief applies the values of the function f to the vector x * * The order in x depends on the order of the points in mesh.  * t is the time argument of the function f.  *   */VECTOR *lfel_apply_function_to_vector (MESH * mesh, xyt_function f,				       MEML_FLOAT t){  VECTOR *v;  v = vecl_vector_new (mesh->number_of_points);  lfel_apply_function_to_vector_f (v, mesh, f, t);  return (v);}/** * \brief  calculates the Neumann boundary condition form a vector field  *         and the mesh data * * \param v vector field at all nodes.  *        Only the values at the boundary nodes will be used. * \param mesh the mesh  *  */VECTOR *lfel_calculat_neumann_boundary_condition (VECTOR ** v, MESH * mesh){  VECTOR *g;  g = meml_vector_new (mesh->number_of_points);  lfel_calculat_neumann_boundary_condition_f (v, mesh, g);  return (g);}/** * \brief  calculates the Neumann boundary condition form a vector field  *         and the mesh data * * \param v vector field at all nodes.  *          Only the values at the boundary nodes will be used. * \param mesh the mesh  * \param g vector which contains the Neumann boundary condition on exit.  *        g has the dimension number_of_points *  */void lfel_calculat_neumann_boundary_condition_f (VECTOR ** v, MESH * mesh,						 VECTOR * g){  MEML_INT i, p1, p2, which_edge;  MEML_FLOAT temp;  for (i = 0; i < mesh->number_of_boundary_edges; i++)    {      which_edge = mesh->boundary_edges[i];      p1 = mesh->edges[which_edge][0];      p2 = mesh->edges[which_edge][1];      temp =	mesh->normal_vector[i]->data[0] * v[p1 - 1]->data[0] +	mesh->normal_vector[i]->data[1] * v[p1 - 1]->data[1];      g->data[p1 - 1] += temp;      temp =	mesh->normal_vector[i]->data[0] * v[p2 - 1]->data[0] +	mesh->normal_vector[i]->data[1] * v[p2 - 1]->data[1];      g->data[p2 - 1] += temp;    }  meml_vector_scaling_f (0.5, g);}/** * \brief  * applies the Neumann boundary compatibility condition to the right side  * *  g must be a vector of number_of_points size.  *  Set for every boundary point i the value of g[i]. *   */void lfel_set_compatibility_condition_to_right_side (VECTOR * b,						     const VECTOR * g,						     MESH * mesh){  MEML_FLOAT S, mu_omega, c;  MEML_INT number_of_points = b->dim;  VECTOR *Ones;  MEML_INT i, j, aktueller_knoten, zaehler, nachbarn[2];  MEML_FLOAT x[3], y[3], h[2], S_rand = 0;  if (g!=NULL)    {      for (i = 0; i < mesh->number_of_boundary_points; i++)	{	  aktueller_knoten = mesh->boundary->data[i];	  zaehler = 0;	  /* finde die rand-nachbarn des aktuellen knotens */	  for (j = 0; j < mesh->number_of_neighbours[aktueller_knoten - 1]; j++)	    if (meml_element_of_indexarray		(mesh->boundary, mesh->neighbours[aktueller_knoten - 1]->data[j]))	      {		nachbarn[zaehler] =		  mesh->neighbours[aktueller_knoten - 1]->data[j];		zaehler++;	      }	  /* bestimme den Abstand */	  for (j = 0; j < 2; j++)	    {	      x[j] = mesh->points->data[2 * (nachbarn[j] - 1)];	      y[j] = mesh->points->data[2 * (nachbarn[j] - 1) + 1];	    }	  	  x[2] = mesh->points->data[2 * (aktueller_knoten - 1)];	  y[2] = mesh->points->data[2 * (aktueller_knoten - 1) + 1];	  	  for (j = 0; j < 2; j++)	    {	      h[j] = sqrt (pow (x[j] - x[2], 2) + pow (y[j] - y[2], 2));	      /* Simpson-Regel */	      S_rand = S_rand + h[j] * (0.5 * g->data[aktueller_knoten - 1] +				    0.5 * g->data[nachbarn[j] - 1]);	    }	}            /* da jedes stueck doppel gezaehlt wurde */      S_rand = S_rand / 2;    }  else    {      S_rand = 0;    }  /* compute the integral of f over omega */  S = lfel_integrating (b, mesh);  /* compute \mu(omega) */  Ones = meml_vector_new_ones (b->dim);  mu_omega = lfel_integrating (Ones, mesh);  meml_vector_free (Ones);  c = (S + S_rand) / mu_omega;  for (i = 0; i < number_of_points; i++)    b->data[i] = b->data[i] - c;}/** * \brief applies the neumann boundary conditions to the right side  * *  g must be a vector of number_of_points size.  *  Set for every boundary point i the value of g[i]. *   */void lfel_set_neumann_cond_to_right_side (VECTOR * b, const VECTOR * g,					  MESH * mesh){  MEML_INT i, j, aktueller_knoten, zaehler, nachbarn[2];  MEML_FLOAT x[3], y[3], h[2], integral_wert[2];  for (i = 0; i < mesh->number_of_boundary_points; i++)    {      aktueller_knoten = mesh->boundary->data[i];      zaehler = 0;      /* finde die rand-nachbarn des aktuellen knotens */      for (j = 0; j < mesh->number_of_neighbours[aktueller_knoten - 1]; j++)	{	  if (meml_element_of_indexarray (mesh->boundary,					  mesh->					  neighbours[aktueller_knoten -						     1]->data[j]))	    {	      nachbarn[zaehler] =		mesh->neighbours[aktueller_knoten - 1]->data[j];	      zaehler++;	    }	}      /* bestimme den Abstand */      for (j = 0; j < 2; j++)	{	  x[j] = mesh->points->data[2 * (nachbarn[j] - 1)];	  y[j] = mesh->points->data[2 * (nachbarn[j] - 1) + 1];	}      x[2] = mesh->points->data[2 * (aktueller_knoten - 1)];      y[2] = mesh->points->data[2 * (aktueller_knoten - 1) + 1];      for (j = 0; j < 2; j++)	{	  h[j] = sqrt (pow (x[j] - x[2], 2) + pow (y[j] - y[2], 2));	  /* Simpson-Regel */	  integral_wert[j] =	    h[j] * ((1.0 / 6.0) * g->data[aktueller_knoten - 1] +		    (2.0 / 3.0) * 0.25 * (g->data[aktueller_knoten - 1] +					  g->data[nachbarn[j] - 1]));	  b->data[aktueller_knoten - 1] =	    b->data[aktueller_knoten - 1] + integral_wert[j];	}    }}/** *  \brief  *  Computes the interpolation operator from the coarse  *  points P0 to the points P1  * * The function computes a sparse matrix representation of the interpolation * operator from a coarse mesh to a finer mesh. * * \todo In the monent mesh_high must be the globale  * red refinement of mesh_low. A more general interpolation must be build. *  * \param mesh_low the coarse mesh * \param mesh_high the finer mesh * */ME_MATRIX *lfel_interpolation (MESH * mesh_low, MESH * mesh_high){  VECTOR *P0 = mesh_low->points;  VECTOR *P1 = mesh_high->points;  INDEXARRAY *triangles = mesh_high->triangles;  MEML_INT n0 = P0->dim / 2;  MEML_INT n1 = P1->dim / 2;  MEML_INT nt = 0.75 * triangles->dim / 3;  TRIANGLE the_triangle;  MEML_INT i;  ME_MATRIX *I;  ME_MATRIX *temp_matrix;  INDEXARRAY *T1;  INDEXARRAY *T2;  INDEXARRAY *T3;  VECTOR *Ones;  T1 = meml_indexarray_new (nt);  T2 = meml_indexarray_new (nt);  T3 = meml_indexarray_new (nt);  /* getting the neighborhood */  for (i = 0; i < nt; i++)    {      the_triangle = smfl_get_triangle (i, triangles->data);      meml_indexarray_element_set (T1, i, the_triangle.p[0] - 1);      meml_indexarray_element_set (T2, i, the_triangle.p[1] - 1);      meml_indexarray_element_set (T3, i, the_triangle.p[2] - 1);    }  Ones = meml_vector_new_ones (nt);  meml_vector_scaling_f (0.5, Ones);  I = meml_sparse (T2, T1, Ones);  temp_matrix = meml_sparse (T3, T1, Ones);  meml_matrix_resize (&I, n1, n0);  meml_matrix_resize (&temp_matrix, n1, n0);  meml_matrix_add_f (temp_matrix, I);  meml_matrix_ceil (I);  meml_matrix_scaling_f (0.5, I);  meml_matrix_free (temp_matrix);  temp_matrix = meml_matrix_new_eye (LS, n1, n0);  meml_matrix_add_f (temp_matrix, I);  meml_vector_free (Ones);  meml_indexarray_free (T1);  meml_indexarray_free (T2);  meml_indexarray_free (T3);  meml_matrix_free (temp_matrix);  return (I);}/** * \brief  * \~german  *  Berechnet den Gradienten einer Funktion, die durch ihre Werte an  *  den Knoten stellen des Gitters gegeben ist.  * \~english *  Computes the gradient of a function, which is given by the  *  values of the function at the nodes of the mesh. * * \f$ (v_x , v_y) = grad \; v  \f$<br> * * \~german  * \param v sind die Werte einer Funktion an den Knoten der  * Triangulierung. Sie werden in einem Vektor in der Reihenfolge der  * Knoten abgespeichert. * *  \param transformation Abildungen des Referenzdreiecks auf die Dreiecke der  *   Triangulierung lfel_compute_transformations * *  \param triangles enthaelt die Informationen ueber die Knoten der Dreiecke  *  der Triangulierung in einem Format wie es von der Funktion  *  lfel_read_triangle_data erzeugt wird. * *  \param v_x enthaelt nach der Beendigung der Funktion *  die partielle Ableitung von v in x Richtung * *  \param v_y enthaelt nach der Beendigung der Funktion *  die partielle Ableitung von v in y Richtung * *  v_x und v_y muessen vor dem Aufruf der Funktion initialisiert worden sein. * */void lfel_grad (const VECTOR * v, MESH * mesh, VECTOR * v_x, VECTOR * v_y){  TRANSFORMATION *transformation = mesh->transformation;  INDEXARRAY *triangles = mesh->triangles;  VECTOR **gradient;  VECTOR *c;  VECTOR *b1;  VECTOR *b2;  MEML_INT number_of_triangles = (triangles->dim) / 3;  MEML_INT number_of_points = v->dim;  MEML_INT i, j;  MEML_INT *zaehler;  MEML_FLOAT gradx, grady;  TRIANGLE the_triangle;  MEML_INT *triangle_node = triangles->data;  gradient = (VECTOR **) calloc (number_of_points, sizeof (VECTOR *));  zaehler = (MEML_INT *) calloc (number_of_points, sizeof (MEML_INT));  for (i = 0; i < number_of_points; i++)    {      gradient[i] = meml_vector_new (2);    }  c = meml_vector_new (3);  b1 = meml_vector_new (3);  b2 = meml_vector_new (3);  for (i = 0; i < number_of_triangles; i++)    {      /* b1xb2=c */      /* konstruiere b1 und b2 */      meml_vector_element_set_f (b1, 0, transformation[i].B[0][0]);      meml_vector_element_set_f (b1, 1, transformation[i].B[1][0]);      meml_vector_element_set_f (b2, 0, transformation[i].B[0][1]);      meml_vector_element_set_f (b2, 1, transformation[i].B[1][1]);      /* dritte komponente berechnen */      the_triangle = smfl_get_triangle (i, triangle_node);      b1->data[2] = v->data[the_triangle.p[1] - 1] -	v->data[the_triangle.p[0] - 1];      b2->data[2] = v->data[the_triangle.p[2] - 1] -	v->data[the_triangle.p[0] - 1];      /* kreuprodukt berechnen */      lfel_kreuzprodukt (b1, b2, c);      if (c->data[2] != 0)	{	  gradx = -(c->data[0] / c->data[2]);	  grady = -(c->data[1] / c->data[2]);	  for (j = 0; j < 3; j++)	    {	      (gradient[the_triangle.p[j] - 1])->data[0] += gradx;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -