Load balancing / redistributing a 1D DM
Hi all, We have a code that solves the 1D multiphase Euler equations, using some very expensive thermodynamic calls in each cell in each time step. The computational time for different cells varies significantly in the spatial direction (due to different thermodynamic states), and varies slowly from timestep to timestep. Currently the code runs in serial, but I would like to use a PETSc DM of some sort to run it in parallell. There will be no linear on nonlinear PETSc solves etc., just a distributed mesh, at least initially. The code is Fortran. Now for my question: Is it possible to do dynamic load balancing using a plain 1D DMDA, somehow? There is some mention of this for PCTELESCOPE, but I guess it only works for linear solves? Or could I use an index set or some other PETSc structure? Or do I need to use a 1D DMPLEX? If the latter, how do I make a 1D DMPLEX? All the variables are stored in cell centers (collocated), so it's a completely trivial "mesh". I tried reading the DMPLEX manual, and looking at examples, but I'm having trouble penetrating the FEM lingo / abstract nonsense. Best regards, Åsmund
On Mon, Mar 5, 2018 at 4:29 AM, Åsmund Ervik <[email protected]> wrote:
Hi all,
We have a code that solves the 1D multiphase Euler equations, using some very expensive thermodynamic calls in each cell in each time step. The computational time for different cells varies significantly in the spatial direction (due to different thermodynamic states), and varies slowly from timestep to timestep.
Currently the code runs in serial, but I would like to use a PETSc DM of some sort to run it in parallell. There will be no linear on nonlinear PETSc solves etc., just a distributed mesh, at least initially. The code is Fortran.
Now for my question: Is it possible to do dynamic load balancing using a plain 1D DMDA, somehow?
Yes.
There is some mention of this for PCTELESCOPE, but I guess it only works for linear solves?
No, that is just their application.
Or could I use an index set or some other PETSc structure? Or do I need to use a 1D DMPLEX?
1D Plex and 1D DA are basically equivalent since 1D has no topology, and discretizations look mostly the same. Now that I am looking, the Plex redistribution is exposed, but the DA redistribution is not.
If the latter, how do I make a 1D DMPLEX? All the variables are stored in cell centers (collocated), so it's a completely trivial "mesh". I tried reading the DMPLEX manual, and looking at examples, but I'm having trouble penetrating the FEM lingo / abstract nonsense.
First question, do you want to create the partition yourself, or have a program do it for you? if you make it, then DA is the best bet, and we should just expose the redistribution code which is already in PCTELESCOPE, so that you can call it directly. If you want a partitioner to do it, then Plex is probably the best, In that case, you need to make a trivial PetscSection to say how many variables lie on each cell. With this info, everything else should be pretty automatic. Thanks, Matt
Best regards, Åsmund
-- What most experimenters take for granted before they begin their experiments is infinitely more interesting than any results to which their experiments lead. -- Norbert Wiener https://www.cse.buffalo.edu/~knepley/ <http://www.caam.rice.edu/~mk51/>
On 5 March 2018 at 09:29, Åsmund Ervik <[email protected]> wrote:
Hi all,
We have a code that solves the 1D multiphase Euler equations, using some very expensive thermodynamic calls in each cell in each time step. The computational time for different cells varies significantly in the spatial direction (due to different thermodynamic states), and varies slowly from timestep to timestep.
Currently the code runs in serial, but I would like to use a PETSc DM of some sort to run it in parallell. There will be no linear on nonlinear PETSc solves etc., just a distributed mesh, at least initially. The code is Fortran.
Now for my question: Is it possible to do dynamic load balancing using a plain 1D DMDA, somehow? There is some mention of this for PCTELESCOPE, but I guess it only works for linear solves? Or could I use an index set or some other PETSc structure? Or do I need to use a 1D DMPLEX?
I don't think TELESCOPE is what you want to use. TELESCOPE redistributes a DMDA from one MPI communicator to another MPI communicator with fewer ranks. I would not describe its functionality as "load balancing". Re-distribution could be interpreted as load balancing onto a different communicator, with an equal "load" associated with each point in the DMDA - but that is not what you are after. In addition, I didn't add support within TELESCOPE to re-distribute a 1D DMDA as that use-case almost never arises. For a 1D problem such as yours, I would use your favourite graph partitioner (Metis,Parmetis, Scotch) together with your cell based weighting and repartition the data yourself. This is not a very helpful comment but I'll make it anyway... If your code was in C, or C++, and you didn't want to mess around with any MPI calls at all from your application code, I think you could use the DMSWAM object pretty easily to perform the load balancing. I haven't tried this exact use-case myself, but in principal you could take the output from Metis (which tells you the rank you should move each point in the graph to) and directly shove this info into a SWARM object and then ask it to migrate your data. DMSWAM lets you define and migrate (across a communicator) any data type you like - it doesn't have to be a PetscReal, PetscScalar, you can define C structs for example. Unfortunately I didn't have the time to add Fortran support for DMSWAM at the moment. Cheers, Dave Thanks, Dave
If the latter, how do I make a 1D DMPLEX? All the variables are stored in cell centers (collocated), so it's a completely trivial "mesh". I tried reading the DMPLEX manual, and looking at examples, but I'm having trouble penetrating the FEM lingo / abstract nonsense.
Best regards, Åsmund
On Mon, Mar 5, 2018 at 8:17 AM, Dave May <[email protected]> wrote:
On 5 March 2018 at 09:29, Åsmund Ervik <[email protected]> wrote:
Hi all,
We have a code that solves the 1D multiphase Euler equations, using some very expensive thermodynamic calls in each cell in each time step. The computational time for different cells varies significantly in the spatial direction (due to different thermodynamic states), and varies slowly from timestep to timestep.
Currently the code runs in serial, but I would like to use a PETSc DM of some sort to run it in parallell. There will be no linear on nonlinear PETSc solves etc., just a distributed mesh, at least initially. The code is Fortran.
Now for my question: Is it possible to do dynamic load balancing using a plain 1D DMDA, somehow? There is some mention of this for PCTELESCOPE, but I guess it only works for linear solves? Or could I use an index set or some other PETSc structure? Or do I need to use a 1D DMPLEX?
I don't think TELESCOPE is what you want to use.
TELESCOPE redistributes a DMDA from one MPI communicator to another MPI communicator with fewer ranks. I would not describe its functionality as "load balancing". Re-distribution could be interpreted as load balancing onto a different communicator, with an equal "load" associated with each point in the DMDA - but that is not what you are after. In addition, I didn't add support within TELESCOPE to re-distribute a 1D DMDA as that use-case almost never arises.
For a 1D problem such as yours, I would use your favourite graph partitioner (Metis,Parmetis, Scotch) together with your cell based weighting and repartition the data yourself.
This is not a very helpful comment but I'll make it anyway... If your code was in C, or C++, and you didn't want to mess around with any MPI calls at all from your application code, I think you could use the DMSWAM object pretty easily to perform the load balancing. I haven't tried this exact use-case myself, but in principal you could take the output from Metis (which tells you the rank you should move each point in the graph to) and directly shove this info into a SWARM object and then ask it to migrate your data. DMSWAM lets you define and migrate (across a communicator) any data type you like - it doesn't have to be a PetscReal, PetscScalar, you can define C structs for example. Unfortunately I didn't have the time to add Fortran support for DMSWAM at the moment.
Okay, then I would say just use Plex. Step 1: You can create a 1D Plex easily with DMPlexCreateFromCellList(). Then call DMPlexDistribute(). Step 2: I would just create a PetscFE() since it defaults to P0, which is what you want. Something like ierr = PetscFECreateDefault(comm, dim, dim, user->simplex, "vel_", PETSC_DEFAULT, &fe);CHKERRQ(ierr); Step 3: Set it in your solver SNESSetDM(snes, dm) Step 4: Test the solve If everything works, then I will show you how to make or set a partition and redistribute. Thanks, Matt Cheers,
Dave
Thanks, Dave
If the latter, how do I make a 1D DMPLEX? All the variables are stored in cell centers (collocated), so it's a completely trivial "mesh". I tried reading the DMPLEX manual, and looking at examples, but I'm having trouble penetrating the FEM lingo / abstract nonsense.
Best regards, Åsmund
-- What most experimenters take for granted before they begin their experiments is infinitely more interesting than any results to which their experiments lead. -- Norbert Wiener https://www.cse.buffalo.edu/~knepley/ <http://www.caam.rice.edu/~mk51/>
Dave May <[email protected]> writes:
For a 1D problem such as yours, I would use your favourite graph partitioner (Metis,Parmetis, Scotch) together with your cell based weighting and repartition the data yourself.
That's overkill in 1D. You can MPI_Allreduce(SUM) and MPI_Scan(SUM) the weights, then find the transition indices in each subdomain. It'll be cheaper, more intuitive/deterministic, and avoid the extra library dependency. Of course if you think you may want to move to multiple dimensions, it would make sense to consider DMPlex or DMForest.
As Jed suggests, computing the (re)partitioning is straightforward in my 1D case. We're not planning to move this to multiple dimensions (we have another type of solver for that). So if it's possible to expose the repartitioning code for DAs, I'd be very happy to go this route. Is it a lot of work to do this? I have another question on a similar-but-different problem for 3D, but I'll write a separate mail on it. Best regards, Åsmund
-----Original Message----- From: Jed Brown [mailto:[email protected]] Sent: Monday, March 5, 2018 2:32 PM To: Dave May <[email protected]>; Åsmund Ervik <[email protected]> Cc: [email protected] Subject: Re: [petsc-users] Load balancing / redistributing a 1D DM
Dave May <[email protected]> writes:
For a 1D problem such as yours, I would use your favourite graph partitioner (Metis,Parmetis, Scotch) together with your cell based weighting and repartition the data yourself.
That's overkill in 1D. You can MPI_Allreduce(SUM) and MPI_Scan(SUM) the weights, then find the transition indices in each subdomain. It'll be cheaper, more intuitive/deterministic, and avoid the extra library dependency. Of course if you think you may want to move to multiple dimensions, it would make sense to consider DMPlex or DMForest.
On 5 March 2018 at 13:56, Åsmund Ervik <[email protected]> wrote:
As Jed suggests, computing the (re)partitioning is straightforward in my 1D case. We're not planning to move this to multiple dimensions (we have another type of solver for that).
So if it's possible to expose the repartitioning code for DAs, I'd be very happy to go this route. Is it a lot of work to do this?
Exposing the code for repartitioning the DA does not make much sense to me given the simplicity of the DMDA and given fact there other more general methods available in petsc. If you want to write the repartition code yourself for a DMDA, it would be straight forward to follow the pattern in Telescope and simplify it for the 1D case. Start with this file: http://www.mcs.anl.gov/petsc/petsc-current/src/ksp/pc/impls/telescope/telesc... and look at PCTelescopeSetUp_dmda() There are three parts to this function: [1] Copying the definition of the parent DMDA for the new repartitioned DMDA (PCTelescopeSetUp_dmda_repart()) [2] Defining the coordinates for the repartitioned DMDA (PCTelescopeSetUp_dmda_repart_coors()) [3] Defining the permutation which maps vectors from the original DMDA to the repartitioned DMDA (PCTelescopeSetUp_dmda_permutation_2d()) * Assuming you have the new layout defined (via Metis or MPI_Scan()), PCTelescopeSetUp_dmda_repart() would look basically the same expect you'd change the call DMDASetOwnershipRanges(ctx->dmrepart,NULL,NULL,NULL); to use an array defining the new layout of the repartitioned DMDA * PCTelescopeSetUp_dmda_repart_coors2d() is straight forward to modify for the 1D case by taking out the loop over j * PCTelescopeSetUp_dmda_permutation_2d() is also straight forward to modify for the 1D by taking out the loop over j and not using dimensionally index variables (like startI[1]) associated the j direction. The following functions support 1D and can be re-used: _DMDADetermineRankFromGlobalIJK() _DMDADetermineGlobalS0() Obviously you also wouldn't need guards like if (isActiveRank(sred->psubcomm)) { Thanks, Dave
I have another question on a similar-but-different problem for 3D, but I'll write a separate mail on it.
Best regards, Åsmund
-----Original Message----- From: Jed Brown [mailto:[email protected]] Sent: Monday, March 5, 2018 2:32 PM To: Dave May <[email protected]>; Åsmund Ervik <[email protected]> Cc: [email protected] Subject: Re: [petsc-users] Load balancing / redistributing a 1D DM
Dave May <[email protected]> writes:
For a 1D problem such as yours, I would use your favourite graph partitioner (Metis,Parmetis, Scotch) together with your cell based weighting and repartition the data yourself.
That's overkill in 1D. You can MPI_Allreduce(SUM) and MPI_Scan(SUM) the weights, then find the transition indices in each subdomain. It'll be cheaper, more intuitive/deterministic, and avoid the extra library dependency. Of course if you think you may want to move to multiple dimensions, it would make sense to consider DMPlex or DMForest.
This is a somewhat incomplete description of the steps in linear partitioning. The rest can be accomplished with PetscSF calls, but I should wrap it up in a PetscPartitioner because it's a mistake-prone operation. On March 5, 2018 8:31:42 AM EST, Jed Brown <[email protected]> wrote:
Dave May <[email protected]> writes:
For a 1D problem such as yours, I would use your favourite graph partitioner (Metis,Parmetis, Scotch) together with your cell based weighting and repartition the data yourself.
That's overkill in 1D. You can MPI_Allreduce(SUM) and MPI_Scan(SUM) the weights, then find the transition indices in each subdomain. It'll be cheaper, more intuitive/deterministic, and avoid the extra library dependency. Of course if you think you may want to move to multiple dimensions, it would make sense to consider DMPlex or DMForest.
On Mon, Mar 5, 2018 at 9:01 AM, Tobin Isaac <[email protected]> wrote:
This is a somewhat incomplete description of the steps in linear partitioning. The rest can be accomplished with PetscSF calls, but I should wrap it up in a PetscPartitioner because it's a mistake-prone operation.
Jed likes to do everything by hand because it is transparent, but then you become the maintainer. I think this is easy to do in Plex, and we maintain the code. It is less transparent, which is the tradeoff. Matt
On March 5, 2018 8:31:42 AM EST, Jed Brown <[email protected]> wrote:
Dave May <[email protected]> writes:
For a 1D problem such as yours, I would use your favourite graph partitioner (Metis,Parmetis, Scotch) together with your cell based weighting and repartition the data yourself.
That's overkill in 1D. You can MPI_Allreduce(SUM) and MPI_Scan(SUM) the weights, then find the transition indices in each subdomain. It'll be cheaper, more intuitive/deterministic, and avoid the extra library dependency. Of course if you think you may want to move to multiple dimensions, it would make sense to consider DMPlex or DMForest.
-- What most experimenters take for granted before they begin their experiments is infinitely more interesting than any results to which their experiments lead. -- Norbert Wiener https://www.cse.buffalo.edu/~knepley/ <http://www.caam.rice.edu/~mk51/>
My only argument "against" using Plex is that I don't understand how to use it. Is there a simple example anywhere that shows how to set up a 1D simplical (?) mesh, and then just get/return data between vectors associated with the Plex and (local) Fortran arrays on each proc? I don't have any KSP, SNES etc. I assume such a code would go something like <Plex mesh init stuff> <Plex initial (uniform) parallel distribution> <My code's init stuff> <loop over time> <Plex equivalent of DMDAGetCorners> <Plex equivalent of DMDAVecGetArrayF90> <My code that computes things with the array, and finds weights for redistribution> <Plex equivalent of DMDAVecRestoreArrayF90> <Plex redistribution> <end loop> Regards, Åsmund
-----Original Message----- From: Matthew Knepley [mailto:[email protected]] Sent: Monday, March 5, 2018 3:08 PM To: Tobin Isaac <[email protected]> Cc: Jed Brown <[email protected]>; Dave May <[email protected]>; Åsmund Ervik <[email protected]>; [email protected] Subject: Re: [petsc-users] Load balancing / redistributing a 1D DM
On Mon, Mar 5, 2018 at 9:01 AM, Tobin Isaac <[email protected] <mailto:[email protected]> > wrote:
This is a somewhat incomplete description of the steps in linear partitioning. The rest can be accomplished with PetscSF calls, but I should wrap it up in a PetscPartitioner because it's a mistake-prone operation.
Jed likes to do everything by hand because it is transparent, but then you become the maintainer. I think this is easy to do in Plex, and we maintain the code. It is less transparent, which is the tradeoff.
Matt
On March 5, 2018 8:31:42 AM EST, Jed Brown <[email protected] <mailto:[email protected]> > wrote:
Dave May <[email protected] <mailto:[email protected]> > writes:
For a 1D problem such as yours, I would use your favourite graph partitioner (Metis,Parmetis, Scotch) together with your cell based weighting and repartition the data yourself.
That's overkill in 1D. You can MPI_Allreduce(SUM) and MPI_Scan(SUM) the weights, then find the transition indices in each subdomain. It'll be cheaper, more intuitive/deterministic, and avoid the extra library dependency. Of course if you think you may want to move to multiple dimensions, it would make sense to consider DMPlex or DMForest.
--
What most experimenters take for granted before they begin their experiments is infinitely more interesting than any results to which their experiments lead. -- Norbert Wiener
https://www.cse.buffalo.edu/~knepley/ <http://www.caam.rice.edu/~mk51/>
On Mon, Mar 5, 2018 at 9:25 AM, Åsmund Ervik <[email protected]> wrote:
My only argument "against" using Plex is that I don't understand how to use it. Is there a simple example anywhere that shows how to set up a 1D simplical (?) mesh, and then just get/return data between vectors associated with the Plex and (local) Fortran arrays on each proc? I don't have any KSP, SNES etc.
I have not done a 1D example, because there is not much call for it. However, I did give the sequence of calls in my last mail. I am killing myself getting ready for SIAM PP right now, but this is easily written when I get back. However, I am not offended if you want to do it by hand. Thanks, Matt
I assume such a code would go something like
<Plex mesh init stuff> <Plex initial (uniform) parallel distribution> <My code's init stuff> <loop over time> <Plex equivalent of DMDAGetCorners> <Plex equivalent of DMDAVecGetArrayF90> <My code that computes things with the array, and finds weights for redistribution> <Plex equivalent of DMDAVecRestoreArrayF90> <Plex redistribution> <end loop>
Regards, Åsmund
-----Original Message----- From: Matthew Knepley [mailto:[email protected]] Sent: Monday, March 5, 2018 3:08 PM To: Tobin Isaac <[email protected]> Cc: Jed Brown <[email protected]>; Dave May <[email protected]>; Åsmund Ervik <[email protected]>; [email protected] Subject: Re: [petsc-users] Load balancing / redistributing a 1D DM
On Mon, Mar 5, 2018 at 9:01 AM, Tobin Isaac <[email protected] <mailto:[email protected]> > wrote:
This is a somewhat incomplete description of the steps in linear partitioning. The rest can be accomplished with PetscSF calls, but I should wrap it up in a PetscPartitioner because it's a mistake-prone operation.
Jed likes to do everything by hand because it is transparent, but then you become the maintainer. I think this is easy to do in Plex, and we maintain the code. It is less transparent, which is the tradeoff.
Matt
On March 5, 2018 8:31:42 AM EST, Jed Brown <[email protected] <mailto:[email protected]> > wrote: >Dave May <[email protected] <mailto:[email protected]> > writes: > >> For a 1D problem such as yours, I would use your favourite graph >> partitioner (Metis,Parmetis, Scotch) together with your cell based >> weighting and repartition the data yourself. > >That's overkill in 1D. You can MPI_Allreduce(SUM) and MPI_Scan(SUM) >the >weights, then find the transition indices in each subdomain. It'll be >cheaper, more intuitive/deterministic, and avoid the extra library >dependency. Of course if you think you may want to move to multiple >dimensions, it would make sense to consider DMPlex or DMForest.
--
What most experimenters take for granted before they begin their experiments is infinitely more interesting than any results to which their experiments lead. -- Norbert Wiener
https://www.cse.buffalo.edu/~knepley/ <http://www.caam.rice.edu/~mk51/>
-- What most experimenters take for granted before they begin their experiments is infinitely more interesting than any results to which their experiments lead. -- Norbert Wiener https://www.cse.buffalo.edu/~knepley/ <http://www.caam.rice.edu/~mk51/>
Matthew Knepley <[email protected]> writes:
On Mon, Mar 5, 2018 at 9:01 AM, Tobin Isaac <[email protected]> wrote:
This is a somewhat incomplete description of the steps in linear partitioning. The rest can be accomplished with PetscSF calls, but I should wrap it up in a PetscPartitioner because it's a mistake-prone operation.
Jed likes to do everything by hand because it is transparent, but then you become the maintainer. I think this is easy to do in Plex, and we maintain the code. It is less transparent, which is the tradeoff.
DMDA gives you direct indexing of neighbors, second neighbors, etc. DMPlex doesn't ensure that, though you could configure a DMPlex to sort vertices according to a particular convention. I don't know whether that convention would be preserved on repartitioning/redistribution. With your very expensive material models, indirect indexing wouldn't be a performance issue, but still may impact readability.
Hmm, there's many elements to consider here. Learning to use Plex might be a better use of my time than setting up and maintaining a custom DMDA repartitioning. But DMDAs are a more natural fit to what I want to do... However, I'm not in a huge rush to do this immediately. Can I ping you back some time next week, Matt, to ask more about details on how to use Plex for this case? (e.g. what is the Plex equivalent of DMDAVecGetArrayF90?) Enjoy Japan. Regards, Åsmund
-----Original Message----- From: Jed Brown [mailto:[email protected]] Sent: Monday, March 5, 2018 3:48 PM To: Matthew Knepley <[email protected]>; Tobin Isaac <[email protected]> Cc: Dave May <[email protected]>; Åsmund Ervik <[email protected]>; [email protected] Subject: Re: [petsc-users] Load balancing / redistributing a 1D DM
Matthew Knepley <[email protected]> writes:
On Mon, Mar 5, 2018 at 9:01 AM, Tobin Isaac <[email protected]> wrote:
This is a somewhat incomplete description of the steps in linear partitioning. The rest can be accomplished with PetscSF calls, but I should wrap it up in a PetscPartitioner because it's a mistake-prone operation.
Jed likes to do everything by hand because it is transparent, but then you become the maintainer. I think this is easy to do in Plex, and we maintain the code. It is less transparent, which is the tradeoff.
DMDA gives you direct indexing of neighbors, second neighbors, etc. DMPlex doesn't ensure that, though you could configure a DMPlex to sort vertices according to a particular convention. I don't know whether that convention would be preserved on repartitioning/redistribution.
With your very expensive material models, indirect indexing wouldn't be a performance issue, but still may impact readability.
On Mon, Mar 5, 2018 at 9:55 AM, Åsmund Ervik <[email protected]> wrote:
Hmm, there's many elements to consider here. Learning to use Plex might be a better use of my time than setting up and maintaining a custom DMDA repartitioning. But DMDAs are a more natural fit to what I want to do...
However, I'm not in a huge rush to do this immediately. Can I ping you back some time next week, Matt, to ask more about details on how to use Plex for this case? (e.g. what is the Plex equivalent of DMDAVecGetArrayF90?) Enjoy Japan.
Yep. Jed is correct that the kind of adjacency in DA is quite unnatural in Plex. Things could be done to make this better, but they are not being done now. However, this is not the case in 1D, where you can easily get neighbors and 2nd neighbors in the right order. We can talk about it after SIAM PP. Thanks, Matt
Regards, Åsmund
-----Original Message----- From: Jed Brown [mailto:[email protected]] Sent: Monday, March 5, 2018 3:48 PM To: Matthew Knepley <[email protected]>; Tobin Isaac <[email protected]> Cc: Dave May <[email protected]>; Åsmund Ervik <[email protected]>; [email protected] Subject: Re: [petsc-users] Load balancing / redistributing a 1D DM
Matthew Knepley <[email protected]> writes:
On Mon, Mar 5, 2018 at 9:01 AM, Tobin Isaac <[email protected]> wrote:
This is a somewhat incomplete description of the steps in linear partitioning. The rest can be accomplished with PetscSF calls, but I should wrap it up in a PetscPartitioner because it's a mistake-prone operation.
Jed likes to do everything by hand because it is transparent, but then you become the maintainer. I think this is easy to do in Plex, and we maintain the code. It is less transparent, which is the tradeoff.
DMDA gives you direct indexing of neighbors, second neighbors, etc. DMPlex doesn't ensure that, though you could configure a DMPlex to sort vertices according to a particular convention. I don't know whether that convention would be preserved on repartitioning/redistribution.
With your very expensive material models, indirect indexing wouldn't be a performance issue, but still may impact readability.
-- What most experimenters take for granted before they begin their experiments is infinitely more interesting than any results to which their experiments lead. -- Norbert Wiener https://www.cse.buffalo.edu/~knepley/ <http://www.caam.rice.edu/~mk51/>
participants (5)
-
Dave May -
Jed Brown -
Matthew Knepley -
Tobin Isaac -
Åsmund Ervik